Loading packages/PackageInstaller/res/values/strings.xml +2 −0 Original line number Diff line number Diff line Loading @@ -143,6 +143,8 @@ <!-- [CHAR LIMIT=100] --> <string name="uninstall_done_app">Uninstalled <xliff:g id="package_label">%1$s</xliff:g></string> <!-- [CHAR LIMIT=100] --> <string name="uninstall_done_clone_app">Deleted <xliff:g id="package_label">%1$s</xliff:g> clone</string> <!-- [CHAR LIMIT=100] --> <string name="uninstall_failed">Uninstall unsuccessful.</string> <!-- [CHAR LIMIT=100] --> <string name="uninstall_failed_app">Uninstalling <xliff:g id="package_label">%1$s</xliff:g> unsuccessful.</string> Loading packages/PackageInstaller/src/com/android/packageinstaller/UninstallFinish.java +5 −1 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ public class UninstallFinish extends BroadcastReceiver { static final String EXTRA_UNINSTALL_ID = "com.android.packageinstaller.extra.UNINSTALL_ID"; static final String EXTRA_APP_LABEL = "com.android.packageinstaller.extra.APP_LABEL"; static final String EXTRA_IS_CLONE_APP = "com.android.packageinstaller.extra.IS_CLONE_APP"; @Override public void onReceive(Context context, Intent intent) { Loading Loading @@ -84,7 +85,10 @@ public class UninstallFinish extends BroadcastReceiver { case PackageInstaller.STATUS_SUCCESS: notificationManager.cancel(uninstallId); Toast.makeText(context, context.getString(R.string.uninstall_done_app, appLabel), boolean isCloneApp = intent.getBooleanExtra(EXTRA_IS_CLONE_APP, false); Toast.makeText(context, isCloneApp ? context.getString(R.string.uninstall_done_clone_app, appLabel) : context.getString(R.string.uninstall_done_app, appLabel), Toast.LENGTH_LONG).show(); return; case PackageInstaller.STATUS_FAILURE_BLOCKED: { Loading packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java +14 −1 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ public class UninstallerActivity extends Activity { private static final String TAG = "UninstallerActivity"; private static final String UNINSTALLING_CHANNEL = "uninstalling"; private boolean mIsClonedApp; public static class DialogInfo { public ApplicationInfo appInfo; Loading Loading @@ -277,6 +278,14 @@ public class UninstallerActivity extends Activity { fragment.show(ft, "dialog"); } /** * Starts uninstall of app. */ public void startUninstallProgress(boolean keepData, boolean isClonedApp) { mIsClonedApp = isClonedApp; startUninstallProgress(keepData); } public void startUninstallProgress(boolean keepData) { boolean returnResult = getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false); CharSequence label = mDialogInfo.appInfo.loadSafeLabel(getPackageManager()); Loading Loading @@ -329,6 +338,7 @@ public class UninstallerActivity extends Activity { broadcastIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mDialogInfo.appInfo); broadcastIntent.putExtra(UninstallFinish.EXTRA_APP_LABEL, label); broadcastIntent.putExtra(UninstallFinish.EXTRA_UNINSTALL_ID, uninstallId); broadcastIntent.putExtra(UninstallFinish.EXTRA_IS_CLONE_APP, mIsClonedApp); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, uninstallId, broadcastIntent, Loading @@ -343,7 +353,10 @@ public class UninstallerActivity extends Activity { Notification uninstallingNotification = (new Notification.Builder(this, UNINSTALLING_CHANNEL)) .setSmallIcon(R.drawable.ic_remove).setProgress(0, 1, true) .setContentTitle(getString(R.string.uninstalling_app, label)).setOngoing(true) .setContentTitle(mIsClonedApp ? getString(R.string.uninstalling_cloned_app, label) : getString(R.string.uninstalling_app, label)) .setOngoing(true) .build(); notificationManager.notify(uninstallId, uninstallingNotification); Loading packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java +6 −6 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ public class UninstallAlertDialogFragment extends DialogFragment implements private static final String LOG_TAG = UninstallAlertDialogFragment.class.getSimpleName(); private @Nullable CheckBox mKeepData; private boolean mIsClonedApp; /** * Get number of bytes of the app data of the package. Loading Loading @@ -125,7 +126,6 @@ public class UninstallAlertDialogFragment extends DialogFragment implements messageBuilder.append(" ").append(appLabel).append(".\n\n"); } } boolean isClonedApp = false; final boolean isUpdate = ((dialogInfo.appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0); Loading Loading @@ -154,7 +154,7 @@ public class UninstallAlertDialogFragment extends DialogFragment implements userName)); } else if (customUserManager.isUserOfType(USER_TYPE_PROFILE_CLONE) && customUserManager.isSameProfileGroup(dialogInfo.user, myUserHandle)) { isClonedApp = true; mIsClonedApp = true; messageBuilder.append(getString( R.string.uninstall_application_text_current_user_clone_profile)); } else { Loading @@ -162,7 +162,7 @@ public class UninstallAlertDialogFragment extends DialogFragment implements getString(R.string.uninstall_application_text_user, userName)); } } else if (isCloneProfile(myUserHandle)) { isClonedApp = true; mIsClonedApp = true; messageBuilder.append(getString( R.string.uninstall_application_text_current_user_clone_profile)); } else { Loading @@ -177,7 +177,7 @@ public class UninstallAlertDialogFragment extends DialogFragment implements } } if (isClonedApp) { if (mIsClonedApp) { dialogBuilder.setTitle(getString(R.string.cloned_app_label, appLabel)); } else { dialogBuilder.setTitle(appLabel); Loading Loading @@ -236,7 +236,7 @@ public class UninstallAlertDialogFragment extends DialogFragment implements UserManager userManager = getContext().getSystemService(UserManager.class); List<UserHandle> profiles = userManager.getUserProfiles(); for (UserHandle userHandle : profiles) { if (!Process.myUserHandle().equals(UserHandle.SYSTEM) && isCloneProfile(userHandle)) { if (!userHandle.equals(UserHandle.SYSTEM) && isCloneProfile(userHandle)) { cloneUser = userHandle; break; } Loading @@ -260,7 +260,7 @@ public class UninstallAlertDialogFragment extends DialogFragment implements public void onClick(DialogInterface dialog, int which) { if (which == Dialog.BUTTON_POSITIVE) { ((UninstallerActivity) getActivity()).startUninstallProgress( mKeepData != null && mKeepData.isChecked()); mKeepData != null && mKeepData.isChecked(), mIsClonedApp); } else { ((UninstallerActivity) getActivity()).dispatchAborted(); } Loading services/core/java/com/android/server/pm/DeletePackageHelper.java +15 −0 Original line number Diff line number Diff line Loading @@ -774,6 +774,21 @@ final class DeletePackageHelper { if (!deleteAllUsers) { returnCode = deletePackageX(internalPackageName, versionCode, userId, deleteFlags, false /*removedBySystem*/); // Get a list of child user profiles and delete if package is // present in clone profile. int[] childUserIds = mUserManagerInternal.getProfileIds(userId, true); for (int childId : childUserIds) { if (childId != userId) { UserInfo userInfo = mUserManagerInternal.getUserInfo(childId); if (userInfo != null && userInfo.isCloneProfile()) { returnCode = deletePackageX(internalPackageName, versionCode, childId, deleteFlags, false /*removedBySystem*/); break; } } } } else { int[] blockUninstallUserIds = getBlockUninstallForUsers(innerSnapshot, internalPackageName, users); Loading Loading
packages/PackageInstaller/res/values/strings.xml +2 −0 Original line number Diff line number Diff line Loading @@ -143,6 +143,8 @@ <!-- [CHAR LIMIT=100] --> <string name="uninstall_done_app">Uninstalled <xliff:g id="package_label">%1$s</xliff:g></string> <!-- [CHAR LIMIT=100] --> <string name="uninstall_done_clone_app">Deleted <xliff:g id="package_label">%1$s</xliff:g> clone</string> <!-- [CHAR LIMIT=100] --> <string name="uninstall_failed">Uninstall unsuccessful.</string> <!-- [CHAR LIMIT=100] --> <string name="uninstall_failed_app">Uninstalling <xliff:g id="package_label">%1$s</xliff:g> unsuccessful.</string> Loading
packages/PackageInstaller/src/com/android/packageinstaller/UninstallFinish.java +5 −1 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ public class UninstallFinish extends BroadcastReceiver { static final String EXTRA_UNINSTALL_ID = "com.android.packageinstaller.extra.UNINSTALL_ID"; static final String EXTRA_APP_LABEL = "com.android.packageinstaller.extra.APP_LABEL"; static final String EXTRA_IS_CLONE_APP = "com.android.packageinstaller.extra.IS_CLONE_APP"; @Override public void onReceive(Context context, Intent intent) { Loading Loading @@ -84,7 +85,10 @@ public class UninstallFinish extends BroadcastReceiver { case PackageInstaller.STATUS_SUCCESS: notificationManager.cancel(uninstallId); Toast.makeText(context, context.getString(R.string.uninstall_done_app, appLabel), boolean isCloneApp = intent.getBooleanExtra(EXTRA_IS_CLONE_APP, false); Toast.makeText(context, isCloneApp ? context.getString(R.string.uninstall_done_clone_app, appLabel) : context.getString(R.string.uninstall_done_app, appLabel), Toast.LENGTH_LONG).show(); return; case PackageInstaller.STATUS_FAILURE_BLOCKED: { Loading
packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java +14 −1 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ public class UninstallerActivity extends Activity { private static final String TAG = "UninstallerActivity"; private static final String UNINSTALLING_CHANNEL = "uninstalling"; private boolean mIsClonedApp; public static class DialogInfo { public ApplicationInfo appInfo; Loading Loading @@ -277,6 +278,14 @@ public class UninstallerActivity extends Activity { fragment.show(ft, "dialog"); } /** * Starts uninstall of app. */ public void startUninstallProgress(boolean keepData, boolean isClonedApp) { mIsClonedApp = isClonedApp; startUninstallProgress(keepData); } public void startUninstallProgress(boolean keepData) { boolean returnResult = getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false); CharSequence label = mDialogInfo.appInfo.loadSafeLabel(getPackageManager()); Loading Loading @@ -329,6 +338,7 @@ public class UninstallerActivity extends Activity { broadcastIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mDialogInfo.appInfo); broadcastIntent.putExtra(UninstallFinish.EXTRA_APP_LABEL, label); broadcastIntent.putExtra(UninstallFinish.EXTRA_UNINSTALL_ID, uninstallId); broadcastIntent.putExtra(UninstallFinish.EXTRA_IS_CLONE_APP, mIsClonedApp); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, uninstallId, broadcastIntent, Loading @@ -343,7 +353,10 @@ public class UninstallerActivity extends Activity { Notification uninstallingNotification = (new Notification.Builder(this, UNINSTALLING_CHANNEL)) .setSmallIcon(R.drawable.ic_remove).setProgress(0, 1, true) .setContentTitle(getString(R.string.uninstalling_app, label)).setOngoing(true) .setContentTitle(mIsClonedApp ? getString(R.string.uninstalling_cloned_app, label) : getString(R.string.uninstalling_app, label)) .setOngoing(true) .build(); notificationManager.notify(uninstallId, uninstallingNotification); Loading
packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java +6 −6 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ public class UninstallAlertDialogFragment extends DialogFragment implements private static final String LOG_TAG = UninstallAlertDialogFragment.class.getSimpleName(); private @Nullable CheckBox mKeepData; private boolean mIsClonedApp; /** * Get number of bytes of the app data of the package. Loading Loading @@ -125,7 +126,6 @@ public class UninstallAlertDialogFragment extends DialogFragment implements messageBuilder.append(" ").append(appLabel).append(".\n\n"); } } boolean isClonedApp = false; final boolean isUpdate = ((dialogInfo.appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0); Loading Loading @@ -154,7 +154,7 @@ public class UninstallAlertDialogFragment extends DialogFragment implements userName)); } else if (customUserManager.isUserOfType(USER_TYPE_PROFILE_CLONE) && customUserManager.isSameProfileGroup(dialogInfo.user, myUserHandle)) { isClonedApp = true; mIsClonedApp = true; messageBuilder.append(getString( R.string.uninstall_application_text_current_user_clone_profile)); } else { Loading @@ -162,7 +162,7 @@ public class UninstallAlertDialogFragment extends DialogFragment implements getString(R.string.uninstall_application_text_user, userName)); } } else if (isCloneProfile(myUserHandle)) { isClonedApp = true; mIsClonedApp = true; messageBuilder.append(getString( R.string.uninstall_application_text_current_user_clone_profile)); } else { Loading @@ -177,7 +177,7 @@ public class UninstallAlertDialogFragment extends DialogFragment implements } } if (isClonedApp) { if (mIsClonedApp) { dialogBuilder.setTitle(getString(R.string.cloned_app_label, appLabel)); } else { dialogBuilder.setTitle(appLabel); Loading Loading @@ -236,7 +236,7 @@ public class UninstallAlertDialogFragment extends DialogFragment implements UserManager userManager = getContext().getSystemService(UserManager.class); List<UserHandle> profiles = userManager.getUserProfiles(); for (UserHandle userHandle : profiles) { if (!Process.myUserHandle().equals(UserHandle.SYSTEM) && isCloneProfile(userHandle)) { if (!userHandle.equals(UserHandle.SYSTEM) && isCloneProfile(userHandle)) { cloneUser = userHandle; break; } Loading @@ -260,7 +260,7 @@ public class UninstallAlertDialogFragment extends DialogFragment implements public void onClick(DialogInterface dialog, int which) { if (which == Dialog.BUTTON_POSITIVE) { ((UninstallerActivity) getActivity()).startUninstallProgress( mKeepData != null && mKeepData.isChecked()); mKeepData != null && mKeepData.isChecked(), mIsClonedApp); } else { ((UninstallerActivity) getActivity()).dispatchAborted(); } Loading
services/core/java/com/android/server/pm/DeletePackageHelper.java +15 −0 Original line number Diff line number Diff line Loading @@ -774,6 +774,21 @@ final class DeletePackageHelper { if (!deleteAllUsers) { returnCode = deletePackageX(internalPackageName, versionCode, userId, deleteFlags, false /*removedBySystem*/); // Get a list of child user profiles and delete if package is // present in clone profile. int[] childUserIds = mUserManagerInternal.getProfileIds(userId, true); for (int childId : childUserIds) { if (childId != userId) { UserInfo userInfo = mUserManagerInternal.getUserInfo(childId); if (userInfo != null && userInfo.isCloneProfile()) { returnCode = deletePackageX(internalPackageName, versionCode, childId, deleteFlags, false /*removedBySystem*/); break; } } } } else { int[] blockUninstallUserIds = getBlockUninstallForUsers(innerSnapshot, internalPackageName, users); Loading