diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java index d262412d5182f..e6612fe8f08b7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java @@ -329,7 +329,8 @@ public class TileLifecycleManager extends BroadcastReceiver implements filter.addDataScheme("package"); try { mPackageReceiverRegistered.set(true); - mContext.registerReceiverAsUser(this, mUser, filter, null, mHandler); + mContext.registerReceiverAsUser( + this, mUser, filter, null, mHandler, Context.RECEIVER_EXPORTED); } catch (Exception ex) { mPackageReceiverRegistered.set(false); Log.e(TAG, "Could not register package receiver", ex); diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java index 7e76e57f48026..fda755bd5c331 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java @@ -92,7 +92,7 @@ public class TileServiceManager { filter.addDataScheme("package"); Context context = mServices.getContext(); context.registerReceiverAsUser(mUninstallReceiver, userTracker.getUserHandle(), filter, - null, mHandler); + null, mHandler, Context.RECEIVER_EXPORTED); } boolean isLifecycleStarted() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java index 0a428654f14a3..f2303c26b6db8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java @@ -19,6 +19,7 @@ import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyString; @@ -27,8 +28,12 @@ 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.Context; +import android.content.ContextWrapper; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.ServiceInfo; import android.net.Uri; @@ -42,6 +47,7 @@ import android.service.quicksettings.Tile; import android.service.quicksettings.TileService; import android.test.suitebuilder.annotation.SmallTest; +import androidx.annotation.Nullable; import androidx.test.runner.AndroidJUnit4; import com.android.systemui.SysuiTestCase; @@ -69,6 +75,7 @@ public class TileLifecycleManagerTest extends SysuiTestCase { private HandlerThread mThread; private Handler mHandler; private TileLifecycleManager mStateManager; + private TestContextWrapper mWrappedContext; @Before public void setUp() throws Exception { @@ -81,12 +88,14 @@ public class TileLifecycleManagerTest extends SysuiTestCase { mContext.addMockService(mTileServiceComponentName, mMockTileService); + mWrappedContext = new TestContextWrapper(mContext); + mTileServiceIntent = new Intent().setComponent(mTileServiceComponentName); mUser = new UserHandle(UserHandle.myUserId()); mThread = new HandlerThread("TestThread"); mThread.start(); mHandler = Handler.createAsync(mThread.getLooper()); - mStateManager = new TileLifecycleManager(mHandler, mContext, + mStateManager = new TileLifecycleManager(mHandler, mWrappedContext, Mockito.mock(IQSService.class), new Tile(), mTileServiceIntent, mUser, @@ -97,6 +106,7 @@ public class TileLifecycleManagerTest extends SysuiTestCase { @After public void tearDown() throws Exception { mThread.quit(); + mStateManager.handleDestroy(); } private void setPackageEnabled(boolean enabled) throws Exception { @@ -126,6 +136,18 @@ public class TileLifecycleManagerTest extends SysuiTestCase { verifyBind(1); } + @Test + public void testPackageReceiverExported() throws Exception { + // Make sure that we register a receiver + setPackageEnabled(false); + mStateManager.setBindService(true); + IntentFilter filter = mWrappedContext.mLastIntentFilter; + assertTrue(filter.hasAction(Intent.ACTION_PACKAGE_ADDED)); + assertTrue(filter.hasAction(Intent.ACTION_PACKAGE_CHANGED)); + assertTrue(filter.hasDataScheme("package")); + assertNotEquals(0, mWrappedContext.mLastFlag & Context.RECEIVER_EXPORTED); + } + @Test public void testUnbind() { mStateManager.setBindService(true); @@ -247,4 +269,23 @@ public class TileLifecycleManagerTest extends SysuiTestCase { public void testToggleableTile() throws Exception { assertTrue(mStateManager.isToggleableTile()); } + + private static class TestContextWrapper extends ContextWrapper { + private IntentFilter mLastIntentFilter; + private int mLastFlag; + + TestContextWrapper(Context base) { + super(base); + } + + @Override + public Intent registerReceiverAsUser(@Nullable BroadcastReceiver receiver, UserHandle user, + IntentFilter filter, @Nullable String broadcastPermission, + @Nullable Handler scheduler, int flags) { + mLastIntentFilter = filter; + mLastFlag = flags; + return super.registerReceiverAsUser(receiver, user, filter, broadcastPermission, + scheduler, flags); + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java index 6a9d9fa6d5a28..573980d015a98 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java @@ -20,6 +20,9 @@ import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.os.Handler; import android.os.HandlerThread; import android.os.UserHandle; @@ -47,6 +50,7 @@ public class TileServiceManagerTest extends SysuiTestCase { private Handler mHandler; private TileServiceManager mTileServiceManager; private UserTracker mUserTracker; + private Context mMockContext; @Before public void setUp() throws Exception { @@ -58,7 +62,8 @@ public class TileServiceManagerTest extends SysuiTestCase { Mockito.when(mUserTracker.getUserId()).thenReturn(UserHandle.USER_SYSTEM); Mockito.when(mUserTracker.getUserHandle()).thenReturn(UserHandle.SYSTEM); - Mockito.when(mTileServices.getContext()).thenReturn(mContext); + mMockContext = Mockito.mock(Context.class); + Mockito.when(mTileServices.getContext()).thenReturn(mMockContext); mTileLifecycle = Mockito.mock(TileLifecycleManager.class); Mockito.when(mTileLifecycle.isActiveTile()).thenReturn(false); ComponentName componentName = new ComponentName(mContext, @@ -71,6 +76,25 @@ public class TileServiceManagerTest extends SysuiTestCase { @After public void tearDown() throws Exception { mThread.quit(); + mTileServiceManager.handleDestroy(); + } + + @Test + public void testUninstallReceiverExported() { + ArgumentCaptor intentFilterCaptor = + ArgumentCaptor.forClass(IntentFilter.class); + + Mockito.verify(mMockContext).registerReceiverAsUser( + Mockito.any(), + Mockito.any(), + intentFilterCaptor.capture(), + Mockito.any(), + Mockito.any(), + Mockito.eq(Context.RECEIVER_EXPORTED) + ); + IntentFilter filter = intentFilterCaptor.getValue(); + assertTrue(filter.hasAction(Intent.ACTION_PACKAGE_REMOVED)); + assertTrue(filter.hasDataScheme("package")); } @Test