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
This commit is contained in:
@@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user