Loading core/java/com/android/internal/content/PackageMonitor.java +6 −0 Original line number Diff line number Diff line Loading @@ -401,6 +401,12 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver { if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { mChangeType = PACKAGE_UPDATING; onPackageUpdateStarted(pkg, uid); if (intent.getBooleanExtra(Intent.EXTRA_ARCHIVAL, false)) { // In case it is a removal event due to archiving, we trigger package // update event to refresh details like icons, title etc. corresponding to // the archived app. onPackageModified(pkg); } } else { mChangeType = PACKAGE_PERMANENT_CHANGE; // We only consider something to have changed if this is Loading core/res/res/drawable/archived_app_cloud_overlay.xml 0 → 100644 +15 −0 Original line number Diff line number Diff line <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="20dp" android:height="20dp" android:viewportWidth="60" android:viewportHeight="60"> <group android:scaleX="1.2" android:scaleY="1.2" android:translateX="15" android:translateY="14"> <path android:fillColor="@android:color/white" android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96zM19,18L6,18c-2.21,0 -4,-1.79 -4,-4 0,-2.05 1.53,-3.76 3.56,-3.97l1.07,-0.11 0.5,-0.95C8.08,7.14 9.94,6 12,6c2.62,0 4.88,1.86 5.39,4.43l0.3,1.5 1.53,0.11c1.56,0.1 2.78,1.41 2.78,2.96 0,1.65 -1.35,3 -3,3zM13.45,10h-2.9v3L8,13l4,4 4,-4h-2.55z"/> </group> </vector> No newline at end of file core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -1405,6 +1405,7 @@ <java-symbol type="drawable" name="ic_test_badge_no_background" /> <java-symbol type="drawable" name="ic_test_icon_badge_experiment" /> <java-symbol type="drawable" name="ic_instant_icon_badge_bolt" /> <java-symbol type="drawable" name="archived_app_cloud_overlay" /> <java-symbol type="drawable" name="emulator_circular_window_overlay" /> <java-symbol type="drawable" name="ic_qs_battery_saver" /> <java-symbol type="drawable" name="ic_qs_bluetooth" /> Loading core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java +37 −0 Original line number Diff line number Diff line Loading @@ -297,6 +297,43 @@ public class PackageMonitorTest { verify(spyPackageMonitor, times(1)).onFinishPackageChanges(); } @Test public void testPackageMonitorDoHandlePackageEventPackageRemovedReplacingArchived() { PackageMonitor spyPackageMonitor = spy(new TestPackageMonitor()); Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED); intent.setData(Uri.fromParts("package", FAKE_PACKAGE_NAME, null)); intent.putExtra(Intent.EXTRA_USER_HANDLE, FAKE_USER_ID); intent.putExtra(Intent.EXTRA_UID, FAKE_PACKAGE_UID); intent.putExtra(Intent.EXTRA_REPLACING, true); intent.putExtra(Intent.EXTRA_ARCHIVAL, true); intent.putExtra(Intent.EXTRA_REMOVED_FOR_ALL_USERS, true); spyPackageMonitor.doHandlePackageEvent(intent); verify(spyPackageMonitor, times(1)).onBeginPackageChanges(); verify(spyPackageMonitor, times(1)) .onPackageUpdateStarted(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID)); verify(spyPackageMonitor, times(1)).onPackageModified(eq(FAKE_PACKAGE_NAME)); ArgumentCaptor<Bundle> argumentCaptor = ArgumentCaptor.forClass(Bundle.class); verify(spyPackageMonitor, times(1)) .onPackageDisappearedWithExtras(eq(FAKE_PACKAGE_NAME), argumentCaptor.capture()); Bundle capturedExtras = argumentCaptor.getValue(); Bundle expectedExtras = intent.getExtras(); assertThat(capturedExtras.getInt(Intent.EXTRA_USER_HANDLE)) .isEqualTo(expectedExtras.getInt(Intent.EXTRA_USER_HANDLE)); assertThat(capturedExtras.getInt(Intent.EXTRA_UID)) .isEqualTo(expectedExtras.getInt(Intent.EXTRA_UID)); assertThat(capturedExtras.getInt(Intent.EXTRA_REPLACING)) .isEqualTo(expectedExtras.getInt(Intent.EXTRA_REPLACING)); assertThat(capturedExtras.getInt(Intent.EXTRA_REMOVED_FOR_ALL_USERS)) .isEqualTo(expectedExtras.getInt(Intent.EXTRA_REMOVED_FOR_ALL_USERS)); verify(spyPackageMonitor, times(1)) .onPackageDisappeared(eq(FAKE_PACKAGE_NAME), eq(PackageMonitor.PACKAGE_UPDATING)); verify(spyPackageMonitor, times(1)).onFinishPackageChanges(); } @Test public void testPackageMonitorDoHandlePackageEventPackageRemovedNotReplacing() throws Exception { Loading services/core/java/com/android/server/pm/PackageArchiver.java +36 −1 Original line number Diff line number Diff line Loading @@ -46,6 +46,12 @@ import android.content.pm.ResolveInfo; import android.content.pm.VersionedPackage; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.os.Binder; import android.os.Bundle; import android.os.Environment; Loading @@ -56,6 +62,7 @@ import android.os.UserHandle; import android.text.TextUtils; import android.util.Slog; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.server.pm.pkg.ArchiveState; Loading Loading @@ -367,7 +374,7 @@ public class PackageArchiver { // TODO(b/298452477) Handle monochrome icons. // In the rare case the archived app defined more than two launcher activities, we choose // the first one arbitrarily. return decodeIcon(activityInfos.get(0)); return includeCloudOverlay(decodeIcon(activityInfos.get(0))); } @VisibleForTesting Loading @@ -375,6 +382,34 @@ public class PackageArchiver { return BitmapFactory.decodeFile(archiveActivityInfo.getIconBitmap().toString()); } Bitmap includeCloudOverlay(Bitmap bitmap) { Drawable cloudDrawable = mContext.getResources() .getDrawable(R.drawable.archived_app_cloud_overlay, mContext.getTheme()); if (cloudDrawable == null) { Slog.e(TAG, "Unable to locate cloud overlay for archived app!"); return bitmap; } BitmapDrawable appIconDrawable = new BitmapDrawable(mContext.getResources(), bitmap); PorterDuffColorFilter colorFilter = new PorterDuffColorFilter( Color.argb(0.32f /* alpha */, 0f /* red */, 0f /* green */, 0f /* blue */), PorterDuff.Mode.SRC_ATOP); appIconDrawable.setColorFilter(colorFilter); appIconDrawable.setBounds( 0 /* left */, 0 /* top */, cloudDrawable.getIntrinsicWidth(), cloudDrawable.getIntrinsicHeight()); LayerDrawable layerDrawable = new LayerDrawable(new Drawable[] {appIconDrawable, cloudDrawable}); final int iconSize = mContext.getSystemService( ActivityManager.class).getLauncherLargeIconSize(); Bitmap appIconWithCloudOverlay = drawableToBitmap(layerDrawable, iconSize); bitmap.recycle(); return appIconWithCloudOverlay; } private void verifyArchived(PackageStateInternal ps, int userId) throws PackageManager.NameNotFoundException { PackageUserStateInternal userState = ps.getUserStateOrDefault(userId); Loading Loading
core/java/com/android/internal/content/PackageMonitor.java +6 −0 Original line number Diff line number Diff line Loading @@ -401,6 +401,12 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver { if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { mChangeType = PACKAGE_UPDATING; onPackageUpdateStarted(pkg, uid); if (intent.getBooleanExtra(Intent.EXTRA_ARCHIVAL, false)) { // In case it is a removal event due to archiving, we trigger package // update event to refresh details like icons, title etc. corresponding to // the archived app. onPackageModified(pkg); } } else { mChangeType = PACKAGE_PERMANENT_CHANGE; // We only consider something to have changed if this is Loading
core/res/res/drawable/archived_app_cloud_overlay.xml 0 → 100644 +15 −0 Original line number Diff line number Diff line <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="20dp" android:height="20dp" android:viewportWidth="60" android:viewportHeight="60"> <group android:scaleX="1.2" android:scaleY="1.2" android:translateX="15" android:translateY="14"> <path android:fillColor="@android:color/white" android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96zM19,18L6,18c-2.21,0 -4,-1.79 -4,-4 0,-2.05 1.53,-3.76 3.56,-3.97l1.07,-0.11 0.5,-0.95C8.08,7.14 9.94,6 12,6c2.62,0 4.88,1.86 5.39,4.43l0.3,1.5 1.53,0.11c1.56,0.1 2.78,1.41 2.78,2.96 0,1.65 -1.35,3 -3,3zM13.45,10h-2.9v3L8,13l4,4 4,-4h-2.55z"/> </group> </vector> No newline at end of file
core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -1405,6 +1405,7 @@ <java-symbol type="drawable" name="ic_test_badge_no_background" /> <java-symbol type="drawable" name="ic_test_icon_badge_experiment" /> <java-symbol type="drawable" name="ic_instant_icon_badge_bolt" /> <java-symbol type="drawable" name="archived_app_cloud_overlay" /> <java-symbol type="drawable" name="emulator_circular_window_overlay" /> <java-symbol type="drawable" name="ic_qs_battery_saver" /> <java-symbol type="drawable" name="ic_qs_bluetooth" /> Loading
core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java +37 −0 Original line number Diff line number Diff line Loading @@ -297,6 +297,43 @@ public class PackageMonitorTest { verify(spyPackageMonitor, times(1)).onFinishPackageChanges(); } @Test public void testPackageMonitorDoHandlePackageEventPackageRemovedReplacingArchived() { PackageMonitor spyPackageMonitor = spy(new TestPackageMonitor()); Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED); intent.setData(Uri.fromParts("package", FAKE_PACKAGE_NAME, null)); intent.putExtra(Intent.EXTRA_USER_HANDLE, FAKE_USER_ID); intent.putExtra(Intent.EXTRA_UID, FAKE_PACKAGE_UID); intent.putExtra(Intent.EXTRA_REPLACING, true); intent.putExtra(Intent.EXTRA_ARCHIVAL, true); intent.putExtra(Intent.EXTRA_REMOVED_FOR_ALL_USERS, true); spyPackageMonitor.doHandlePackageEvent(intent); verify(spyPackageMonitor, times(1)).onBeginPackageChanges(); verify(spyPackageMonitor, times(1)) .onPackageUpdateStarted(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID)); verify(spyPackageMonitor, times(1)).onPackageModified(eq(FAKE_PACKAGE_NAME)); ArgumentCaptor<Bundle> argumentCaptor = ArgumentCaptor.forClass(Bundle.class); verify(spyPackageMonitor, times(1)) .onPackageDisappearedWithExtras(eq(FAKE_PACKAGE_NAME), argumentCaptor.capture()); Bundle capturedExtras = argumentCaptor.getValue(); Bundle expectedExtras = intent.getExtras(); assertThat(capturedExtras.getInt(Intent.EXTRA_USER_HANDLE)) .isEqualTo(expectedExtras.getInt(Intent.EXTRA_USER_HANDLE)); assertThat(capturedExtras.getInt(Intent.EXTRA_UID)) .isEqualTo(expectedExtras.getInt(Intent.EXTRA_UID)); assertThat(capturedExtras.getInt(Intent.EXTRA_REPLACING)) .isEqualTo(expectedExtras.getInt(Intent.EXTRA_REPLACING)); assertThat(capturedExtras.getInt(Intent.EXTRA_REMOVED_FOR_ALL_USERS)) .isEqualTo(expectedExtras.getInt(Intent.EXTRA_REMOVED_FOR_ALL_USERS)); verify(spyPackageMonitor, times(1)) .onPackageDisappeared(eq(FAKE_PACKAGE_NAME), eq(PackageMonitor.PACKAGE_UPDATING)); verify(spyPackageMonitor, times(1)).onFinishPackageChanges(); } @Test public void testPackageMonitorDoHandlePackageEventPackageRemovedNotReplacing() throws Exception { Loading
services/core/java/com/android/server/pm/PackageArchiver.java +36 −1 Original line number Diff line number Diff line Loading @@ -46,6 +46,12 @@ import android.content.pm.ResolveInfo; import android.content.pm.VersionedPackage; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.os.Binder; import android.os.Bundle; import android.os.Environment; Loading @@ -56,6 +62,7 @@ import android.os.UserHandle; import android.text.TextUtils; import android.util.Slog; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.server.pm.pkg.ArchiveState; Loading Loading @@ -367,7 +374,7 @@ public class PackageArchiver { // TODO(b/298452477) Handle monochrome icons. // In the rare case the archived app defined more than two launcher activities, we choose // the first one arbitrarily. return decodeIcon(activityInfos.get(0)); return includeCloudOverlay(decodeIcon(activityInfos.get(0))); } @VisibleForTesting Loading @@ -375,6 +382,34 @@ public class PackageArchiver { return BitmapFactory.decodeFile(archiveActivityInfo.getIconBitmap().toString()); } Bitmap includeCloudOverlay(Bitmap bitmap) { Drawable cloudDrawable = mContext.getResources() .getDrawable(R.drawable.archived_app_cloud_overlay, mContext.getTheme()); if (cloudDrawable == null) { Slog.e(TAG, "Unable to locate cloud overlay for archived app!"); return bitmap; } BitmapDrawable appIconDrawable = new BitmapDrawable(mContext.getResources(), bitmap); PorterDuffColorFilter colorFilter = new PorterDuffColorFilter( Color.argb(0.32f /* alpha */, 0f /* red */, 0f /* green */, 0f /* blue */), PorterDuff.Mode.SRC_ATOP); appIconDrawable.setColorFilter(colorFilter); appIconDrawable.setBounds( 0 /* left */, 0 /* top */, cloudDrawable.getIntrinsicWidth(), cloudDrawable.getIntrinsicHeight()); LayerDrawable layerDrawable = new LayerDrawable(new Drawable[] {appIconDrawable, cloudDrawable}); final int iconSize = mContext.getSystemService( ActivityManager.class).getLauncherLargeIconSize(); Bitmap appIconWithCloudOverlay = drawableToBitmap(layerDrawable, iconSize); bitmap.recycle(); return appIconWithCloudOverlay; } private void verifyArchived(PackageStateInternal ps, int userId) throws PackageManager.NameNotFoundException { PackageUserStateInternal userState = ps.getUserStateOrDefault(userId); Loading