summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Fabián Kozynski <kozynski@google.com> 2023-03-28 15:30:34 -0400
committer Fabián Kozynski <kozynski@google.com> 2023-03-29 09:21:13 -0400
commitc4ef08411d04159fc0bc472c2037fddd1360c81c (patch)
tree9b353652751577458fe6289b68665b13cf5fa8b4
parent25be63a7bc27c53be1de2c67bf4bc9ea228e73f5 (diff)
Store tiles by component name and user
This way, when the user changes, the old tile is not just replaced in the map, instead we keep it until it can be freed. This solves an issue of active tiles not being able to be set into listening state after user changing. Test: atest TileServices Test: manual, using sample tile service app Fixes: 243902636 Change-Id: I57d08aec5c0b40f09f5bd763d63068aaea7ba450
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java40
2 files changed, 51 insertions, 7 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index 5e4f53181706..42536fef17aa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -30,6 +30,7 @@ import android.service.quicksettings.IQSService;
import android.service.quicksettings.Tile;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.SparseArrayMap;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -64,7 +65,7 @@ public class TileServices extends IQSService.Stub {
private static final String TAG = "TileServices";
private final ArrayMap<CustomTile, TileServiceManager> mServices = new ArrayMap<>();
- private final ArrayMap<ComponentName, CustomTile> mTiles = new ArrayMap<>();
+ private final SparseArrayMap<ComponentName, CustomTile> mTiles = new SparseArrayMap<>();
private final ArrayMap<IBinder, CustomTile> mTokenMap = new ArrayMap<>();
private final Context mContext;
private final Handler mMainHandler;
@@ -112,10 +113,11 @@ public class TileServices extends IQSService.Stub {
public TileServiceManager getTileWrapper(CustomTile tile) {
ComponentName component = tile.getComponent();
+ int userId = tile.getUser();
TileServiceManager service = onCreateTileService(component, mBroadcastDispatcher);
synchronized (mServices) {
mServices.put(tile, service);
- mTiles.put(component, tile);
+ mTiles.add(userId, component, tile);
mTokenMap.put(service.getToken(), tile);
}
// Makes sure binding only happens after the maps have been populated
@@ -135,7 +137,7 @@ public class TileServices extends IQSService.Stub {
service.handleDestroy();
mServices.remove(tile);
mTokenMap.remove(service.getToken());
- mTiles.remove(tile.getComponent());
+ mTiles.delete(tile.getUser(), tile.getComponent());
final String slot = getStatusBarIconSlotName(tile.getComponent());
mMainHandler.post(() -> mStatusBarIconController.removeIconForTile(slot));
}
@@ -188,9 +190,10 @@ public class TileServices extends IQSService.Stub {
private void requestListening(ComponentName component) {
synchronized (mServices) {
- CustomTile customTile = getTileForComponent(component);
+ int userId = mUserTracker.getUserId();
+ CustomTile customTile = getTileForUserAndComponent(userId, component);
if (customTile == null) {
- Log.d("TileServices", "Couldn't find tile for " + component);
+ Log.d(TAG, "Couldn't find tile for " + component + "(" + userId + ")");
return;
}
TileServiceManager service = mServices.get(customTile);
@@ -362,9 +365,9 @@ public class TileServices extends IQSService.Stub {
}
@Nullable
- private CustomTile getTileForComponent(ComponentName component) {
+ private CustomTile getTileForUserAndComponent(int userId, ComponentName component) {
synchronized (mServices) {
- return mTiles.get(component);
+ return mTiles.get(userId, component);
}
}
@@ -395,4 +398,5 @@ public class TileServices extends IQSService.Stub {
return -Integer.compare(left.getBindPriority(), right.getBindPriority());
}
};
+
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index 7e052bfa15d2..fb9336734d99 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -54,6 +54,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -95,6 +96,8 @@ public class TileServicesTest extends SysuiTestCase {
private QSHost mQSHost;
@Mock
private PanelInteractor mPanelInteractor;
+ @Captor
+ private ArgumentCaptor<CommandQueue.Callbacks> mCallbacksArgumentCaptor;
@Before
public void setUp() throws Exception {
@@ -251,6 +254,41 @@ public class TileServicesTest extends SysuiTestCase {
verify(mPanelInteractor).forceCollapsePanels();
}
+ @Test
+ public void tileFreedForCorrectUser() throws RemoteException {
+ verify(mCommandQueue).addCallback(mCallbacksArgumentCaptor.capture());
+
+ ComponentName componentName = new ComponentName("pkg", "cls");
+ CustomTile tileUser0 = mock(CustomTile.class);
+ CustomTile tileUser1 = mock(CustomTile.class);
+
+ when(tileUser0.getComponent()).thenReturn(componentName);
+ when(tileUser1.getComponent()).thenReturn(componentName);
+ when(tileUser0.getUser()).thenReturn(0);
+ when(tileUser1.getUser()).thenReturn(1);
+
+ // Create a tile for user 0
+ TileServiceManager manager0 = mTileService.getTileWrapper(tileUser0);
+ when(manager0.isActiveTile()).thenReturn(true);
+ // Then create a tile for user 1
+ TileServiceManager manager1 = mTileService.getTileWrapper(tileUser1);
+ when(manager1.isActiveTile()).thenReturn(true);
+
+ // When the tile for user 0 gets freed
+ mTileService.freeService(tileUser0, manager0);
+ // and the user is 1
+ when(mUserTracker.getUserId()).thenReturn(1);
+
+ // a call to requestListeningState
+ mCallbacksArgumentCaptor.getValue().requestTileServiceListeningState(componentName);
+ mTestableLooper.processAllMessages();
+
+ // will call in the correct tile
+ verify(manager1).setBindRequested(true);
+ // and set it to listening
+ verify(manager1.getTileService()).onStartListening();
+ }
+
private class TestTileServices extends TileServices {
TestTileServices(QSHost host, Provider<Handler> handlerProvider,
BroadcastDispatcher broadcastDispatcher, UserTracker userTracker,
@@ -268,6 +306,8 @@ public class TileServicesTest extends SysuiTestCase {
when(manager.isLifecycleStarted()).thenReturn(true);
Binder b = new Binder();
when(manager.getToken()).thenReturn(b);
+ IQSTileService service = mock(IQSTileService.class);
+ when(manager.getTileService()).thenReturn(service);
return manager;
}
}