diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5d093f16e9a..65f522ea557 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4557,6 +4557,8 @@
Deactivate
Uninstall
+
+ Deactivate and Uninstall
Device administrators
diff --git a/src/com/android/settings/DeviceAdminAdd.java b/src/com/android/settings/DeviceAdminAdd.java
index 1ce72f98b18..0c928f6cfb0 100644
--- a/src/com/android/settings/DeviceAdminAdd.java
+++ b/src/com/android/settings/DeviceAdminAdd.java
@@ -77,6 +77,13 @@ public class DeviceAdminAdd extends Activity {
private static final int REQUEST_CODE_UNINSTALL = 1;
+ /**
+ * Optional key to map to the package name of the Device Admin.
+ * Currently only used when uninstalling an active device admin.
+ */
+ public static final String EXTRA_DEVICE_ADMIN_PACKAGE_NAME =
+ "android.app.extra.DEVICE_ADMIN_PACKAGE_NAME";
+
Handler mHandler;
DevicePolicyManager mDPM;
@@ -99,6 +106,7 @@ public class DeviceAdminAdd extends Activity {
Button mUninstallButton;
Button mCancelButton;
+ boolean mUninstalling = false;
boolean mAdding;
boolean mRefreshing;
boolean mWaitingForRemoveMsg;
@@ -123,13 +131,24 @@ public class DeviceAdminAdd extends Activity {
return;
}
+
String action = getIntent().getAction();
ComponentName who = (ComponentName)getIntent().getParcelableExtra(
DevicePolicyManager.EXTRA_DEVICE_ADMIN);
if (who == null) {
- Log.w(TAG, "No component specified in " + action);
- finish();
- return;
+ String packageName = getIntent().getStringExtra(EXTRA_DEVICE_ADMIN_PACKAGE_NAME);
+ for (ComponentName component : mDPM.getActiveAdmins()) {
+ if (component.getPackageName().equals(packageName)) {
+ who = component;
+ mUninstalling = true;
+ break;
+ }
+ }
+ if (who == null) {
+ Log.w(TAG, "No component specified in " + action);
+ finish();
+ return;
+ }
}
if (action != null && action.equals(DevicePolicyManager.ACTION_SET_PROFILE_OWNER)) {
@@ -329,6 +348,9 @@ public class DeviceAdminAdd extends Activity {
}
}
).show();
+ } else if (mUninstalling) {
+ mDPM.uninstallPackageWithActiveAdmins(mDeviceAdmin.getPackageName());
+ finish();
} else if (!mWaitingForRemoveMsg) {
try {
// Don't allow the admin to put a dialog up in front
@@ -524,7 +546,11 @@ public class DeviceAdminAdd extends Activity {
mDeviceAdmin.getActivityInfo().applicationInfo.loadLabel(
getPackageManager())));
setTitle(R.string.active_device_admin_msg);
- mActionButton.setText(R.string.remove_device_admin);
+ if (mUninstalling) {
+ mActionButton.setText(R.string.remove_and_uninstall_device_admin);
+ } else {
+ mActionButton.setText(R.string.remove_device_admin);
+ }
}
String supportMessage = mDPM.getLongSupportMessageForUser(
mDeviceAdmin.getComponent(), UserHandle.myUserId());
@@ -606,7 +632,6 @@ public class DeviceAdminAdd extends Activity {
final Intent uninstallIntent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageURI);
uninstallIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, false);
uninstallIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
-
startActivityForResult(uninstallIntent, REQUEST_CODE_UNINSTALL);
}
}
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index 83159e326d1..a8e8eae4c22 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -68,6 +68,7 @@ import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.AppHeader;
+import com.android.settings.DeviceAdminAdd;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
@@ -116,6 +117,8 @@ public class InstalledAppDetails extends AppInfoBase
// Result code identifiers
public static final int REQUEST_UNINSTALL = 0;
+ private static final int REQUEST_REMOVE_DEVICE_ADMIN = 1;
+
private static final int SUB_INFO_FRAGMENT = 1;
private static final int LOADER_CHART_DATA = 2;
@@ -207,7 +210,7 @@ public class InstalledAppDetails extends AppInfoBase
}
// If this is a device admin, it can't be uninstalled or disabled.
// We do this here so the text of the button is still set correctly.
- if (mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) {
+ if (isBundled && mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) {
enabled = false;
}
@@ -218,6 +221,11 @@ public class InstalledAppDetails extends AppInfoBase
enabled = false;
}
+ // If the uninstall intent is already queued, disable the uninstall button
+ if (mDpm.isUninstallInQueue(mPackageName)) {
+ enabled = false;
+ }
+
// Home apps need special handling. Bundled ones we don't risk downgrading
// because that can interfere with home-key resolution. Furthermore, we
// can't allow uninstallation of the only home app, and we don't want to
@@ -447,6 +455,11 @@ public class InstalledAppDetails extends AppInfoBase
setIntentAndFinish(true, true);
}
}
+ if (requestCode == REQUEST_REMOVE_DEVICE_ADMIN) {
+ if (!refreshUi()) {
+ setIntentAndFinish(true, true);
+ }
+ }
}
// Utility method to set application label and icon.
@@ -717,6 +730,14 @@ public class InstalledAppDetails extends AppInfoBase
}
String packageName = mAppEntry.info.packageName;
if(v == mUninstallButton) {
+ if (mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) {
+ Activity activity = getActivity();
+ Intent uninstallDAIntent = new Intent(activity, DeviceAdminAdd.class);
+ uninstallDAIntent.putExtra(DeviceAdminAdd.EXTRA_DEVICE_ADMIN_PACKAGE_NAME,
+ mPackageName);
+ activity.startActivityForResult(uninstallDAIntent, REQUEST_REMOVE_DEVICE_ADMIN);
+ return;
+ }
EnforcedAdmin admin = RestrictedLockUtils.checkIfUninstallBlocked(getActivity(),
packageName, mUserId);
if (admin != null) {