[nearby] Unregister broadcast listener in death
Fix: 280377682
Test: unit test
Ignore-AOSP-First: nearby_not_in_aosp_yet
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:691adc8cdd1cca9077740ce06246ce347867d757)
Merged-In: I1d632cb150ae30808cbf3343869534111e3dde12
Change-Id: I1d632cb150ae30808cbf3343869534111e3dde12
diff --git a/nearby/service/java/com/android/server/nearby/managers/BroadcastProviderManager.java b/nearby/service/java/com/android/server/nearby/managers/BroadcastProviderManager.java
index 024bff8..d95032c 100644
--- a/nearby/service/java/com/android/server/nearby/managers/BroadcastProviderManager.java
+++ b/nearby/service/java/com/android/server/nearby/managers/BroadcastProviderManager.java
@@ -22,6 +22,7 @@
import android.nearby.BroadcastRequest;
import android.nearby.IBroadcastListener;
import android.nearby.PresenceBroadcastRequest;
+import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
@@ -49,6 +50,10 @@
private final NearbyConfiguration mNearbyConfiguration;
private IBroadcastListener mBroadcastListener;
+ // Used with mBroadcastListener. Now we only support single client, for multi clients, a map
+ // between live binder to the information over the binder is needed.
+ // TODO: Finish multi-client logic for broadcast.
+ private BroadcastListenerDeathRecipient mDeathRecipient;
public BroadcastProviderManager(Context context, Injector injector) {
this(ForegroundThread.getExecutor(),
@@ -62,6 +67,7 @@
mLock = new Object();
mNearbyConfiguration = new NearbyConfiguration();
mBroadcastListener = null;
+ mDeathRecipient = null;
}
/**
@@ -70,6 +76,9 @@
public void startBroadcast(BroadcastRequest broadcastRequest, IBroadcastListener listener) {
synchronized (mLock) {
mExecutor.execute(() -> {
+ if (listener == null) {
+ return;
+ }
if (!mNearbyConfiguration.isTestAppSupported()) {
NearbyConfiguration configuration = new NearbyConfiguration();
if (!configuration.isPresenceBroadcastLegacyEnabled()) {
@@ -89,7 +98,17 @@
reportBroadcastStatus(listener, BroadcastCallback.STATUS_FAILURE);
return;
}
+ BroadcastListenerDeathRecipient deathRecipient =
+ new BroadcastListenerDeathRecipient(listener);
+ try {
+ listener.asBinder().linkToDeath(deathRecipient, 0);
+ } catch (RemoteException e) {
+ // This binder has already died, so call the DeathRecipient as if we had
+ // called linkToDeath in time.
+ deathRecipient.binderDied();
+ }
mBroadcastListener = listener;
+ mDeathRecipient = deathRecipient;
mBleBroadcastProvider.start(presenceBroadcastRequest.getVersion(),
advertisement.toBytes(), this);
});
@@ -113,13 +132,19 @@
*/
public void stopBroadcast(IBroadcastListener listener) {
synchronized (mLock) {
- if (!mNearbyConfiguration.isTestAppSupported()
- && !mNearbyConfiguration.isPresenceBroadcastLegacyEnabled()) {
- reportBroadcastStatus(listener, BroadcastCallback.STATUS_FAILURE);
- return;
+ if (listener != null) {
+ if (!mNearbyConfiguration.isTestAppSupported()
+ && !mNearbyConfiguration.isPresenceBroadcastLegacyEnabled()) {
+ reportBroadcastStatus(listener, BroadcastCallback.STATUS_FAILURE);
+ return;
+ }
+ if (mDeathRecipient != null) {
+ listener.asBinder().unlinkToDeath(mDeathRecipient, 0);
+ }
}
mBroadcastListener = null;
- mExecutor.execute(() -> mBleBroadcastProvider.stop());
+ mDeathRecipient = null;
+ mExecutor.execute(mBleBroadcastProvider::stop);
}
}
@@ -142,4 +167,21 @@
Log.e(TAG, "remote exception when reporting status");
}
}
+
+ /**
+ * Class to make listener unregister after the binder is dead.
+ */
+ public class BroadcastListenerDeathRecipient implements IBinder.DeathRecipient {
+ public IBroadcastListener mListener;
+
+ BroadcastListenerDeathRecipient(IBroadcastListener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public void binderDied() {
+ Log.d(TAG, "Binder is dead - stop broadcast listener");
+ stopBroadcast(mListener);
+ }
+ }
}
diff --git a/nearby/tests/unit/src/com/android/server/nearby/managers/BroadcastProviderManagerTest.java b/nearby/tests/unit/src/com/android/server/nearby/managers/BroadcastProviderManagerTest.java
index bc38210..47133f4 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/managers/BroadcastProviderManagerTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/managers/BroadcastProviderManagerTest.java
@@ -25,6 +25,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.UiAutomation;
import android.content.Context;
@@ -34,6 +35,7 @@
import android.nearby.PresenceBroadcastRequest;
import android.nearby.PresenceCredential;
import android.nearby.PrivateCredential;
+import android.os.IBinder;
import android.provider.DeviceConfig;
import androidx.test.core.app.ApplicationProvider;
@@ -74,6 +76,8 @@
IBroadcastListener mBroadcastListener;
@Mock
BleBroadcastProvider mBleBroadcastProvider;
+ @Mock
+ IBinder mBinder;
private Context mContext;
private BroadcastProviderManager mBroadcastProviderManager;
private BroadcastRequest mBroadcastRequest;
@@ -82,9 +86,12 @@
@Before
public void setUp() {
+ when(mBroadcastListener.asBinder()).thenReturn(mBinder);
mUiAutomation.adoptShellPermissionIdentity(WRITE_DEVICE_CONFIG, READ_DEVICE_CONFIG);
DeviceConfig.setProperty(
NAMESPACE, NEARBY_ENABLE_PRESENCE_BROADCAST_LEGACY, "true", false);
+ DeviceConfig.setProperty(
+ NAMESPACE, NEARBY_SUPPORT_TEST_APP, "true", false);
mContext = ApplicationProvider.getApplicationContext();
mBroadcastProviderManager = new BroadcastProviderManager(
@@ -104,15 +111,18 @@
}
@Test
- public void testStartAdvertising() {
+ public void testStartAdvertising() throws Exception {
mBroadcastProviderManager.startBroadcast(mBroadcastRequest, mBroadcastListener);
verify(mBleBroadcastProvider).start(eq(BroadcastRequest.PRESENCE_VERSION_V0),
any(byte[].class), any(BleBroadcastProvider.BroadcastListener.class));
+ verify(mBinder).linkToDeath(any(), eq(0));
}
@Test
public void testStopAdvertising() {
+ mBroadcastProviderManager.startBroadcast(mBroadcastRequest, mBroadcastListener);
mBroadcastProviderManager.stopBroadcast(mBroadcastListener);
+ verify(mBinder).unlinkToDeath(any(), eq(0));
}
@Test