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
This commit is contained in:
Remi NGUYEN VAN 2024-08-08 17:45:26 +09:00
commit 151be34424
2 changed files with 36 additions and 29 deletions

View file

@ -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<Intent> callback;
final String mTag;
final AtomicInteger mAtomicGenerationNumber;
final Consumer<Intent> 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<Intent> callback) {
this.tag = tag;
this.atomicGenerationNumber = atomicGenerationNumber;
this.callback = callback;
generationNumber = atomicGenerationNumber.incrementAndGet();
Receiver(String tag, AtomicInteger atomicGenerationNumber, Consumer<Intent> 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);
});
}
}
}

View file

@ -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