Loading packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java +11 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading @@ -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)); } Loading Loading @@ -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); Loading Loading @@ -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); } } Loading Loading @@ -395,4 +398,5 @@ public class TileServices extends IQSService.Stub { return -Integer.compare(left.getBindPriority(), right.getBindPriority()); } }; } packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java +40 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 { Loading Loading @@ -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, Loading @@ -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; } } Loading Loading
packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java +11 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading @@ -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)); } Loading Loading @@ -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); Loading Loading @@ -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); } } Loading Loading @@ -395,4 +398,5 @@ public class TileServices extends IQSService.Stub { return -Integer.compare(left.getBindPriority(), right.getBindPriority()); } }; }
packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java +40 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 { Loading Loading @@ -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, Loading @@ -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; } } Loading