From 95a0a7ffa4391d4156791ef176c5a18ba8d96e72 Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Thu, 15 Jul 2021 15:04:53 -0400 Subject: [PATCH] Add guards around unbind Also, make sure that mIsBound is in the correct state and clean up after death. Test: atest TileServiceTest for the leaks Test: atest TileLifecycleManagerTest Fixes: 183807631 Change-Id: I8fa2b746d9ba273bcbef088e4ca4ba50a317128a --- .../qs/external/TileLifecycleManager.java | 26 ++++++++++++++++--- .../qs/external/TileLifecycleManagerTest.java | 2 +- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java index 1d791f5d632c5..d262412d5182f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java @@ -40,6 +40,7 @@ import androidx.annotation.VisibleForTesting; import com.android.systemui.broadcast.BroadcastDispatcher; +import java.util.NoSuchElementException; import java.util.Objects; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; @@ -204,9 +205,14 @@ public class TileLifecycleManager extends BroadcastReceiver implements if (DEBUG) Log.d(TAG, "Unbinding service " + mIntent + " " + mUser); // Give it another chance next time it needs to be bound, out of kindness. mBindTryCount = 0; - mWrapper = null; + freeWrapper(); if (mIsBound) { - mContext.unbindService(this); + try { + mContext.unbindService(this); + } catch (Exception e) { + Log.e(TAG, "Failed to unbind service " + + mIntent.getComponent().flattenToShortString(), e); + } mIsBound = false; } } @@ -290,7 +296,9 @@ public class TileLifecycleManager extends BroadcastReceiver implements private void handleDeath() { if (mWrapper == null) return; - mWrapper = null; + freeWrapper(); + // Clearly not bound anymore + mIsBound = false; if (!mBound) return; if (DEBUG) Log.d(TAG, "handleDeath"); if (checkComponentState()) { @@ -472,6 +480,18 @@ public class TileLifecycleManager extends BroadcastReceiver implements return mToken; } + private void freeWrapper() { + if (mWrapper != null) { + try { + mWrapper.asBinder().unlinkToDeath(this, 0); + } catch (NoSuchElementException e) { + Log.w(TAG, "Trying to unlink not linked recipient for component" + + mIntent.getComponent().flattenToShortString()); + } + mWrapper = null; + } + } + public interface TileChangeListener { void onTileChanged(ComponentName tile); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java index 42fd288d94ee2..0a428654f14a3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java @@ -77,10 +77,10 @@ public class TileLifecycleManagerTest extends SysuiTestCase { // Stub.asInterface will just return itself. when(mMockTileService.queryLocalInterface(anyString())).thenReturn(mMockTileService); + when(mMockTileService.asBinder()).thenReturn(mMockTileService); mContext.addMockService(mTileServiceComponentName, mMockTileService); - mTileServiceIntent = new Intent().setComponent(mTileServiceComponentName); mUser = new UserHandle(UserHandle.myUserId()); mThread = new HandlerThread("TestThread");