diff options
9 files changed, 261 insertions, 69 deletions
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index c6e36a36701b..89854bbab3e8 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -844,6 +844,24 @@ public class StatusBarManager { } /** + * Sets an active {@link android.service.quicksettings.TileService} to listening state + * + * The {@code componentName}'s package must match the calling package. + * + * @param componentName the tile to set into listening state + * @see android.service.quicksettings.TileService#requestListeningState + * @hide + */ + public void requestTileServiceListeningState(@NonNull ComponentName componentName) { + Objects.requireNonNull(componentName); + try { + getService().requestTileServiceListeningState(componentName, mContext.getUserId()); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } + } + + /** * Request to the user to add a {@link android.service.quicksettings.TileService} * to the set of current QS tiles. * <p> diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java index b507328d21a1..0829d2813c83 100644 --- a/core/java/android/service/quicksettings/TileService.java +++ b/core/java/android/service/quicksettings/TileService.java @@ -15,18 +15,19 @@ */ package android.service.quicksettings; -import android.Manifest; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.annotation.TestApi; import android.app.Dialog; import android.app.Service; +import android.app.StatusBarManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.graphics.drawable.Icon; +import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -147,13 +148,6 @@ public class TileService extends Service { "android.service.quicksettings.TOGGLEABLE_TILE"; /** - * Used to notify SysUI that Listening has be requested. - * @hide - */ - public static final String ACTION_REQUEST_LISTENING = - "android.service.quicksettings.action.REQUEST_LISTENING"; - - /** * @hide */ public static final String EXTRA_SERVICE = "service"; @@ -482,14 +476,24 @@ public class TileService extends Service { * * This method is only applicable to tiles that have {@link #META_DATA_ACTIVE_TILE} defined * as true on their TileService Manifest declaration, and will do nothing otherwise. + * + * For apps targeting {@link Build.VERSION_CODES#TIRAMISU} or later, this call may throw + * the following exceptions if the request is not valid: + * <ul> + * <li> {@link NullPointerException} if {@code component} is {@code null}.</li> + * <li> {@link SecurityException} if the package of {@code component} does not match + * the calling package or if the calling user cannot act on behalf of the user from the + * {@code context}.</li> + * <li> {@link IllegalArgumentException} if the user of the {@code context} is not the + * current user.</li> + * </ul> */ public static final void requestListeningState(Context context, ComponentName component) { - final ComponentName sysuiComponent = ComponentName.unflattenFromString( - context.getResources().getString( - com.android.internal.R.string.config_systemUIServiceComponent)); - Intent intent = new Intent(ACTION_REQUEST_LISTENING); - intent.putExtra(Intent.EXTRA_COMPONENT_NAME, component); - intent.setPackage(sysuiComponent.getPackageName()); - context.sendBroadcast(intent, Manifest.permission.BIND_QUICK_SETTINGS_TILE); + StatusBarManager sbm = context.getSystemService(StatusBarManager.class); + if (sbm == null) { + Log.e(TAG, "No StatusBarManager service found"); + return; + } + sbm.requestTileServiceListeningState(component); } } diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index d629d66d1c31..089179dbba27 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -297,6 +297,11 @@ oneway interface IStatusBar */ void runGcForTest(); + /** + * Send a request to SystemUI to put a given active tile in listening state + */ + void requestTileServiceListeningState(in ComponentName componentName); + void requestAddTile(in ComponentName componentName, in CharSequence appName, in CharSequence label, in Icon icon, in IAddTileResultCallback callback); void cancelRequestAddTile(in String packageName); diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index 9163b6d6215e..3bfd21440f9b 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -171,6 +171,11 @@ interface IStatusBarService */ void suppressAmbientDisplay(boolean suppress); + /** + * Send a request to SystemUI to put a given active tile in listening state + */ + void requestTileServiceListeningState(in ComponentName componentName, int userId); + void requestAddTile(in ComponentName componentName, in CharSequence label, in Icon icon, int userId, in IAddTileResultCallback callback); void cancelRequestAddTile(in String packageName); 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 5bcf9f8a0534..4cacbbacec2f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java @@ -15,11 +15,8 @@ */ package com.android.systemui.qs.external; -import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.graphics.drawable.Icon; @@ -30,10 +27,10 @@ import android.os.RemoteException; import android.os.UserHandle; import android.service.quicksettings.IQSService; import android.service.quicksettings.Tile; -import android.service.quicksettings.TileService; import android.util.ArrayMap; import android.util.Log; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.statusbar.StatusBarIcon; @@ -41,6 +38,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.qs.QSTileHost; import com.android.systemui.settings.UserTracker; +import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -69,6 +67,7 @@ public class TileServices extends IQSService.Stub { private final QSTileHost mHost; private final KeyguardStateController mKeyguardStateController; private final BroadcastDispatcher mBroadcastDispatcher; + private final CommandQueue mCommandQueue; private final UserTracker mUserTracker; private int mMaxBound = DEFAULT_MAX_BOUND; @@ -79,7 +78,8 @@ public class TileServices extends IQSService.Stub { @Main Provider<Handler> handlerProvider, BroadcastDispatcher broadcastDispatcher, UserTracker userTracker, - KeyguardStateController keyguardStateController) { + KeyguardStateController keyguardStateController, + CommandQueue commandQueue) { mHost = host; mKeyguardStateController = keyguardStateController; mContext = mHost.getContext(); @@ -87,12 +87,8 @@ public class TileServices extends IQSService.Stub { mHandlerProvider = handlerProvider; mMainHandler = mHandlerProvider.get(); mUserTracker = userTracker; - mBroadcastDispatcher.registerReceiver( - mRequestListeningReceiver, - new IntentFilter(TileService.ACTION_REQUEST_LISTENING), - null, // Use the default Executor - UserHandle.ALL - ); + mCommandQueue = commandQueue; + mCommandQueue.addCallback(mRequestListeningCallback); } public Context getContext() { @@ -354,21 +350,14 @@ public class TileServices extends IQSService.Stub { public void destroy() { synchronized (mServices) { mServices.values().forEach(service -> service.handleDestroy()); - mBroadcastDispatcher.unregisterReceiver(mRequestListeningReceiver); } + mCommandQueue.removeCallback(mRequestListeningCallback); } - private final BroadcastReceiver mRequestListeningReceiver = new BroadcastReceiver() { + private final CommandQueue.Callbacks mRequestListeningCallback = new CommandQueue.Callbacks() { @Override - public void onReceive(Context context, Intent intent) { - if (TileService.ACTION_REQUEST_LISTENING.equals(intent.getAction())) { - try { - ComponentName c = intent.getParcelableExtra(Intent.EXTRA_COMPONENT_NAME); - requestListening(c); - } catch (ClassCastException ex) { - Log.e(TAG, "Bad component name", ex); - } - } + public void requestTileServiceListeningState(@NonNull ComponentName componentName) { + mMainHandler.post(() -> requestListening(componentName)); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 5932a64c1c71..d9a98b165795 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -163,6 +163,7 @@ public class CommandQueue extends IStatusBar.Stub implements private static final int MSG_MEDIA_TRANSFER_RECEIVER_STATE = 65 << MSG_SHIFT; private static final int MSG_REGISTER_NEARBY_MEDIA_DEVICE_PROVIDER = 66 << MSG_SHIFT; private static final int MSG_UNREGISTER_NEARBY_MEDIA_DEVICE_PROVIDER = 67 << MSG_SHIFT; + private static final int MSG_TILE_SERVICE_REQUEST_LISTENING_STATE = 68 << MSG_SHIFT; public static final int FLAG_EXCLUDE_NONE = 0; public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0; @@ -433,6 +434,11 @@ public class CommandQueue extends IStatusBar.Stub implements default void setNavigationBarLumaSamplingEnabled(int displayId, boolean enable) {} /** + * @see IStatusBar#requestTileServiceListeningState + */ + default void requestTileServiceListeningState(@NonNull ComponentName componentName) {} + + /** * @see IStatusBar#requestAddTile */ default void requestAddTile( @@ -1190,6 +1196,12 @@ public class CommandQueue extends IStatusBar.Stub implements } @Override + public void requestTileServiceListeningState(@NonNull ComponentName componentName) { + mHandler.obtainMessage(MSG_TILE_SERVICE_REQUEST_LISTENING_STATE, componentName) + .sendToTarget(); + } + + @Override public void requestAddTile( @NonNull ComponentName componentName, @NonNull CharSequence appName, @@ -1686,6 +1698,12 @@ public class CommandQueue extends IStatusBar.Stub implements mCallbacks.get(i).unregisterNearbyMediaDevicesProvider(provider); } break; + case MSG_TILE_SERVICE_REQUEST_LISTENING_STATE: + ComponentName component = (ComponentName) msg.obj; + for (int i = 0; i < mCallbacks.size(); i++) { + mCallbacks.get(i).requestTileServiceListeningState(component); + } + break; } } } 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 e75780166f05..6b7e5b9335f2 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 @@ -20,20 +20,18 @@ import static junit.framework.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Intent; -import android.content.IntentFilter; import android.os.Handler; +import android.os.RemoteException; import android.os.UserHandle; -import android.service.quicksettings.TileService; +import android.service.quicksettings.IQSTileService; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -48,6 +46,7 @@ import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSFactoryImpl; import com.android.systemui.settings.UserTracker; import com.android.systemui.shared.plugins.PluginManager; +import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.phone.AutoTileManager; import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.phone.StatusBarIconController; @@ -75,12 +74,17 @@ import javax.inject.Provider; public class TileServicesTest extends SysuiTestCase { private static int NUM_FAKES = TileServices.DEFAULT_MAX_BOUND * 2; + private static final ComponentName TEST_COMPONENT = + ComponentName.unflattenFromString("pkg/.cls"); + private TileServices mTileService; private TestableLooper mTestableLooper; private ArrayList<TileServiceManager> mManagers; @Mock private BroadcastDispatcher mBroadcastDispatcher; @Mock + private CommandQueue mCommandQueue; + @Mock private StatusBarIconController mStatusBarIconController; @Mock private QSFactoryImpl mQSFactory; @@ -146,7 +150,7 @@ public class TileServicesTest extends SysuiTestCase { mTileServiceRequestControllerBuilder, mTileLifecycleManagerFactory); mTileService = new TestTileServices(host, provider, mBroadcastDispatcher, - mUserTracker, mKeyguardStateController); + mUserTracker, mKeyguardStateController, mCommandQueue); } @After @@ -157,24 +161,6 @@ public class TileServicesTest extends SysuiTestCase { } @Test - public void testActiveTileListenerRegisteredOnAllUsers() { - ArgumentCaptor<IntentFilter> captor = ArgumentCaptor.forClass(IntentFilter.class); - verify(mBroadcastDispatcher).registerReceiver(any(), captor.capture(), any(), eq( - UserHandle.ALL)); - assertTrue(captor.getValue().hasAction(TileService.ACTION_REQUEST_LISTENING)); - } - - @Test - public void testBadComponentName_doesntCrash() { - ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mBroadcastDispatcher).registerReceiver(captor.capture(), any(), any(), eq( - UserHandle.ALL)); - Intent intent = new Intent(TileService.ACTION_REQUEST_LISTENING) - .putExtra(Intent.EXTRA_COMPONENT_NAME, "abc"); - captor.getValue().onReceive(mContext, intent); - } - - @Test public void testRecalculateBindAllowance() { // Add some fake tiles. for (int i = 0; i < NUM_FAKES; i++) { @@ -230,11 +216,36 @@ public class TileServicesTest extends SysuiTestCase { } } + @Test + public void testRegisterCommand() { + verify(mCommandQueue).addCallback(any()); + } + + @Test + public void testRequestListeningStatusCommand() throws RemoteException { + ArgumentCaptor<CommandQueue.Callbacks> captor = + ArgumentCaptor.forClass(CommandQueue.Callbacks.class); + verify(mCommandQueue).addCallback(captor.capture()); + + CustomTile mockTile = mock(CustomTile.class); + when(mockTile.getComponent()).thenReturn(TEST_COMPONENT); + + TileServiceManager manager = mTileService.getTileWrapper(mockTile); + when(manager.isActiveTile()).thenReturn(true); + when(manager.getTileService()).thenReturn(mock(IQSTileService.class)); + + captor.getValue().requestTileServiceListeningState(TEST_COMPONENT); + mTestableLooper.processAllMessages(); + verify(manager).setBindRequested(true); + verify(manager.getTileService()).onStartListening(); + } + private class TestTileServices extends TileServices { TestTileServices(QSTileHost host, Provider<Handler> handlerProvider, BroadcastDispatcher broadcastDispatcher, UserTracker userTracker, - KeyguardStateController keyguardStateController) { - super(host, handlerProvider, broadcastDispatcher, userTracker, keyguardStateController); + KeyguardStateController keyguardStateController, CommandQueue commandQueue) { + super(host, handlerProvider, broadcastDispatcher, userTracker, keyguardStateController, + commandQueue); } @Override diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 59b9daf709d8..60ede3bcda4d 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -36,6 +36,7 @@ import android.app.Notification; import android.app.StatusBarManager; import android.app.compat.CompatChanges; import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledAfter; import android.compat.annotation.EnabledSince; import android.content.ComponentName; import android.content.Context; @@ -135,6 +136,17 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S) private static final long LOCK_DOWN_COLLAPSE_STATUS_BAR = 173031413L; + /** + * In apps targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or higher, calling + * {@link android.service.quicksettings.TileService#requestListeningState} will check that the + * calling package (uid) and the package of the target {@link android.content.ComponentName} + * match. It'll also make sure that the context used can take actions on behalf of the current + * user. + */ + @ChangeId + @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2) + static final long REQUEST_LISTENING_MUST_MATCH_PACKAGE = 172251878L; + private final Context mContext; private final Handler mHandler = new Handler(); @@ -1776,6 +1788,42 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } @Override + public void requestTileServiceListeningState( + @NonNull ComponentName componentName, + int userId + ) { + int callingUid = Binder.getCallingUid(); + String packageName = componentName.getPackageName(); + + boolean mustPerformChecks = CompatChanges.isChangeEnabled( + REQUEST_LISTENING_MUST_MATCH_PACKAGE, callingUid); + + if (mustPerformChecks) { + // Check calling user can act on behalf of current user + userId = mActivityManagerInternal.handleIncomingUser(Binder.getCallingPid(), callingUid, + userId, false, ActivityManagerInternal.ALLOW_NON_FULL, + "requestTileServiceListeningState", packageName); + + // Check calling uid matches package + checkCallingUidPackage(packageName, callingUid, userId); + + int currentUser = mActivityManagerInternal.getCurrentUserId(); + + // Check current user + if (userId != currentUser) { + throw new IllegalArgumentException("User " + userId + " is not the current user."); + } + } + if (mBar != null) { + try { + mBar.requestTileServiceListeningState(componentName); + } catch (RemoteException e) { + Slog.e(TAG, "requestTileServiceListeningState", e); + } + } + } + + @Override public void requestAddTile( @NonNull ComponentName componentName, @NonNull CharSequence label, diff --git a/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java index 1442f1c82d42..d76a1de1b1b0 100644 --- a/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java @@ -23,9 +23,11 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertThrows; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.anyLong; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.argThat; import static org.mockito.Mockito.eq; @@ -37,6 +39,7 @@ import static org.mockito.Mockito.when; import android.Manifest; import android.app.ActivityManagerInternal; import android.app.StatusBarManager; +import android.compat.testing.PlatformCompatChangeRule; import android.content.ComponentName; import android.content.Intent; import android.content.om.IOverlayManager; @@ -62,10 +65,13 @@ import com.android.server.LocalServices; import com.android.server.policy.GlobalActionsProvider; import com.android.server.wm.ActivityTaskManagerInternal; +import libcore.junit.util.compat.CoreCompatChangeRule; + import org.junit.Before; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.ArgumentCaptor; @@ -73,6 +79,7 @@ import org.mockito.ArgumentMatcher; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.stubbing.Answer; @RunWith(JUnit4.class) public class StatusBarManagerServiceTest { @@ -88,6 +95,9 @@ public class StatusBarManagerServiceTest { public final TestableContext mContext = new NoBroadcastContextWrapper(InstrumentationRegistry.getContext()); + @Rule + public TestRule mCompatChangeRule = new PlatformCompatChangeRule(); + @Mock private ActivityTaskManagerInternal mActivityTaskManagerInternal; @Mock @@ -127,6 +137,7 @@ public class StatusBarManagerServiceTest { when(mMockStatusBar.asBinder()).thenReturn(mMockStatusBar); when(mApplicationInfo.loadLabel(any())).thenReturn(APP_NAME); + mockHandleIncomingUser(); mStatusBarManagerService = new StatusBarManagerService(mContext); LocalServices.removeServiceForTest(StatusBarManagerInternal.class); @@ -142,6 +153,80 @@ public class StatusBarManagerServiceTest { } @Test + @CoreCompatChangeRule.EnableCompatChanges( + {StatusBarManagerService.REQUEST_LISTENING_MUST_MATCH_PACKAGE}) + public void testRequestActive_changeEnabled_OKCall() throws RemoteException { + int user = 0; + mockEverything(user); + mStatusBarManagerService.requestTileServiceListeningState(TEST_COMPONENT, user); + + verify(mMockStatusBar).requestTileServiceListeningState(TEST_COMPONENT); + } + + @Test + @CoreCompatChangeRule.EnableCompatChanges( + {StatusBarManagerService.REQUEST_LISTENING_MUST_MATCH_PACKAGE}) + public void testRequestActive_changeEnabled_differentPackage_fail() throws RemoteException { + when(mPackageManagerInternal.getPackageUid(TEST_PACKAGE, 0L, mContext.getUserId())) + .thenReturn(Binder.getCallingUid() + 1); + try { + mStatusBarManagerService.requestTileServiceListeningState(TEST_COMPONENT, 0); + fail("Should cause security exception"); + } catch (SecurityException e) { } + verify(mMockStatusBar, never()).requestTileServiceListeningState(TEST_COMPONENT); + } + + @Test + @CoreCompatChangeRule.EnableCompatChanges( + {StatusBarManagerService.REQUEST_LISTENING_MUST_MATCH_PACKAGE}) + public void testRequestActive_changeEnabled_notCurrentUser_fail() throws RemoteException { + mockUidCheck(); + int user = 0; + mockCurrentUserCheck(user); + try { + mStatusBarManagerService.requestTileServiceListeningState(TEST_COMPONENT, user + 1); + fail("Should cause illegal argument exception"); + } catch (IllegalArgumentException e) { } + + // Do not call into SystemUI + verify(mMockStatusBar, never()).requestTileServiceListeningState(TEST_COMPONENT); + } + + @Test + @CoreCompatChangeRule.DisableCompatChanges( + {StatusBarManagerService.REQUEST_LISTENING_MUST_MATCH_PACKAGE}) + public void testRequestActive_changeDisabled_pass() throws RemoteException { + int user = 0; + mockEverything(user); + mStatusBarManagerService.requestTileServiceListeningState(TEST_COMPONENT, user); + + verify(mMockStatusBar).requestTileServiceListeningState(TEST_COMPONENT); + } + + @Test + @CoreCompatChangeRule.DisableCompatChanges( + {StatusBarManagerService.REQUEST_LISTENING_MUST_MATCH_PACKAGE}) + public void testRequestActive_changeDisabled_differentPackage_pass() throws RemoteException { + when(mPackageManagerInternal.getPackageUid(TEST_PACKAGE, 0L, mContext.getUserId())) + .thenReturn(Binder.getCallingUid() + 1); + mStatusBarManagerService.requestTileServiceListeningState(TEST_COMPONENT, 0); + + verify(mMockStatusBar).requestTileServiceListeningState(TEST_COMPONENT); + } + + @Test + @CoreCompatChangeRule.DisableCompatChanges( + {StatusBarManagerService.REQUEST_LISTENING_MUST_MATCH_PACKAGE}) + public void testRequestActive_changeDisabled_notCurrentUser_pass() throws RemoteException { + mockUidCheck(); + int user = 0; + mockCurrentUserCheck(user); + mStatusBarManagerService.requestTileServiceListeningState(TEST_COMPONENT, user + 1); + + verify(mMockStatusBar).requestTileServiceListeningState(TEST_COMPONENT); + } + + @Test public void testHandleIncomingUserCalled() { int fakeUser = 17; try { @@ -252,7 +337,7 @@ public class StatusBarManagerServiceTest { mockCurrentUserCheck(user); IntentMatcher im = new IntentMatcher( new Intent(TileService.ACTION_QS_TILE).setComponent(TEST_COMPONENT)); - when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0), + when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0L), eq(user), anyInt())).thenReturn(null); Callback callback = new Callback(); @@ -272,7 +357,7 @@ public class StatusBarManagerServiceTest { IntentMatcher im = new IntentMatcher( new Intent(TileService.ACTION_QS_TILE).setComponent(TEST_COMPONENT)); - when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0), + when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0L), eq(user), anyInt())).thenReturn(r); when(mPackageManagerInternal.getComponentEnabledSetting(TEST_COMPONENT, Binder.getCallingUid(), user)).thenReturn( @@ -294,7 +379,7 @@ public class StatusBarManagerServiceTest { IntentMatcher im = new IntentMatcher( new Intent(TileService.ACTION_QS_TILE).setComponent(TEST_COMPONENT)); - when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0), + when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0L), eq(user), anyInt())).thenReturn(r); when(mPackageManagerInternal.getComponentEnabledSetting(TEST_COMPONENT, Binder.getCallingUid(), user)).thenReturn( @@ -318,7 +403,7 @@ public class StatusBarManagerServiceTest { IntentMatcher im = new IntentMatcher( new Intent(TileService.ACTION_QS_TILE).setComponent(TEST_COMPONENT)); - when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0), + when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0L), eq(user), anyInt())).thenReturn(r); when(mPackageManagerInternal.getComponentEnabledSetting(TEST_COMPONENT, Binder.getCallingUid(), user)).thenReturn( @@ -342,7 +427,7 @@ public class StatusBarManagerServiceTest { IntentMatcher im = new IntentMatcher( new Intent(TileService.ACTION_QS_TILE).setComponent(TEST_COMPONENT)); - when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0), + when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0L), eq(user), anyInt())).thenReturn(r); when(mPackageManagerInternal.getComponentEnabledSetting(TEST_COMPONENT, Binder.getCallingUid(), user)).thenReturn( @@ -641,7 +726,7 @@ public class StatusBarManagerServiceTest { } private void mockUidCheck(String packageName) { - when(mPackageManagerInternal.getPackageUid(eq(packageName), anyInt(), anyInt())) + when(mPackageManagerInternal.getPackageUid(eq(packageName), anyLong(), anyInt())) .thenReturn(Binder.getCallingUid()); } @@ -667,7 +752,7 @@ public class StatusBarManagerServiceTest { IntentMatcher im = new IntentMatcher( new Intent(TileService.ACTION_QS_TILE).setComponent(componentName)); - when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0), + when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0L), eq(user), anyInt())).thenReturn(r); when(mPackageManagerInternal.getComponentEnabledSetting(componentName, Binder.getCallingUid(), user)).thenReturn( @@ -679,6 +764,15 @@ public class StatusBarManagerServiceTest { PROCESS_STATE_TOP); } + private void mockHandleIncomingUser() { + when(mActivityManagerInternal.handleIncomingUser(anyInt(), anyInt(), anyInt(), anyBoolean(), + anyInt(), anyString(), anyString())).thenAnswer( + (Answer<Integer>) invocation -> { + return invocation.getArgument(2); // same user + } + ); + } + private void mockEverything(int user) { mockUidCheck(); mockCurrentUserCheck(user); |