From 151be34424107174cbe94d5d780f1fdb7fece61b Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 8 Aug 2024 17:45:26 +0900 Subject: [PATCH] Do not block broadcast on handler processing Instead of blocking the broadcast until onReceive returns on the handler, only post in onReceive. This should make no difference for the only user, the mCarrierConfigChange listener in Tethering.java, as the callback still runs on the handler. Bug: 349919195 Test: atest Change-Id: Ie8ce7afbe905b4c6972b3aabda2d7792c96eda6c --- .../util/VersionedBroadcastListener.java | 41 +++++++++++-------- .../util/VersionedBroadcastListenerTest.java | 22 +++++----- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/Tethering/src/com/android/networkstack/tethering/util/VersionedBroadcastListener.java b/Tethering/src/com/android/networkstack/tethering/util/VersionedBroadcastListener.java index c9e75c0642..5eb155152b 100644 --- a/Tethering/src/com/android/networkstack/tethering/util/VersionedBroadcastListener.java +++ b/Tethering/src/com/android/networkstack/tethering/util/VersionedBroadcastListener.java @@ -62,8 +62,8 @@ public class VersionedBroadcastListener { if (DBG) Log.d(mTag, "startListening"); if (mReceiver != null) return; - mReceiver = new Receiver(mTag, mGenerationNumber, mCallback); - mContext.registerReceiver(mReceiver, mFilter, null, mHandler); + mReceiver = new Receiver(mTag, mGenerationNumber, mCallback, mHandler); + mContext.registerReceiver(mReceiver, mFilter); } /** Stop listening to intent broadcast. */ @@ -77,30 +77,35 @@ public class VersionedBroadcastListener { } private static class Receiver extends BroadcastReceiver { - public final String tag; - public final AtomicInteger atomicGenerationNumber; - public final Consumer callback; + final String mTag; + final AtomicInteger mAtomicGenerationNumber; + final Consumer mCallback; // Used to verify this receiver is still current. - public final int generationNumber; + final int mGenerationNumber; + private final Handler mHandler; - Receiver(String tag, AtomicInteger atomicGenerationNumber, Consumer callback) { - this.tag = tag; - this.atomicGenerationNumber = atomicGenerationNumber; - this.callback = callback; - generationNumber = atomicGenerationNumber.incrementAndGet(); + Receiver(String tag, AtomicInteger atomicGenerationNumber, Consumer callback, + Handler handler) { + mTag = tag; + mAtomicGenerationNumber = atomicGenerationNumber; + mCallback = callback; + mGenerationNumber = atomicGenerationNumber.incrementAndGet(); + mHandler = handler; } @Override public void onReceive(Context context, Intent intent) { - final int currentGenerationNumber = atomicGenerationNumber.get(); + mHandler.post(() -> { + final int currentGenerationNumber = mAtomicGenerationNumber.get(); - if (DBG) { - Log.d(tag, "receiver generationNumber=" + generationNumber - + ", current generationNumber=" + currentGenerationNumber); - } - if (generationNumber != currentGenerationNumber) return; + if (DBG) { + Log.d(mTag, "receiver generationNumber=" + mGenerationNumber + + ", current generationNumber=" + currentGenerationNumber); + } + if (mGenerationNumber != currentGenerationNumber) return; - callback.accept(intent); + mCallback.accept(intent); + }); } } } diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/util/VersionedBroadcastListenerTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/util/VersionedBroadcastListenerTest.java index b7dc66e015..ed4f3daec9 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/util/VersionedBroadcastListenerTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/util/VersionedBroadcastListenerTest.java @@ -16,6 +16,8 @@ package com.android.networkstack.tethering.util; +import static com.android.testutils.HandlerUtils.waitForIdle; + import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.reset; @@ -23,7 +25,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Handler; -import android.os.Looper; +import android.os.HandlerThread; import android.os.UserHandle; import androidx.test.filters.SmallTest; @@ -33,7 +35,6 @@ import com.android.internal.util.test.BroadcastInterceptingContext; import org.junit.After; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -44,9 +45,11 @@ import org.mockito.MockitoAnnotations; public class VersionedBroadcastListenerTest { private static final String TAG = VersionedBroadcastListenerTest.class.getSimpleName(); private static final String ACTION_TEST = "action.test.happy.broadcasts"; + private static final long TEST_TIMEOUT_MS = 10_000L; @Mock private Context mContext; private BroadcastInterceptingContext mServiceContext; + private HandlerThread mHandlerThread; private Handler mHandler; private VersionedBroadcastListener mListener; private int mCallbackCount; @@ -61,18 +64,13 @@ public class VersionedBroadcastListenerTest { } } - @BeforeClass - public static void setUpBeforeClass() throws Exception { - if (Looper.myLooper() == null) { - Looper.prepare(); - } - } - @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); reset(mContext); + mHandlerThread = new HandlerThread(TAG); + mHandlerThread.start(); + mHandler = new Handler(mHandlerThread.getLooper()); mServiceContext = new MockContext(mContext); - mHandler = new Handler(Looper.myLooper()); mCallbackCount = 0; final IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_TEST); @@ -85,11 +83,15 @@ public class VersionedBroadcastListenerTest { mListener.stopListening(); mListener = null; } + mHandlerThread.quitSafely(); + mHandlerThread.join(TEST_TIMEOUT_MS); } private void sendBroadcast() { final Intent intent = new Intent(ACTION_TEST); mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); + // Sending the broadcast is synchronous, but the receiver just posts on the handler + waitForIdle(mHandler, TEST_TIMEOUT_MS); } @Test