Loading src/com/android/packageinstaller/PackageUtil.java +5 −2 Original line number Diff line number Diff line Loading @@ -17,7 +17,9 @@ package com.android.packageinstaller; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; Loading @@ -38,6 +40,7 @@ import java.util.List; * This is a utility class for defining some utility methods and constants * used in the package installer application. */ @SuppressLint("NewApi") public class PackageUtil { public static final String PREFIX="com.android.packageinstaller."; public static final String INTENT_ATTR_INSTALL_STATUS = PREFIX+"installStatus"; Loading Loading @@ -74,7 +77,7 @@ public class PackageUtil { * @param componentInfo ComponentInfo object whose resources are to be loaded * @param snippetView the snippet view */ public static View initSnippetForInstalledApp(Activity pContext, public static View initSnippetForInstalledApp(Context pContext, ApplicationInfo appInfo, View snippetView) { return initSnippetForInstalledApp(pContext, appInfo, snippetView, null); } Loading @@ -90,7 +93,7 @@ public class PackageUtil { * @param snippetView the snippet view * @param UserHandle user that the app si installed for. */ public static View initSnippetForInstalledApp(Activity pContext, public static View initSnippetForInstalledApp(Context pContext, ApplicationInfo appInfo, View snippetView, UserHandle user) { final PackageManager pm = pContext.getPackageManager(); Drawable icon = appInfo.loadIcon(pm); Loading src/com/android/packageinstaller/UninstallAppProgress.java +188 −200 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ */ package com.android.packageinstaller; import android.annotation.SuppressLint; import android.app.Activity; import android.app.admin.IDevicePolicyManager; import android.content.Context; Loading @@ -27,7 +28,6 @@ import android.content.pm.IPackageManager; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.content.res.Configuration; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; Loading @@ -38,17 +38,14 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.util.Log; import android.util.TypedValue; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.android.packageinstaller.handheld.UninstallAppProgressFragment; import java.lang.ref.WeakReference; import java.util.List; /** Loading @@ -58,17 +55,16 @@ import java.util.List; * by an intent with the intent's class name explicitly set to UninstallAppProgress and expects * the application object of the application to uninstall. */ public class UninstallAppProgress extends Activity implements OnClickListener { private final String TAG="UninstallAppProgress"; @SuppressLint("NewApi") public class UninstallAppProgress extends Activity { private static final String TAG = "UninstallAppProgress"; private static final String FRAGMENT_TAG = "progress_fragment"; private ApplicationInfo mAppInfo; private boolean mAllUsers; private UserHandle mUser; private IBinder mCallback; private Button mOkButton; private Button mDeviceManagerButton; private Button mUsersButton; private volatile int mResultCode = -1; /** Loading @@ -83,16 +79,25 @@ public class UninstallAppProgress extends Activity implements OnClickListener { private static final int UNINSTALL_COMPLETE = 1; private static final int UNINSTALL_IS_SLOW = 2; private boolean isProfileOfOrSame(UserManager userManager, int userId, int profileId) { if (userId == profileId) { return true; } UserInfo parentUser = userManager.getProfileParent(profileId); return parentUser != null && parentUser.id == userId; private Handler mHandler = new MessageHandler(this); private static class MessageHandler extends Handler { private final WeakReference<UninstallAppProgress> mActivity; public MessageHandler(UninstallAppProgress activity) { mActivity = new WeakReference<>(activity); } private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { UninstallAppProgress activity = mActivity.get(); if (activity != null) { activity.handleMessage(msg); } } } private void handleMessage(Message msg) { if (isFinishing() || isDestroyed()) { return; } Loading Loading @@ -141,7 +146,7 @@ public class UninstallAppProgress extends Activity implements OnClickListener { // Show a Toast and finish the activity Context ctx = getBaseContext(); Toast.makeText(ctx, statusText, Toast.LENGTH_LONG).show(); setResultAndFinish(mResultCode); setResultAndFinish(); return; case PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER: { UserManager userManager = Loading @@ -168,13 +173,13 @@ public class UninstallAppProgress extends Activity implements OnClickListener { if (otherBlockingUser == null) { Log.d(TAG, "Uninstall failed because " + packageName + " is a device admin"); mDeviceManagerButton.setVisibility(View.VISIBLE); getProgressFragment().setDeviceManagerButtonVisible(true); statusText = getString( R.string.uninstall_failed_device_policy_manager); } else { Log.d(TAG, "Uninstall failed because " + packageName + " is a device admin of user " + otherBlockingUser); mDeviceManagerButton.setVisibility(View.GONE); getProgressFragment().setDeviceManagerButtonVisible(false); statusText = String.format( getString(R.string.uninstall_failed_device_policy_manager_of_user), otherBlockingUser.name); Loading Loading @@ -203,10 +208,10 @@ public class UninstallAppProgress extends Activity implements OnClickListener { } int myUserId = UserHandle.myUserId(); if (isProfileOfOrSame(userManager, myUserId, blockingUserId)) { mDeviceManagerButton.setVisibility(View.VISIBLE); getProgressFragment().setDeviceManagerButtonVisible(true); } else { mDeviceManagerButton.setVisibility(View.GONE); mUsersButton.setVisibility(View.VISIBLE); getProgressFragment().setDeviceManagerButtonVisible(false); getProgressFragment().setUsersButtonVisible(true); } // TODO: b/25442806 if (blockingUserId == UserHandle.USER_SYSTEM) { Loading @@ -228,16 +233,20 @@ public class UninstallAppProgress extends Activity implements OnClickListener { statusText = getString(R.string.uninstall_failed); break; } findViewById(R.id.progress_view).setVisibility(View.GONE); findViewById(R.id.status_view).setVisibility(View.VISIBLE); ((TextView)findViewById(R.id.status_text)).setText(statusText); findViewById(R.id.ok_panel).setVisibility(View.VISIBLE); getProgressFragment().showCompletion(statusText); break; default: break; } } }; private boolean isProfileOfOrSame(UserManager userManager, int userId, int profileId) { if (userId == profileId) { return true; } UserInfo parentUser = userManager.getProfileParent(profileId); return parentUser != null && parentUser.id == userId; } @Override public void onCreate(Bundle icicle) { Loading @@ -261,7 +270,7 @@ public class UninstallAppProgress extends Activity implements OnClickListener { } finish(); } else { setResultAndFinish(mResultCode); setResultAndFinish(); } return; Loading @@ -271,15 +280,15 @@ public class UninstallAppProgress extends Activity implements OnClickListener { if (mAllUsers && !UserManager.get(this).isAdminUser()) { throw new SecurityException("Only admin user can request uninstall for all users"); } mUser = intent.getParcelableExtra(Intent.EXTRA_USER); if (mUser == null) { mUser = android.os.Process.myUserHandle(); UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER); if (user == null) { user = android.os.Process.myUserHandle(); } else { UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); List<UserHandle> profiles = userManager.getUserProfiles(); if (!profiles.contains(mUser)) { if (!profiles.contains(user)) { throw new SecurityException("User " + android.os.Process.myUserHandle() + " can't " + "request uninstall for user " + mUser); + "request uninstall for user " + user); } } Loading @@ -293,13 +302,17 @@ public class UninstallAppProgress extends Activity implements OnClickListener { getWindow().setNavigationBarColor(Color.TRANSPARENT); getPackageManager().deletePackageAsUser(mAppInfo.packageName, observer, mAllUsers ? PackageManager.DELETE_ALL_USERS : 0, mUser.getIdentifier()); mAllUsers ? PackageManager.DELETE_ALL_USERS : 0, user.getIdentifier()); mHandler.sendMessageDelayed(mHandler.obtainMessage(UNINSTALL_IS_SLOW), QUICK_INSTALL_DELAY_MILLIS); } class PackageDeleteObserver extends IPackageDeleteObserver.Stub { public ApplicationInfo getAppInfo() { return mAppInfo; } private class PackageDeleteObserver extends IPackageDeleteObserver.Stub { public void packageDeleted(String packageName, int returnCode) { Message msg = mHandler.obtainMessage(UNINSTALL_COMPLETE); msg.arg1 = returnCode; Loading @@ -308,12 +321,12 @@ public class UninstallAppProgress extends Activity implements OnClickListener { } } void setResultAndFinish(int retCode) { setResult(retCode); public void setResultAndFinish() { setResult(mResultCode); finish(); } public void initView() { private void initView() { if (mIsViewInitialized) { return; } Loading @@ -339,44 +352,9 @@ public class UninstallAppProgress extends Activity implements OnClickListener { boolean isUpdate = ((mAppInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0); setTitle(isUpdate ? R.string.uninstall_update_title : R.string.uninstall_application_title); setContentView(R.layout.uninstall_progress); // Initialize views View snippetView = findViewById(R.id.app_snippet); PackageUtil.initSnippetForInstalledApp(this, mAppInfo, snippetView); mDeviceManagerButton = (Button) findViewById(R.id.device_manager_button); mUsersButton = (Button) findViewById(R.id.users_button); mDeviceManagerButton.setVisibility(View.GONE); mDeviceManagerButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); intent.setClassName("com.android.settings", "com.android.settings.Settings$DeviceAdminSettingsActivity"); intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); finish(); } }); mUsersButton.setVisibility(View.GONE); mUsersButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(Settings.ACTION_USER_SETTINGS); intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); finish(); } }); // Hide button till progress is being displayed mOkButton = (Button) findViewById(R.id.ok_button); mOkButton.setOnClickListener(this); } public void onClick(View v) { if(v == mOkButton) { Log.i(TAG, "Finished uninstalling pkg: " + mAppInfo.packageName); setResultAndFinish(mResultCode); } getFragmentManager().beginTransaction() .add(android.R.id.content, new UninstallAppProgressFragment(), FRAGMENT_TAG) .commitNowAllowingStateLoss(); } @Override Loading @@ -392,4 +370,14 @@ public class UninstallAppProgress extends Activity implements OnClickListener { } return super.dispatchKeyEvent(ev); } private ProgressFragment getProgressFragment() { return (ProgressFragment) getFragmentManager().findFragmentByTag(FRAGMENT_TAG); } public interface ProgressFragment { void setUsersButtonVisible(boolean visible); void setDeviceManagerButtonVisible(boolean visible); void showCompletion(CharSequence statusText); } } src/com/android/packageinstaller/UninstallerActivity.java +19 −117 Original line number Diff line number Diff line Loading @@ -16,14 +16,12 @@ */ package com.android.packageinstaller; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; import android.app.Fragment; import android.app.FragmentTransaction; import android.content.ComponentName; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; Loading @@ -31,132 +29,32 @@ import android.content.pm.IPackageDeleteObserver2; import android.content.pm.IPackageManager; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.util.Log; import com.android.packageinstaller.handheld.AppNotFoundDialogFragment; import com.android.packageinstaller.handheld.UninstallAlertDialogFragment; /* * This activity presents UI to uninstall an application. Usually launched with intent * Intent.ACTION_UNINSTALL_PKG_COMMAND and attribute * com.android.packageinstaller.PackageName set to the application package name */ @SuppressLint("NewApi") public class UninstallerActivity extends Activity { private static final String TAG = "UninstallerActivity"; public static class UninstallAlertDialogFragment extends DialogFragment implements DialogInterface.OnClickListener { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final PackageManager pm = getActivity().getPackageManager(); final DialogInfo dialogInfo = ((UninstallerActivity) getActivity()).mDialogInfo; final CharSequence appLabel = dialogInfo.appInfo.loadLabel(pm); AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity()); StringBuilder messageBuilder = new StringBuilder(); // If the Activity label differs from the App label, then make sure the user // knows the Activity belongs to the App being uninstalled. if (dialogInfo.activityInfo != null) { final CharSequence activityLabel = dialogInfo.activityInfo.loadLabel(pm); if (!activityLabel.equals(appLabel)) { messageBuilder.append( getString(R.string.uninstall_activity_text, activityLabel)); messageBuilder.append(" ").append(appLabel).append(".\n\n"); } } final boolean isUpdate = ((dialogInfo.appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0); UserManager userManager = UserManager.get(getActivity()); if (isUpdate) { if (isSingleUser(userManager)) { messageBuilder.append(getString(R.string.uninstall_update_text)); } else { messageBuilder.append(getString(R.string.uninstall_update_text_multiuser)); } } else { if (dialogInfo.allUsers && !isSingleUser(userManager)) { messageBuilder.append(getString(R.string.uninstall_application_text_all_users)); } else if (!dialogInfo.user.equals(android.os.Process.myUserHandle())) { UserInfo userInfo = userManager.getUserInfo(dialogInfo.user.getIdentifier()); messageBuilder.append( getString(R.string.uninstall_application_text_user, userInfo.name)); } else { messageBuilder.append(getString(R.string.uninstall_application_text)); } } dialogBuilder.setTitle(appLabel); dialogBuilder.setIcon(dialogInfo.appInfo.loadIcon(pm)); dialogBuilder.setPositiveButton(android.R.string.ok, this); dialogBuilder.setNegativeButton(android.R.string.cancel, this); dialogBuilder.setMessage(messageBuilder.toString()); return dialogBuilder.create(); } @Override public void onClick(DialogInterface dialog, int which) { if (which == Dialog.BUTTON_POSITIVE) { ((UninstallerActivity) getActivity()).startUninstallProgress(); } else { ((UninstallerActivity) getActivity()).dispatchAborted(); } } @Override public void onDismiss(DialogInterface dialog) { super.onDismiss(dialog); if (isAdded()) { getActivity().finish(); } } /** * Returns whether there is only one user on this device, not including * the system-only user. */ private boolean isSingleUser(UserManager userManager) { final int userCount = userManager.getUserCount(); return userCount == 1 || (UserManager.isSplitSystemUser() && userCount == 2); } } public static class AppNotFoundDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new AlertDialog.Builder(getActivity()) .setTitle(R.string.app_not_found_dlg_title) .setMessage(R.string.app_not_found_dlg_text) .setNeutralButton(android.R.string.ok, null) .create(); } @Override public void onDismiss(DialogInterface dialog) { super.onDismiss(dialog); if (isAdded()) { ((UninstallerActivity) getActivity()).dispatchAborted(); getActivity().setResult(Activity.RESULT_FIRST_USER); getActivity().finish(); } } } static class DialogInfo { ApplicationInfo appInfo; ActivityInfo activityInfo; boolean allUsers; UserHandle user; IBinder callback; public static class DialogInfo { public ApplicationInfo appInfo; public ActivityInfo activityInfo; public boolean allUsers; public UserHandle user; public IBinder callback; } private String mPackageName; Loading Loading @@ -197,7 +95,7 @@ public class UninstallerActivity extends Activity { try { mDialogInfo.appInfo = pm.getApplicationInfo(mPackageName, PackageManager.GET_UNINSTALLED_PACKAGES, mDialogInfo.user.getIdentifier()); PackageManager.MATCH_UNINSTALLED_PACKAGES, mDialogInfo.user.getIdentifier()); } catch (RemoteException e) { Log.e(TAG, "Unable to get packageName. Package manager is dead?"); } Loading @@ -224,6 +122,10 @@ public class UninstallerActivity extends Activity { showConfirmationDialog(); } public DialogInfo getDialogInfo() { return mDialogInfo; } private void showConfirmationDialog() { showDialogFragment(new UninstallAlertDialogFragment()); } Loading @@ -241,7 +143,7 @@ public class UninstallerActivity extends Activity { fragment.show(ft, "dialog"); } void startUninstallProgress() { public void startUninstallProgress() { Intent newIntent = new Intent(Intent.ACTION_VIEW); newIntent.putExtra(Intent.EXTRA_USER, mDialogInfo.user); newIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, mDialogInfo.allUsers); Loading @@ -255,7 +157,7 @@ public class UninstallerActivity extends Activity { startActivity(newIntent); } void dispatchAborted() { public void dispatchAborted() { if (mDialogInfo != null && mDialogInfo.callback != null) { final IPackageDeleteObserver2 observer = IPackageDeleteObserver2.Stub.asInterface( mDialogInfo.callback); Loading src/com/android/packageinstaller/handheld/AppNotFoundDialogFragment.java 0 → 100644 +51 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.packageinstaller.handheld; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; import android.content.DialogInterface; import android.os.Bundle; import com.android.packageinstaller.R; import com.android.packageinstaller.UninstallerActivity; @SuppressLint("NewApi") public class AppNotFoundDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new AlertDialog.Builder(getActivity()) .setTitle(R.string.app_not_found_dlg_title) .setMessage(R.string.app_not_found_dlg_text) .setNeutralButton(android.R.string.ok, null) .create(); } @Override public void onDismiss(DialogInterface dialog) { super.onDismiss(dialog); if (isAdded()) { ((UninstallerActivity) getActivity()).dispatchAborted(); getActivity().setResult(Activity.RESULT_FIRST_USER); getActivity().finish(); } } } src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java 0 → 100644 +113 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
src/com/android/packageinstaller/PackageUtil.java +5 −2 Original line number Diff line number Diff line Loading @@ -17,7 +17,9 @@ package com.android.packageinstaller; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; Loading @@ -38,6 +40,7 @@ import java.util.List; * This is a utility class for defining some utility methods and constants * used in the package installer application. */ @SuppressLint("NewApi") public class PackageUtil { public static final String PREFIX="com.android.packageinstaller."; public static final String INTENT_ATTR_INSTALL_STATUS = PREFIX+"installStatus"; Loading Loading @@ -74,7 +77,7 @@ public class PackageUtil { * @param componentInfo ComponentInfo object whose resources are to be loaded * @param snippetView the snippet view */ public static View initSnippetForInstalledApp(Activity pContext, public static View initSnippetForInstalledApp(Context pContext, ApplicationInfo appInfo, View snippetView) { return initSnippetForInstalledApp(pContext, appInfo, snippetView, null); } Loading @@ -90,7 +93,7 @@ public class PackageUtil { * @param snippetView the snippet view * @param UserHandle user that the app si installed for. */ public static View initSnippetForInstalledApp(Activity pContext, public static View initSnippetForInstalledApp(Context pContext, ApplicationInfo appInfo, View snippetView, UserHandle user) { final PackageManager pm = pContext.getPackageManager(); Drawable icon = appInfo.loadIcon(pm); Loading
src/com/android/packageinstaller/UninstallAppProgress.java +188 −200 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ */ package com.android.packageinstaller; import android.annotation.SuppressLint; import android.app.Activity; import android.app.admin.IDevicePolicyManager; import android.content.Context; Loading @@ -27,7 +28,6 @@ import android.content.pm.IPackageManager; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.content.res.Configuration; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; Loading @@ -38,17 +38,14 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.util.Log; import android.util.TypedValue; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.android.packageinstaller.handheld.UninstallAppProgressFragment; import java.lang.ref.WeakReference; import java.util.List; /** Loading @@ -58,17 +55,16 @@ import java.util.List; * by an intent with the intent's class name explicitly set to UninstallAppProgress and expects * the application object of the application to uninstall. */ public class UninstallAppProgress extends Activity implements OnClickListener { private final String TAG="UninstallAppProgress"; @SuppressLint("NewApi") public class UninstallAppProgress extends Activity { private static final String TAG = "UninstallAppProgress"; private static final String FRAGMENT_TAG = "progress_fragment"; private ApplicationInfo mAppInfo; private boolean mAllUsers; private UserHandle mUser; private IBinder mCallback; private Button mOkButton; private Button mDeviceManagerButton; private Button mUsersButton; private volatile int mResultCode = -1; /** Loading @@ -83,16 +79,25 @@ public class UninstallAppProgress extends Activity implements OnClickListener { private static final int UNINSTALL_COMPLETE = 1; private static final int UNINSTALL_IS_SLOW = 2; private boolean isProfileOfOrSame(UserManager userManager, int userId, int profileId) { if (userId == profileId) { return true; } UserInfo parentUser = userManager.getProfileParent(profileId); return parentUser != null && parentUser.id == userId; private Handler mHandler = new MessageHandler(this); private static class MessageHandler extends Handler { private final WeakReference<UninstallAppProgress> mActivity; public MessageHandler(UninstallAppProgress activity) { mActivity = new WeakReference<>(activity); } private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { UninstallAppProgress activity = mActivity.get(); if (activity != null) { activity.handleMessage(msg); } } } private void handleMessage(Message msg) { if (isFinishing() || isDestroyed()) { return; } Loading Loading @@ -141,7 +146,7 @@ public class UninstallAppProgress extends Activity implements OnClickListener { // Show a Toast and finish the activity Context ctx = getBaseContext(); Toast.makeText(ctx, statusText, Toast.LENGTH_LONG).show(); setResultAndFinish(mResultCode); setResultAndFinish(); return; case PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER: { UserManager userManager = Loading @@ -168,13 +173,13 @@ public class UninstallAppProgress extends Activity implements OnClickListener { if (otherBlockingUser == null) { Log.d(TAG, "Uninstall failed because " + packageName + " is a device admin"); mDeviceManagerButton.setVisibility(View.VISIBLE); getProgressFragment().setDeviceManagerButtonVisible(true); statusText = getString( R.string.uninstall_failed_device_policy_manager); } else { Log.d(TAG, "Uninstall failed because " + packageName + " is a device admin of user " + otherBlockingUser); mDeviceManagerButton.setVisibility(View.GONE); getProgressFragment().setDeviceManagerButtonVisible(false); statusText = String.format( getString(R.string.uninstall_failed_device_policy_manager_of_user), otherBlockingUser.name); Loading Loading @@ -203,10 +208,10 @@ public class UninstallAppProgress extends Activity implements OnClickListener { } int myUserId = UserHandle.myUserId(); if (isProfileOfOrSame(userManager, myUserId, blockingUserId)) { mDeviceManagerButton.setVisibility(View.VISIBLE); getProgressFragment().setDeviceManagerButtonVisible(true); } else { mDeviceManagerButton.setVisibility(View.GONE); mUsersButton.setVisibility(View.VISIBLE); getProgressFragment().setDeviceManagerButtonVisible(false); getProgressFragment().setUsersButtonVisible(true); } // TODO: b/25442806 if (blockingUserId == UserHandle.USER_SYSTEM) { Loading @@ -228,16 +233,20 @@ public class UninstallAppProgress extends Activity implements OnClickListener { statusText = getString(R.string.uninstall_failed); break; } findViewById(R.id.progress_view).setVisibility(View.GONE); findViewById(R.id.status_view).setVisibility(View.VISIBLE); ((TextView)findViewById(R.id.status_text)).setText(statusText); findViewById(R.id.ok_panel).setVisibility(View.VISIBLE); getProgressFragment().showCompletion(statusText); break; default: break; } } }; private boolean isProfileOfOrSame(UserManager userManager, int userId, int profileId) { if (userId == profileId) { return true; } UserInfo parentUser = userManager.getProfileParent(profileId); return parentUser != null && parentUser.id == userId; } @Override public void onCreate(Bundle icicle) { Loading @@ -261,7 +270,7 @@ public class UninstallAppProgress extends Activity implements OnClickListener { } finish(); } else { setResultAndFinish(mResultCode); setResultAndFinish(); } return; Loading @@ -271,15 +280,15 @@ public class UninstallAppProgress extends Activity implements OnClickListener { if (mAllUsers && !UserManager.get(this).isAdminUser()) { throw new SecurityException("Only admin user can request uninstall for all users"); } mUser = intent.getParcelableExtra(Intent.EXTRA_USER); if (mUser == null) { mUser = android.os.Process.myUserHandle(); UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER); if (user == null) { user = android.os.Process.myUserHandle(); } else { UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); List<UserHandle> profiles = userManager.getUserProfiles(); if (!profiles.contains(mUser)) { if (!profiles.contains(user)) { throw new SecurityException("User " + android.os.Process.myUserHandle() + " can't " + "request uninstall for user " + mUser); + "request uninstall for user " + user); } } Loading @@ -293,13 +302,17 @@ public class UninstallAppProgress extends Activity implements OnClickListener { getWindow().setNavigationBarColor(Color.TRANSPARENT); getPackageManager().deletePackageAsUser(mAppInfo.packageName, observer, mAllUsers ? PackageManager.DELETE_ALL_USERS : 0, mUser.getIdentifier()); mAllUsers ? PackageManager.DELETE_ALL_USERS : 0, user.getIdentifier()); mHandler.sendMessageDelayed(mHandler.obtainMessage(UNINSTALL_IS_SLOW), QUICK_INSTALL_DELAY_MILLIS); } class PackageDeleteObserver extends IPackageDeleteObserver.Stub { public ApplicationInfo getAppInfo() { return mAppInfo; } private class PackageDeleteObserver extends IPackageDeleteObserver.Stub { public void packageDeleted(String packageName, int returnCode) { Message msg = mHandler.obtainMessage(UNINSTALL_COMPLETE); msg.arg1 = returnCode; Loading @@ -308,12 +321,12 @@ public class UninstallAppProgress extends Activity implements OnClickListener { } } void setResultAndFinish(int retCode) { setResult(retCode); public void setResultAndFinish() { setResult(mResultCode); finish(); } public void initView() { private void initView() { if (mIsViewInitialized) { return; } Loading @@ -339,44 +352,9 @@ public class UninstallAppProgress extends Activity implements OnClickListener { boolean isUpdate = ((mAppInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0); setTitle(isUpdate ? R.string.uninstall_update_title : R.string.uninstall_application_title); setContentView(R.layout.uninstall_progress); // Initialize views View snippetView = findViewById(R.id.app_snippet); PackageUtil.initSnippetForInstalledApp(this, mAppInfo, snippetView); mDeviceManagerButton = (Button) findViewById(R.id.device_manager_button); mUsersButton = (Button) findViewById(R.id.users_button); mDeviceManagerButton.setVisibility(View.GONE); mDeviceManagerButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); intent.setClassName("com.android.settings", "com.android.settings.Settings$DeviceAdminSettingsActivity"); intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); finish(); } }); mUsersButton.setVisibility(View.GONE); mUsersButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(Settings.ACTION_USER_SETTINGS); intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); finish(); } }); // Hide button till progress is being displayed mOkButton = (Button) findViewById(R.id.ok_button); mOkButton.setOnClickListener(this); } public void onClick(View v) { if(v == mOkButton) { Log.i(TAG, "Finished uninstalling pkg: " + mAppInfo.packageName); setResultAndFinish(mResultCode); } getFragmentManager().beginTransaction() .add(android.R.id.content, new UninstallAppProgressFragment(), FRAGMENT_TAG) .commitNowAllowingStateLoss(); } @Override Loading @@ -392,4 +370,14 @@ public class UninstallAppProgress extends Activity implements OnClickListener { } return super.dispatchKeyEvent(ev); } private ProgressFragment getProgressFragment() { return (ProgressFragment) getFragmentManager().findFragmentByTag(FRAGMENT_TAG); } public interface ProgressFragment { void setUsersButtonVisible(boolean visible); void setDeviceManagerButtonVisible(boolean visible); void showCompletion(CharSequence statusText); } }
src/com/android/packageinstaller/UninstallerActivity.java +19 −117 Original line number Diff line number Diff line Loading @@ -16,14 +16,12 @@ */ package com.android.packageinstaller; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; import android.app.Fragment; import android.app.FragmentTransaction; import android.content.ComponentName; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; Loading @@ -31,132 +29,32 @@ import android.content.pm.IPackageDeleteObserver2; import android.content.pm.IPackageManager; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.util.Log; import com.android.packageinstaller.handheld.AppNotFoundDialogFragment; import com.android.packageinstaller.handheld.UninstallAlertDialogFragment; /* * This activity presents UI to uninstall an application. Usually launched with intent * Intent.ACTION_UNINSTALL_PKG_COMMAND and attribute * com.android.packageinstaller.PackageName set to the application package name */ @SuppressLint("NewApi") public class UninstallerActivity extends Activity { private static final String TAG = "UninstallerActivity"; public static class UninstallAlertDialogFragment extends DialogFragment implements DialogInterface.OnClickListener { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final PackageManager pm = getActivity().getPackageManager(); final DialogInfo dialogInfo = ((UninstallerActivity) getActivity()).mDialogInfo; final CharSequence appLabel = dialogInfo.appInfo.loadLabel(pm); AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity()); StringBuilder messageBuilder = new StringBuilder(); // If the Activity label differs from the App label, then make sure the user // knows the Activity belongs to the App being uninstalled. if (dialogInfo.activityInfo != null) { final CharSequence activityLabel = dialogInfo.activityInfo.loadLabel(pm); if (!activityLabel.equals(appLabel)) { messageBuilder.append( getString(R.string.uninstall_activity_text, activityLabel)); messageBuilder.append(" ").append(appLabel).append(".\n\n"); } } final boolean isUpdate = ((dialogInfo.appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0); UserManager userManager = UserManager.get(getActivity()); if (isUpdate) { if (isSingleUser(userManager)) { messageBuilder.append(getString(R.string.uninstall_update_text)); } else { messageBuilder.append(getString(R.string.uninstall_update_text_multiuser)); } } else { if (dialogInfo.allUsers && !isSingleUser(userManager)) { messageBuilder.append(getString(R.string.uninstall_application_text_all_users)); } else if (!dialogInfo.user.equals(android.os.Process.myUserHandle())) { UserInfo userInfo = userManager.getUserInfo(dialogInfo.user.getIdentifier()); messageBuilder.append( getString(R.string.uninstall_application_text_user, userInfo.name)); } else { messageBuilder.append(getString(R.string.uninstall_application_text)); } } dialogBuilder.setTitle(appLabel); dialogBuilder.setIcon(dialogInfo.appInfo.loadIcon(pm)); dialogBuilder.setPositiveButton(android.R.string.ok, this); dialogBuilder.setNegativeButton(android.R.string.cancel, this); dialogBuilder.setMessage(messageBuilder.toString()); return dialogBuilder.create(); } @Override public void onClick(DialogInterface dialog, int which) { if (which == Dialog.BUTTON_POSITIVE) { ((UninstallerActivity) getActivity()).startUninstallProgress(); } else { ((UninstallerActivity) getActivity()).dispatchAborted(); } } @Override public void onDismiss(DialogInterface dialog) { super.onDismiss(dialog); if (isAdded()) { getActivity().finish(); } } /** * Returns whether there is only one user on this device, not including * the system-only user. */ private boolean isSingleUser(UserManager userManager) { final int userCount = userManager.getUserCount(); return userCount == 1 || (UserManager.isSplitSystemUser() && userCount == 2); } } public static class AppNotFoundDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new AlertDialog.Builder(getActivity()) .setTitle(R.string.app_not_found_dlg_title) .setMessage(R.string.app_not_found_dlg_text) .setNeutralButton(android.R.string.ok, null) .create(); } @Override public void onDismiss(DialogInterface dialog) { super.onDismiss(dialog); if (isAdded()) { ((UninstallerActivity) getActivity()).dispatchAborted(); getActivity().setResult(Activity.RESULT_FIRST_USER); getActivity().finish(); } } } static class DialogInfo { ApplicationInfo appInfo; ActivityInfo activityInfo; boolean allUsers; UserHandle user; IBinder callback; public static class DialogInfo { public ApplicationInfo appInfo; public ActivityInfo activityInfo; public boolean allUsers; public UserHandle user; public IBinder callback; } private String mPackageName; Loading Loading @@ -197,7 +95,7 @@ public class UninstallerActivity extends Activity { try { mDialogInfo.appInfo = pm.getApplicationInfo(mPackageName, PackageManager.GET_UNINSTALLED_PACKAGES, mDialogInfo.user.getIdentifier()); PackageManager.MATCH_UNINSTALLED_PACKAGES, mDialogInfo.user.getIdentifier()); } catch (RemoteException e) { Log.e(TAG, "Unable to get packageName. Package manager is dead?"); } Loading @@ -224,6 +122,10 @@ public class UninstallerActivity extends Activity { showConfirmationDialog(); } public DialogInfo getDialogInfo() { return mDialogInfo; } private void showConfirmationDialog() { showDialogFragment(new UninstallAlertDialogFragment()); } Loading @@ -241,7 +143,7 @@ public class UninstallerActivity extends Activity { fragment.show(ft, "dialog"); } void startUninstallProgress() { public void startUninstallProgress() { Intent newIntent = new Intent(Intent.ACTION_VIEW); newIntent.putExtra(Intent.EXTRA_USER, mDialogInfo.user); newIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, mDialogInfo.allUsers); Loading @@ -255,7 +157,7 @@ public class UninstallerActivity extends Activity { startActivity(newIntent); } void dispatchAborted() { public void dispatchAborted() { if (mDialogInfo != null && mDialogInfo.callback != null) { final IPackageDeleteObserver2 observer = IPackageDeleteObserver2.Stub.asInterface( mDialogInfo.callback); Loading
src/com/android/packageinstaller/handheld/AppNotFoundDialogFragment.java 0 → 100644 +51 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.packageinstaller.handheld; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; import android.content.DialogInterface; import android.os.Bundle; import com.android.packageinstaller.R; import com.android.packageinstaller.UninstallerActivity; @SuppressLint("NewApi") public class AppNotFoundDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new AlertDialog.Builder(getActivity()) .setTitle(R.string.app_not_found_dlg_title) .setMessage(R.string.app_not_found_dlg_text) .setNeutralButton(android.R.string.ok, null) .create(); } @Override public void onDismiss(DialogInterface dialog) { super.onDismiss(dialog); if (isAdded()) { ((UninstallerActivity) getActivity()).dispatchAborted(); getActivity().setResult(Activity.RESULT_FIRST_USER); getActivity().finish(); } } }
src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java 0 → 100644 +113 −0 File added.Preview size limit exceeded, changes collapsed. Show changes