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
This commit is contained in:
Fabian Kozynski
2021-07-15 15:04:53 -04:00
parent 1d2cbb6f50
commit 95a0a7ffa4
2 changed files with 24 additions and 4 deletions

View File

@@ -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);
}

View File

@@ -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");