Loading core/java/com/android/internal/content/PackageMonitor.java +10 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver { sPackageFilt.addAction(Intent.ACTION_PACKAGE_CHANGED); sPackageFilt.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); sPackageFilt.addAction(Intent.ACTION_PACKAGE_RESTARTED); sPackageFilt.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED); sPackageFilt.addDataScheme("package"); sNonDataFilt.addAction(Intent.ACTION_UID_REMOVED); sNonDataFilt.addAction(Intent.ACTION_USER_STOPPED); Loading Loading @@ -275,6 +276,9 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver { public void onFinishPackageChanges() { } public void onPackageDataCleared(String packageName, int uid) { } public int getChangingUserId() { return mChangeUserId; } Loading Loading @@ -365,6 +369,12 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver { } onPackageModified(pkg); } } else if (Intent.ACTION_PACKAGE_DATA_CLEARED.equals(action)) { String pkg = getPackageName(intent); int uid = intent.getIntExtra(Intent.EXTRA_UID, 0); if (pkg != null) { onPackageDataCleared(pkg, uid); } } else if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) { mDisappearingPackages = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES); mChangeType = PACKAGE_TEMPORARY_CHANGE; Loading services/core/java/com/android/server/pm/ShortcutService.java +27 −26 Original line number Diff line number Diff line Loading @@ -1561,48 +1561,46 @@ public class ShortcutService extends IShortcutService.Stub { // === House keeping === @VisibleForTesting void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId) { cleanUpPackageLocked(packageName, owningUserId, packageUserId, /* forceForCommandLine= */ false); private void cleanUpPackageForAllLoadedUsers(String packageName, @UserIdInt int packageUserId) { synchronized (mLock) { forEachLoadedUserLocked(user -> cleanUpPackageLocked(packageName, user.getUserId(), packageUserId)); } } /** * Remove all the information associated with a package. This will really remove all the * information, including the restore information (i.e. it'll remove packages even if they're * shadow). * * This is called when an app is uninstalled, or an app gets "clear data"ed. */ private void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId, boolean forceForCommandLine) { if (!forceForCommandLine && isPackageInstalled(packageName, packageUserId)) { wtf("Package " + packageName + " is still installed for user " + packageUserId); return; } @VisibleForTesting void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId) { final boolean wasUserLoaded = isUserLoadedLocked(owningUserId); final ShortcutUser mUser = getUserShortcutsLocked(owningUserId); final ShortcutUser user = getUserShortcutsLocked(owningUserId); boolean doNotify = false; // First, remove the package from the package list (if the package is a publisher). if (packageUserId == owningUserId) { if (mUser.removePackage(this, packageName) != null) { if (user.removePackage(this, packageName) != null) { doNotify = true; } } // Also remove from the launcher list (if the package is a launcher). mUser.removeLauncher(packageUserId, packageName); user.removeLauncher(packageUserId, packageName); // Then remove pinned shortcuts from all launchers. final ArrayMap<PackageWithUser, ShortcutLauncher> launchers = mUser.getAllLaunchers(); final ArrayMap<PackageWithUser, ShortcutLauncher> launchers = user.getAllLaunchers(); for (int i = launchers.size() - 1; i >= 0; i--) { launchers.valueAt(i).cleanUpPackage(packageName, packageUserId); } // Now there may be orphan shortcuts because we removed pinned shortucts at the previous // step. Remove them too. for (int i = mUser.getAllPackages().size() - 1; i >= 0; i--) { mUser.getAllPackages().valueAt(i).refreshPinnedFlags(this); for (int i = user.getAllPackages().size() - 1; i >= 0; i--) { user.getAllPackages().valueAt(i).refreshPinnedFlags(this); } scheduleSaveUser(owningUserId); Loading Loading @@ -1842,6 +1840,11 @@ public class ShortcutService extends IShortcutService.Stub { public void onPackageRemoved(String packageName, int uid) { handlePackageRemoved(packageName, getChangingUserId()); } @Override public void onPackageDataCleared(String packageName, int uid) { handlePackageDataCleared(packageName, getChangingUserId()); } }; /** Loading Loading @@ -1915,16 +1918,15 @@ public class ShortcutService extends IShortcutService.Stub { Slog.d(TAG, String.format("handlePackageRemoved: %s user=%d", packageName, packageUserId)); } handlePackageRemovedInner(packageName, packageUserId, /* forceForCommandLine =*/ false); cleanUpPackageForAllLoadedUsers(packageName, packageUserId); } private void handlePackageRemovedInner(String packageName, @UserIdInt int packageUserId, boolean forceForCommandLine) { synchronized (mLock) { forEachLoadedUserLocked(user -> cleanUpPackageLocked(packageName, user.getUserId(), packageUserId, forceForCommandLine)); private void handlePackageDataCleared(String packageName, int packageUserId) { if (DEBUG) { Slog.d(TAG, String.format("handlePackageDataCleared: %s user=%d", packageName, packageUserId)); } cleanUpPackageForAllLoadedUsers(packageName, packageUserId); } // === PackageManager interaction === Loading Loading @@ -2390,8 +2392,7 @@ public class ShortcutService extends IShortcutService.Stub { Slog.i(TAG, "cmd: handleClearShortcuts: " + mUserId + ", " + packageName); ShortcutService.this.handlePackageRemovedInner(packageName, mUserId, /* forceForCommandLine= */ true); ShortcutService.this.cleanUpPackageForAllLoadedUsers(packageName, mUserId); } } Loading services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java +79 −0 Original line number Diff line number Diff line Loading @@ -1061,6 +1061,12 @@ public class ShortcutManagerTest extends InstrumentationTestCase { i.putExtra(Intent.EXTRA_REPLACING, true); return i; } private Intent genPackageDataClear(String packageName, int userId) { Intent i = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED); i.setData(Uri.parse("package:" + packageName)); i.putExtra(Intent.EXTRA_USER_HANDLE, userId); return i; } private ShortcutInfo parceled(ShortcutInfo si) { Parcel p = Parcel.obtain(); Loading Loading @@ -4159,6 +4165,79 @@ public class ShortcutManagerTest extends InstrumentationTestCase { assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10)); } /** Almost ame as testHandlePackageDelete, except it doesn't uninstall packages. */ public void testHandlePackageClearData() { final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource( getTestContext().getResources(), R.drawable.black_32x32)); setCaller(CALLING_PACKAGE_1, USER_0); assertTrue(mManager.addDynamicShortcuts(list( makeShortcutWithIcon("s1", bmp32x32), makeShortcutWithIcon("s2", bmp32x32) ))); setCaller(CALLING_PACKAGE_2, USER_0); assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32)))); setCaller(CALLING_PACKAGE_3, USER_0); assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32)))); setCaller(CALLING_PACKAGE_1, USER_10); assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32)))); setCaller(CALLING_PACKAGE_2, USER_10); assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32)))); setCaller(CALLING_PACKAGE_3, USER_10); assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32)))); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10)); mService.mPackageMonitor.onReceive(getTestContext(), genPackageDataClear(CALLING_PACKAGE_1, USER_0)); assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10)); assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10)); mService.mPackageMonitor.onReceive(getTestContext(), genPackageDataClear(CALLING_PACKAGE_2, USER_10)); assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10)); assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10)); assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10)); assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10)); } public void testHandlePackageUpdate() throws Throwable { // Set up shortcuts and launchers. Loading Loading
core/java/com/android/internal/content/PackageMonitor.java +10 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver { sPackageFilt.addAction(Intent.ACTION_PACKAGE_CHANGED); sPackageFilt.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); sPackageFilt.addAction(Intent.ACTION_PACKAGE_RESTARTED); sPackageFilt.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED); sPackageFilt.addDataScheme("package"); sNonDataFilt.addAction(Intent.ACTION_UID_REMOVED); sNonDataFilt.addAction(Intent.ACTION_USER_STOPPED); Loading Loading @@ -275,6 +276,9 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver { public void onFinishPackageChanges() { } public void onPackageDataCleared(String packageName, int uid) { } public int getChangingUserId() { return mChangeUserId; } Loading Loading @@ -365,6 +369,12 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver { } onPackageModified(pkg); } } else if (Intent.ACTION_PACKAGE_DATA_CLEARED.equals(action)) { String pkg = getPackageName(intent); int uid = intent.getIntExtra(Intent.EXTRA_UID, 0); if (pkg != null) { onPackageDataCleared(pkg, uid); } } else if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) { mDisappearingPackages = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES); mChangeType = PACKAGE_TEMPORARY_CHANGE; Loading
services/core/java/com/android/server/pm/ShortcutService.java +27 −26 Original line number Diff line number Diff line Loading @@ -1561,48 +1561,46 @@ public class ShortcutService extends IShortcutService.Stub { // === House keeping === @VisibleForTesting void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId) { cleanUpPackageLocked(packageName, owningUserId, packageUserId, /* forceForCommandLine= */ false); private void cleanUpPackageForAllLoadedUsers(String packageName, @UserIdInt int packageUserId) { synchronized (mLock) { forEachLoadedUserLocked(user -> cleanUpPackageLocked(packageName, user.getUserId(), packageUserId)); } } /** * Remove all the information associated with a package. This will really remove all the * information, including the restore information (i.e. it'll remove packages even if they're * shadow). * * This is called when an app is uninstalled, or an app gets "clear data"ed. */ private void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId, boolean forceForCommandLine) { if (!forceForCommandLine && isPackageInstalled(packageName, packageUserId)) { wtf("Package " + packageName + " is still installed for user " + packageUserId); return; } @VisibleForTesting void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId) { final boolean wasUserLoaded = isUserLoadedLocked(owningUserId); final ShortcutUser mUser = getUserShortcutsLocked(owningUserId); final ShortcutUser user = getUserShortcutsLocked(owningUserId); boolean doNotify = false; // First, remove the package from the package list (if the package is a publisher). if (packageUserId == owningUserId) { if (mUser.removePackage(this, packageName) != null) { if (user.removePackage(this, packageName) != null) { doNotify = true; } } // Also remove from the launcher list (if the package is a launcher). mUser.removeLauncher(packageUserId, packageName); user.removeLauncher(packageUserId, packageName); // Then remove pinned shortcuts from all launchers. final ArrayMap<PackageWithUser, ShortcutLauncher> launchers = mUser.getAllLaunchers(); final ArrayMap<PackageWithUser, ShortcutLauncher> launchers = user.getAllLaunchers(); for (int i = launchers.size() - 1; i >= 0; i--) { launchers.valueAt(i).cleanUpPackage(packageName, packageUserId); } // Now there may be orphan shortcuts because we removed pinned shortucts at the previous // step. Remove them too. for (int i = mUser.getAllPackages().size() - 1; i >= 0; i--) { mUser.getAllPackages().valueAt(i).refreshPinnedFlags(this); for (int i = user.getAllPackages().size() - 1; i >= 0; i--) { user.getAllPackages().valueAt(i).refreshPinnedFlags(this); } scheduleSaveUser(owningUserId); Loading Loading @@ -1842,6 +1840,11 @@ public class ShortcutService extends IShortcutService.Stub { public void onPackageRemoved(String packageName, int uid) { handlePackageRemoved(packageName, getChangingUserId()); } @Override public void onPackageDataCleared(String packageName, int uid) { handlePackageDataCleared(packageName, getChangingUserId()); } }; /** Loading Loading @@ -1915,16 +1918,15 @@ public class ShortcutService extends IShortcutService.Stub { Slog.d(TAG, String.format("handlePackageRemoved: %s user=%d", packageName, packageUserId)); } handlePackageRemovedInner(packageName, packageUserId, /* forceForCommandLine =*/ false); cleanUpPackageForAllLoadedUsers(packageName, packageUserId); } private void handlePackageRemovedInner(String packageName, @UserIdInt int packageUserId, boolean forceForCommandLine) { synchronized (mLock) { forEachLoadedUserLocked(user -> cleanUpPackageLocked(packageName, user.getUserId(), packageUserId, forceForCommandLine)); private void handlePackageDataCleared(String packageName, int packageUserId) { if (DEBUG) { Slog.d(TAG, String.format("handlePackageDataCleared: %s user=%d", packageName, packageUserId)); } cleanUpPackageForAllLoadedUsers(packageName, packageUserId); } // === PackageManager interaction === Loading Loading @@ -2390,8 +2392,7 @@ public class ShortcutService extends IShortcutService.Stub { Slog.i(TAG, "cmd: handleClearShortcuts: " + mUserId + ", " + packageName); ShortcutService.this.handlePackageRemovedInner(packageName, mUserId, /* forceForCommandLine= */ true); ShortcutService.this.cleanUpPackageForAllLoadedUsers(packageName, mUserId); } } Loading
services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java +79 −0 Original line number Diff line number Diff line Loading @@ -1061,6 +1061,12 @@ public class ShortcutManagerTest extends InstrumentationTestCase { i.putExtra(Intent.EXTRA_REPLACING, true); return i; } private Intent genPackageDataClear(String packageName, int userId) { Intent i = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED); i.setData(Uri.parse("package:" + packageName)); i.putExtra(Intent.EXTRA_USER_HANDLE, userId); return i; } private ShortcutInfo parceled(ShortcutInfo si) { Parcel p = Parcel.obtain(); Loading Loading @@ -4159,6 +4165,79 @@ public class ShortcutManagerTest extends InstrumentationTestCase { assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10)); } /** Almost ame as testHandlePackageDelete, except it doesn't uninstall packages. */ public void testHandlePackageClearData() { final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource( getTestContext().getResources(), R.drawable.black_32x32)); setCaller(CALLING_PACKAGE_1, USER_0); assertTrue(mManager.addDynamicShortcuts(list( makeShortcutWithIcon("s1", bmp32x32), makeShortcutWithIcon("s2", bmp32x32) ))); setCaller(CALLING_PACKAGE_2, USER_0); assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32)))); setCaller(CALLING_PACKAGE_3, USER_0); assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32)))); setCaller(CALLING_PACKAGE_1, USER_10); assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32)))); setCaller(CALLING_PACKAGE_2, USER_10); assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32)))); setCaller(CALLING_PACKAGE_3, USER_10); assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32)))); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10)); mService.mPackageMonitor.onReceive(getTestContext(), genPackageDataClear(CALLING_PACKAGE_1, USER_0)); assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10)); assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10)); mService.mPackageMonitor.onReceive(getTestContext(), genPackageDataClear(CALLING_PACKAGE_2, USER_10)); assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10)); assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10)); assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10)); assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10)); } public void testHandlePackageUpdate() throws Throwable { // Set up shortcuts and launchers. Loading