From 67c25db003fa8cb21cafa790344febc42063de46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CAnkita?= Date: Tue, 29 Nov 2022 15:49:55 +0000 Subject: [PATCH] Include clone app's presence in uninstall dialogues. Change display text of dialog in below cases - uninstalling an app which also has a cloned instance present from AppInfo page - uninstalling cloned app from its AppInfo page - uninstalling cloned app from Cloned Apps page by clicking on trash icon Also update the toast while deletion process is ongoing. Bug: 260713897 Test: manual Change-Id: I938a3259fe478d3c65cf5047de5bb60160f59735 --- .../PackageInstaller/res/values/strings.xml | 9 +++ .../UninstallUninstalling.java | 33 +++++++++- .../UninstallAlertDialogFragment.java | 61 ++++++++++++++++++- 3 files changed, 99 insertions(+), 4 deletions(-) diff --git a/packages/PackageInstaller/res/values/strings.xml b/packages/PackageInstaller/res/values/strings.xml index 6a3b23900fa4d..b713c1420928b 100644 --- a/packages/PackageInstaller/res/values/strings.xml +++ b/packages/PackageInstaller/res/values/strings.xml @@ -119,6 +119,10 @@ Replace this app with the factory version? All data will be removed. This affects all users of this device, including those with work profiles. Keep %1$s of app data. + + Do you want to delete this app? + + Do you want to uninstall this app? %1$s clone will also be deleted. Running uninstalls @@ -137,6 +141,8 @@ Uninstall unsuccessful. Uninstalling %1$s unsuccessful. + + Deleting %1$s clone\u2026 Can\'t uninstall active device admin @@ -219,6 +225,9 @@ TV or loss of data that may result from its use. + + %1$s Clone + Continue diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java index 7bf27dfe64200..1485352c0f528 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java @@ -33,8 +33,10 @@ import android.content.pm.PackageManager; import android.content.pm.VersionedPackage; import android.os.Bundle; import android.os.IBinder; +import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; +import android.os.UserManager; import android.util.Log; import android.widget.Toast; @@ -51,6 +53,7 @@ public class UninstallUninstalling extends Activity implements static final String EXTRA_APP_LABEL = "com.android.packageinstaller.extra.APP_LABEL"; static final String EXTRA_KEEP_DATA = "com.android.packageinstaller.extra.KEEP_DATA"; + public static final String EXTRA_IS_CLONE_USER = "isCloneUser"; private int mUninstallId; private ApplicationInfo mAppInfo; @@ -76,6 +79,18 @@ public class UninstallUninstalling extends Activity implements boolean keepData = getIntent().getBooleanExtra(EXTRA_KEEP_DATA, false); UserHandle user = getIntent().getParcelableExtra(Intent.EXTRA_USER); + boolean isCloneUser = false; + if (user == null) { + user = Process.myUserHandle(); + } + + UserManager customUserManager = UninstallUninstalling.this + .createContextAsUser(UserHandle.of(user.getIdentifier()), 0) + .getSystemService(UserManager.class); + if (customUserManager.isUserOfType(UserManager.USER_TYPE_PROFILE_CLONE)) { + isCloneUser = true; + } + // Show dialog, which is the whole UI FragmentTransaction transaction = getFragmentManager().beginTransaction(); Fragment prev = getFragmentManager().findFragmentByTag("dialog"); @@ -83,6 +98,9 @@ public class UninstallUninstalling extends Activity implements transaction.remove(prev); } DialogFragment dialog = new UninstallUninstallingFragment(); + Bundle args = new Bundle(); + args.putBoolean(EXTRA_IS_CLONE_USER, isCloneUser); + dialog.setArguments(args); dialog.setCancelable(false); dialog.show(transaction, "dialog"); @@ -176,9 +194,20 @@ public class UninstallUninstalling extends Activity implements public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity()); + Bundle bundle = getArguments(); + boolean isCloneUser = false; + if (bundle != null) { + isCloneUser = bundle.getBoolean(EXTRA_IS_CLONE_USER); + } + dialogBuilder.setCancelable(false); - dialogBuilder.setMessage(getActivity().getString(R.string.uninstalling_app, - ((UninstallUninstalling) getActivity()).mLabel)); + if (isCloneUser) { + dialogBuilder.setMessage(getActivity().getString(R.string.uninstalling_cloned_app, + ((UninstallUninstalling) getActivity()).mLabel)); + } else { + dialogBuilder.setMessage(getActivity().getString(R.string.uninstalling_app, + ((UninstallUninstalling) getActivity()).mLabel)); + } Dialog dialog = dialogBuilder.create(); dialog.setCanceledOnTouchOutside(false); diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java index c9230b4ebf5bd..a1bc9928ae69d 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java @@ -123,6 +123,7 @@ 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); @@ -144,16 +145,36 @@ public class UninstallAlertDialogFragment extends DialogFragment implements messageBuilder.append( getString(R.string.uninstall_application_text_current_user_work_profile, userInfo.name)); + } else if (userInfo.isCloneProfile() + && userInfo.profileGroupId == myUserHandle.getIdentifier()) { + isClonedApp = true; + messageBuilder.append(getString( + R.string.uninstall_application_text_current_user_clone_profile)); } else { messageBuilder.append( getString(R.string.uninstall_application_text_user, userInfo.name)); } + } else if (isCloneProfile(myUserHandle)) { + isClonedApp = true; + messageBuilder.append(getString( + R.string.uninstall_application_text_current_user_clone_profile)); } else { - messageBuilder.append(getString(R.string.uninstall_application_text)); + if (Process.myUserHandle().equals(UserHandle.SYSTEM) + && hasClonedInstance(dialogInfo.appInfo.packageName)) { + messageBuilder.append(getString( + R.string.uninstall_application_text_with_clone_instance, + appLabel)); + } else { + messageBuilder.append(getString(R.string.uninstall_application_text)); + } } } - dialogBuilder.setTitle(appLabel); + if (isClonedApp) { + dialogBuilder.setTitle(getString(R.string.cloned_app_label, appLabel)); + } else { + dialogBuilder.setTitle(appLabel); + } dialogBuilder.setPositiveButton(android.R.string.ok, this); dialogBuilder.setNegativeButton(android.R.string.cancel, this); @@ -192,6 +213,42 @@ public class UninstallAlertDialogFragment extends DialogFragment implements return dialogBuilder.create(); } + private boolean isCloneProfile(UserHandle userHandle) { + UserManager customUserManager = getContext() + .createContextAsUser(UserHandle.of(userHandle.getIdentifier()), 0) + .getSystemService(UserManager.class); + if (customUserManager.isUserOfType(UserManager.USER_TYPE_PROFILE_CLONE)) { + return true; + } + return false; + } + + private boolean hasClonedInstance(String packageName) { + // Check if clone user is present on the device. + UserHandle cloneUser = null; + UserManager userManager = getContext().getSystemService(UserManager.class); + List profiles = userManager.getUserProfiles(); + for (UserHandle userHandle : profiles) { + if (!Process.myUserHandle().equals(UserHandle.SYSTEM) && isCloneProfile(userHandle)) { + cloneUser = userHandle; + break; + } + } + + // Check if another instance of given package exists in clone user profile. + if (cloneUser != null) { + try { + if (getContext().getPackageManager() + .getPackageUidAsUser(packageName, cloneUser.getIdentifier()) > 0) { + return true; + } + } catch (PackageManager.NameNotFoundException e) { + return false; + } + } + return false; + } + @Override public void onClick(DialogInterface dialog, int which) { if (which == Dialog.BUTTON_POSITIVE) {