First pass at new device policy and administration APIs.
This adds new DevicAdmin, DevicePolicyManager, and DeviceAdminInfo classes.
See the java docs for each on documentation on them. Basically: a DeviceAdmin
is what you derive from to administer a device; DevicePolicyManager is what you
use to apply and check your policy requirements and perform other administration
tasks.
diff --git a/core/java/android/app/DevicePolicyManager.java b/core/java/android/app/DevicePolicyManager.java
new file mode 100644
index 0000000..4fdfe0a
--- /dev/null
+++ b/core/java/android/app/DevicePolicyManager.java
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2010 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 android.app;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import java.io.IOException;
+
+/**
+ * Public interface for managing policies enforced on a device. Most clients
+ * of this class must have published a {@link DeviceAdmin} that the user
+ * has currently enabled.
+ */
+public class DevicePolicyManager {
+ private static String TAG = "DevicePolicyManager";
+ private static boolean DEBUG = false;
+ private static boolean localLOGV = DEBUG || android.util.Config.LOGV;
+
+ private final Context mContext;
+ private final Handler mHandler;
+ private final IDevicePolicyManager mService;
+
+ /*package*/ DevicePolicyManager(Context context, Handler handler) {
+ mContext = context;
+ mHandler = handler;
+ mService = IDevicePolicyManager.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
+ }
+
+ /**
+ * Activity action: ask the user to add a new device administrator to the system.
+ * The desired policy is the ComponentName of the policy in the
+ * {@link #EXTRA_DEVICE_ADMIN} extra field. This will invoke a UI to
+ * bring the user through adding the device administrator to the system (or
+ * allowing them to reject it).
+ *
+ * <p>Note: the current platform can only have one device administrator
+ * active at a time. If you make this request while there is already
+ * an active administrator, this new request will be canceled automatically.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_ADD_DEVICE_ADMIN
+ = "android.app.action.ADD_DEVICE_ADMIN";
+
+ /**
+ * The ComponentName of the administrator component.
+ *
+ * @see #ACTION_ADD_DEVICE_ADMIN
+ */
+ public static final String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
+
+ /**
+ * Activity action: have the user enter a new password. This activity
+ * should be launched after using {@link #setPasswordMode(ComponentName, int)}
+ * or {@link #setMinimumPasswordLength(ComponentName, int)} to have the
+ * user enter a new password that meets the current requirements. If the
+ * current password is sufficient, the activity will exit immediately without
+ * being displayed to the user. Upon receiving a result from this activity,
+ * you can check the new password characteristics to see if they are
+ * sufficient.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_SET_NEW_PASSWORD
+ = "android.app.action.SET_NEW_PASSWORD";
+
+ /**
+ * Return true if the given administrator component is currently
+ * active (enabled) in the system.
+ */
+ public boolean isAdminActive(ComponentName who) {
+ if (mService != null) {
+ try {
+ return who.equals(mService.getActiveAdmin());
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Remove a current administration component. This can only be called
+ * by the application that owns the administration component; if you
+ * try to remove someone else's component, a security exception will be
+ * thrown.
+ */
+ public void removeActiveAdmin(ComponentName who) {
+ if (mService != null) {
+ try {
+ mService.removeActiveAdmin(who);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * Constant for {@link #setPasswordMode}: the policy has no requirements
+ * for the password.
+ */
+ public static final int PASSWORD_MODE_UNSPECIFIED = 0;
+
+ /**
+ * Constant for {@link #setPasswordMode}: the user must have at least a
+ * numeric password.
+ */
+ public static final int PASSWORD_MODE_NUMERIC = 1000;
+
+ /**
+ * Constant for {@link #setPasswordMode}: the user must have at least an
+ * alphanumeric password.
+ */
+ public static final int PASSWORD_MODE_ALPHANUMERIC = 2000;
+
+ /**
+ * Called by an application that is administering the device to set the
+ * password restrictions it is imposing. After setting this, the user
+ * will not be able to enter a new password that is not at least as
+ * restrictive as what has been set. Note that the current password
+ * will remain until the user has set a new one, so the change does not
+ * take place immediately. To prompt the user for a new password, use
+ * {@link #ACTION_SET_NEW_PASSWORD} after setting this value.
+ *
+ * @param admin Which {@link DeviceAdmin} this request is associated with.
+ * @param mode The new desired mode. One of
+ * {@link #PASSWORD_MODE_UNSPECIFIED}, {@link #PASSWORD_MODE_NUMERIC},
+ * or {@link #PASSWORD_MODE_ALPHANUMERIC}.
+ */
+ public void setPasswordMode(ComponentName admin, int mode) {
+ if (mService != null) {
+ try {
+ mService.setPasswordMode(admin, mode);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * Retrieve the current password mode that is in effect due to all
+ * device admins.
+ */
+ public int getPasswordMode() {
+ if (mService != null) {
+ try {
+ return mService.getPasswordMode();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return PASSWORD_MODE_UNSPECIFIED;
+ }
+
+ /**
+ * Retrieve the password mode associated with the last password the
+ * user selected.
+ */
+ public int getActivePasswordMode() {
+ if (mService != null) {
+ try {
+ return mService.getActivePasswordMode();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return PASSWORD_MODE_UNSPECIFIED;
+ }
+
+ /**
+ * Called by an application that is administering the device to set the
+ * minimum allowed password length. After setting this, the user
+ * will not be able to enter a new password that is not at least as
+ * restrictive as what has been set. Note that the current password
+ * will remain until the user has set a new one, so the change does not
+ * take place immediately. To prompt the user for a new password, use
+ * {@link #ACTION_SET_NEW_PASSWORD} after setting this value. This
+ * constraint is only imposed if the administrator has also requested either
+ * {@link #PASSWORD_MODE_NUMERIC} or {@link #PASSWORD_MODE_ALPHANUMERIC}
+ * with {@link #setPasswordMode}.
+ *
+ * @param admin Which {@link DeviceAdmin} this request is associated with.
+ * @param length The new desired minimum password length. A value of 0
+ * means there is no restriction.
+ */
+ public void setMinimumPasswordLength(ComponentName admin, int length) {
+ if (mService != null) {
+ try {
+ mService.setMinimumPasswordLength(admin, length);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * Retrieve the current minimum password length that is in effect due to all
+ * device admins.
+ */
+ public int getMinimumPasswordLength() {
+ if (mService != null) {
+ try {
+ return mService.getMinimumPasswordLength();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Retrieve the password length associated with the last password the
+ * user selected.
+ */
+ public int getActiveMinimumPasswordLength() {
+ if (mService != null) {
+ try {
+ return mService.getActiveMinimumPasswordLength();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Retrieve the number of times the user has failed at entering a
+ * password since that last successful password entry.
+ */
+ public int getCurrentFailedPasswordAttempts() {
+ if (mService != null) {
+ try {
+ return mService.getCurrentFailedPasswordAttempts();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Called by an application that is administering the device to set the
+ * maximum time for user activity until the device will lock. This limits
+ * the length that the user can set. It takes effect immediately.
+ *
+ * @param admin Which {@link DeviceAdmin} this request is associated with.
+ * @param timeMs The new desired maximum time to lock in milliseconds.
+ * A value of 0 means there is no restriction.
+ */
+ public void setMaximumTimeToLock(ComponentName admin, long timeMs) {
+ if (mService != null) {
+ try {
+ mService.setMaximumTimeToLock(admin, timeMs);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * Retrieve the current maximum time to lock that is in effect due to all
+ * device admins. Returns 0 if no maximum is set.
+ */
+ public long getMaximumTimeToLock() {
+ if (mService != null) {
+ try {
+ return mService.getMaximumTimeToLock();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Constant for {@link #wipeData}: perform a low-level format of data
+ * storage.
+ */
+ public static final int WIPE_LOW_LEVEL_FORMAT = 0x0001;
+
+ /**
+ * Constant for {@link #wipeData}: also wipe any external storage.
+ */
+ public static final int WIPE_EXTERNAL_STORAGE = 0x0002;
+
+ /**
+ * Ask the user date be wiped. This will cause the device to reboot,
+ * erasing all user data while next booting up.
+ *
+ * @param flags Bit mask of additional options: currently
+ * {@link #WIPE_LOW_LEVEL_FORMAT} and {@link #WIPE_EXTERNAL_STORAGE}.
+ */
+ public void wipeData(int flags) {
+ if (mService != null) {
+ try {
+ mService.wipeData(flags);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void setActiveAdmin(ComponentName policyReceiver) {
+ if (mService != null) {
+ try {
+ mService.setActiveAdmin(policyReceiver);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public ComponentName getActiveAdmin() {
+ if (mService != null) {
+ try {
+ return mService.getActiveAdmin();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @hide
+ */
+ public DeviceAdminInfo getActiveAdminInfo() {
+ ComponentName cn = getActiveAdmin();
+ if (cn == null) {
+ return null;
+ }
+
+ ActivityInfo ai;
+ try {
+ ai = mContext.getPackageManager().getReceiverInfo(cn,
+ PackageManager.GET_META_DATA);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Unable to retrieve device policy " + cn, e);
+ return null;
+ }
+
+ ResolveInfo ri = new ResolveInfo();
+ ri.activityInfo = ai;
+
+ try {
+ return new DeviceAdminInfo(mContext, ri);
+ } catch (XmlPullParserException e) {
+ Log.w(TAG, "Unable to parse device policy " + cn, e);
+ return null;
+ } catch (IOException e) {
+ Log.w(TAG, "Unable to parse device policy " + cn, e);
+ return null;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void setActivePasswordState(int mode, int length) {
+ if (mService != null) {
+ try {
+ mService.setActivePasswordState(mode, length);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void reportFailedPasswordAttempt() {
+ if (mService != null) {
+ try {
+ mService.reportFailedPasswordAttempt();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void reportSuccessfulPasswordAttempt() {
+ if (mService != null) {
+ try {
+ mService.reportSuccessfulPasswordAttempt();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+}