Make DPM API for disabling keyguard widgets more generic

This change renames the widget-specific API to be more generic
to allow further disabling of keyguard-specific customizations
in the future.  Currently only allows disabling widgets and the
secure camera but can now easily be extended to disable other
features we add.

Fixes bug: 7021368

Change-Id: I3934cc2e7c64e0c6d511efb86980fc38a849708d
diff --git a/api/current.txt b/api/current.txt
index ba74e38..6d69550 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4207,7 +4207,7 @@
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static final int USES_ENCRYPTED_STORAGE = 7; // 0x7
     field public static final int USES_POLICY_DISABLE_CAMERA = 8; // 0x8
-    field public static final int USES_POLICY_DISABLE_KEYGUARD_WIDGETS = 9; // 0x9
+    field public static final int USES_POLICY_DISABLE_KEYGUARD_FEATURES = 9; // 0x9
     field public static final int USES_POLICY_EXPIRE_PASSWORD = 6; // 0x6
     field public static final int USES_POLICY_FORCE_LOCK = 3; // 0x3
     field public static final int USES_POLICY_LIMIT_PASSWORD = 0; // 0x0
@@ -4243,7 +4243,7 @@
     method public java.util.List<android.content.ComponentName> getActiveAdmins();
     method public boolean getCameraDisabled(android.content.ComponentName);
     method public int getCurrentFailedPasswordAttempts();
-    method public int getKeyguardWidgetsDisabled(android.content.ComponentName);
+    method public int getKeyguardDisabledFeatures(android.content.ComponentName);
     method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
     method public long getMaximumTimeToLock(android.content.ComponentName);
     method public long getPasswordExpiration(android.content.ComponentName);
@@ -4267,7 +4267,7 @@
     method public void removeActiveAdmin(android.content.ComponentName);
     method public boolean resetPassword(java.lang.String, int);
     method public void setCameraDisabled(android.content.ComponentName, boolean);
-    method public void setKeyguardWidgetsDisabled(android.content.ComponentName, int);
+    method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
     method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
     method public void setMaximumTimeToLock(android.content.ComponentName, long);
     method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
@@ -4291,8 +4291,10 @@
     field public static final int ENCRYPTION_STATUS_UNSUPPORTED = 0; // 0x0
     field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
     field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
-    field public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 2147483647; // 0x7fffffff
-    field public static final int KEYGUARD_DISABLE_WIDGETS_NONE = 0; // 0x0
+    field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff
+    field public static final int KEYGUARD_DISABLE_FEATURES_NONE = 0; // 0x0
+    field public static final int KEYGUARD_DISABLE_SECURE_CAMERA = 2; // 0x2
+    field public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 1; // 0x1
     field public static final int PASSWORD_QUALITY_ALPHABETIC = 262144; // 0x40000
     field public static final int PASSWORD_QUALITY_ALPHANUMERIC = 327680; // 0x50000
     field public static final int PASSWORD_QUALITY_BIOMETRIC_WEAK = 32768; // 0x8000
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index c8062ca..b351811 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -144,7 +144,7 @@
      * <p>To control this policy, the device admin must have a "disable-keyguard-widgets"
      * tag in the "uses-policies" section of its meta-data.
      */
-    public static final int USES_POLICY_DISABLE_KEYGUARD_WIDGETS = 9;
+    public static final int USES_POLICY_DISABLE_KEYGUARD_FEATURES = 9;
 
     /** @hide */
     public static class PolicyInfo {
@@ -194,9 +194,9 @@
                 com.android.internal.R.string.policylab_disableCamera,
                 com.android.internal.R.string.policydesc_disableCamera));
         sPoliciesDisplayOrder.add(new PolicyInfo(
-                USES_POLICY_DISABLE_KEYGUARD_WIDGETS, "disable-keyguard-widgets",
-                com.android.internal.R.string.policylab_disableKeyguardWidgets,
-                com.android.internal.R.string.policydesc_disableKeyguardWidgets));
+                USES_POLICY_DISABLE_KEYGUARD_FEATURES, "disable-keyguard-features",
+                com.android.internal.R.string.policylab_disableKeyguardFeatures,
+                com.android.internal.R.string.policydesc_disableKeyguardFeatures));
 
         for (int i=0; i<sPoliciesDisplayOrder.size(); i++) {
             PolicyInfo pi = sPoliciesDisplayOrder.get(i);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 600d02a..6966793 100755
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1215,12 +1215,22 @@
     /**
      * Widgets are enabled in keyguard
      */
-    public static final int KEYGUARD_DISABLE_WIDGETS_NONE = 0;
+    public static final int KEYGUARD_DISABLE_FEATURES_NONE = 0;
 
     /**
      * Disable all keyguard widgets
      */
-    public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 0x7fffffff;
+    public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 1 << 0;
+
+    /**
+     * Disable the camera on secure keyguard screens (e.g. PIN/Pattern/Password)
+     */
+    public static final int KEYGUARD_DISABLE_SECURE_CAMERA = 1 << 1;
+
+    /**
+     * Disable all current and future keyguard customizations
+     */
+    public static final int KEYGUARD_DISABLE_FEATURES_ALL = 0x7fffffff;
 
     /**
      * Called by an application that is administering the device to
@@ -1362,22 +1372,22 @@
     }
 
     /**
-     * Called by an application that is administering the device to disable adding widgets to
-     * keyguard.  After setting this, keyguard widgets will be disabled according to the state
-     * provided.
+     * Called by an application that is administering the device to disable keyguard customizations,
+     * such as widgets. After setting this, keyguard features will be disabled according to the
+     * provided feature list.
      *
      * <p>The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_WIDGETS} to be able to call
+     * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call
      * this method; if it has not, a security exception will be thrown.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param which {@link DevicePolicyManager#KEYGUARD_DISABLE_WIDGETS_ALL} or
-     * {@link DevicePolicyManager#KEYGUARD_DISABLE_WIDGETS_NONE} (the default).
+     * {@link DevicePolicyManager#KEYGUARD_DISABLE_FEATURES_NONE} (the default).
      */
-    public void setKeyguardWidgetsDisabled(ComponentName admin, int which) {
+    public void setKeyguardDisabledFeatures(ComponentName admin, int which) {
         if (mService != null) {
             try {
-                mService.setKeyguardWidgetsDisabled(admin, which, UserHandle.myUserId());
+                mService.setKeyguardDisabledFeatures(admin, which, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1385,25 +1395,25 @@
     }
 
     /**
-     * Determine whether or not widgets have been disabled in keyguard either by the current
+     * Determine whether or not features have been disabled in keyguard either by the current
      * admin, if specified, or all admins.
      * @param admin The name of the admin component to check, or null to check if any admins
-     * have disabled widgets in keyguard.
+     * have disabled features in keyguard.
      */
-    public int getKeyguardWidgetsDisabled(ComponentName admin) {
-        return getKeyguardWidgetsDisabled(admin, UserHandle.myUserId());
+    public int getKeyguardDisabledFeatures(ComponentName admin) {
+        return getKeyguardDisabledFeatures(admin, UserHandle.myUserId());
     }
 
     /** @hide per-user version */
-    public int getKeyguardWidgetsDisabled(ComponentName admin, int userHandle) {
+    public int getKeyguardDisabledFeatures(ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
-                return mService.getKeyguardWidgetsDisabled(admin, userHandle);
+                return mService.getKeyguardDisabledFeatures(admin, userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
         }
-        return KEYGUARD_DISABLE_WIDGETS_NONE;
+        return KEYGUARD_DISABLE_FEATURES_NONE;
     }
 
     /**
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index bdfb177..e061ab3 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -82,8 +82,8 @@
     void setCameraDisabled(in ComponentName who, boolean disabled, int userHandle);
     boolean getCameraDisabled(in ComponentName who, int userHandle);
 
-    void setKeyguardWidgetsDisabled(in ComponentName who, int which, int userHandle);
-    int getKeyguardWidgetsDisabled(in ComponentName who, int userHandle);
+    void setKeyguardDisabledFeatures(in ComponentName who, int which, int userHandle);
+    int getKeyguardDisabledFeatures(in ComponentName who, int userHandle);
 
     void setActiveAdmin(in ComponentName policyReceiver, boolean refreshing, int userHandle);
     boolean isAdminActive(in ComponentName policyReceiver, int userHandle);
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 761bfba..ae2cffe 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -878,7 +878,7 @@
     <!-- [CHAR LIMIT=NONE] Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_freezeScreen">Allows the application to temporarily freeze
         the screen for a full-screen transition.</string>
-    
+
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_injectEvents">press keys and control buttons</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -1810,9 +1810,9 @@
     <!-- Description of policy access to disable all device cameras [CHAR LIMIT=110]-->
     <string name="policydesc_disableCamera">Prevent use of all device cameras.</string>
     <!-- Title of policy access to disable all device cameras [CHAR LIMIT=30]-->
-    <string name="policylab_disableKeyguardWidgets">Disable widgets on keyguard</string>
+    <string name="policylab_disableKeyguardFeatures">Disable features in keyguard</string>
     <!-- Description of policy access to disable all device cameras [CHAR LIMIT=110]-->
-    <string name="policydesc_disableKeyguardWidgets">Prevent use of some or all widgets on keyguard.</string>
+    <string name="policydesc_disableKeyguardFeatures">Prevent use of some features in keyguard.</string>
 
     <!-- The order of these is important, don't reorder without changing Contacts.java --> <skip />
     <!-- Phone number types from android.provider.Contacts. This could be used when adding a new phone number for a contact, for example. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5612360..6dd3fc9 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -630,7 +630,7 @@
   <java-symbol type="string" name="policydesc_setGlobalProxy" />
   <java-symbol type="string" name="policydesc_watchLogin" />
   <java-symbol type="string" name="policydesc_wipeData" />
-  <java-symbol type="string" name="policydesc_disableKeyguardWidgets" />
+  <java-symbol type="string" name="policydesc_disableKeyguardFeatures" />
   <java-symbol type="string" name="policylab_disableCamera" />
   <java-symbol type="string" name="policylab_encryptedStorage" />
   <java-symbol type="string" name="policylab_expirePassword" />
@@ -640,7 +640,7 @@
   <java-symbol type="string" name="policylab_setGlobalProxy" />
   <java-symbol type="string" name="policylab_watchLogin" />
   <java-symbol type="string" name="policylab_wipeData" />
-  <java-symbol type="string" name="policylab_disableKeyguardWidgets" />
+  <java-symbol type="string" name="policylab_disableKeyguardFeatures" />
   <java-symbol type="string" name="postalTypeCustom" />
   <java-symbol type="string" name="postalTypeHome" />
   <java-symbol type="string" name="postalTypeOther" />
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
index bbd07a3..636f31f 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -684,10 +684,13 @@
     private void maybePopulateWidgets() {
         DevicePolicyManager dpm =
                 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
-        if (dpm != null && dpm.getKeyguardWidgetsDisabled(null, mLockPatternUtils.getCurrentUser())
-                != DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_NONE) {
-            Log.v(TAG, "Keyguard widgets disabled because of device policy admin");
-            return;
+        if (dpm != null) {
+            final int currentUser = mLockPatternUtils.getCurrentUser();
+            final int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, currentUser);
+            if ((disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL) != 0) {
+                Log.v(TAG, "Keyguard widgets disabled because of device policy admin");
+                return;
+            }
         }
         inflateAndAddUserSelectorWidgetIfNecessary();
 
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
index dc20e74..78cfe53 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
@@ -18,6 +18,7 @@
 import android.animation.ObjectAnimator;
 import android.app.ActivityManagerNative;
 import android.app.SearchManager;
+import android.app.admin.DevicePolicyManager;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.Context;
@@ -192,8 +193,12 @@
 
     private void updateTargets() {
         int currentUserHandle = mLockPatternUtils.getCurrentUser();
-        boolean disabledByAdmin = mLockPatternUtils.getDevicePolicyManager()
-                .getCameraDisabled(null, currentUserHandle);
+        DevicePolicyManager dpm = mLockPatternUtils.getDevicePolicyManager();
+        int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, currentUserHandle);
+        boolean secureCameraDisabled = mLockPatternUtils.isSecure()
+                && (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0;
+        boolean cameraDisabledByAdmin = dpm.getCameraDisabled(null, currentUserHandle)
+                || secureCameraDisabled;
         final KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(getContext());
         boolean disabledBySimState = monitor.isSimLocked();
         boolean cameraTargetPresent =
@@ -201,7 +206,7 @@
         boolean searchTargetPresent =
             isTargetPresent(com.android.internal.R.drawable.ic_action_assist_generic);
 
-        if (disabledByAdmin) {
+        if (cameraDisabledByAdmin) {
             Log.v(TAG, "Camera disabled by Device Policy");
         } else if (disabledBySimState) {
             Log.v(TAG, "Camera disabled by Sim State");
@@ -209,7 +214,7 @@
         boolean searchActionAvailable =
                 ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
                 .getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
-        mCameraDisabled = disabledByAdmin || disabledBySimState || !cameraTargetPresent;
+        mCameraDisabled = cameraDisabledByAdmin || disabledBySimState || !cameraTargetPresent;
         mSearchDisabled = disabledBySimState || !searchActionAvailable || !searchTargetPresent;
         updateResources();
     }
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index aec5d6e..83fa55b 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -212,8 +212,8 @@
         static final long DEF_PASSWORD_EXPIRATION_DATE = 0;
         long passwordExpirationDate = DEF_PASSWORD_EXPIRATION_DATE;
 
-        static final int DEF_KEYGUARD_WIDGET_DISABLED = 0; // none
-        int disableKeyguardWidgets = DEF_KEYGUARD_WIDGET_DISABLED;
+        static final int DEF_KEYGUARD_FEATURES_DISABLED = 0; // none
+        int disabledKeyguardFeatures = DEF_KEYGUARD_FEATURES_DISABLED;
 
         boolean encryptionRequested = false;
         boolean disableCamera = false;
@@ -328,10 +328,10 @@
                 out.attribute(null, "value", Boolean.toString(disableCamera));
                 out.endTag(null, "disable-camera");
             }
-            if (disableKeyguardWidgets != DEF_KEYGUARD_WIDGET_DISABLED) {
-                out.startTag(null, "disable-keyguard-widgets");
-                out.attribute(null, "value", Integer.toString(disableKeyguardWidgets));
-                out.endTag(null, "disable-keyguard-widgets");
+            if (disabledKeyguardFeatures != DEF_KEYGUARD_FEATURES_DISABLED) {
+                out.startTag(null, "disable-keyguard-features");
+                out.attribute(null, "value", Integer.toString(disabledKeyguardFeatures));
+                out.endTag(null, "disable-keyguard-features");
             }
         }
 
@@ -2300,18 +2300,18 @@
     }
 
     /**
-     * Selectively disable keyguard widgets.
+     * Selectively disable keyguard features.
      */
-    public void setKeyguardWidgetsDisabled(ComponentName who, int which, int userHandle) {
+    public void setKeyguardDisabledFeatures(ComponentName who, int which, int userHandle) {
         enforceCrossUserPermission(userHandle);
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
             }
             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
-                    DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_WIDGETS);
-            if ((ap.disableKeyguardWidgets & which) != which) {
-                ap.disableKeyguardWidgets |= which;
+                    DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
+            if (ap.disabledKeyguardFeatures != which) {
+                ap.disabledKeyguardFeatures = which;
                 saveSettingsLocked(userHandle);
             }
             syncDeviceCapabilitiesLocked(getUserData(userHandle));
@@ -2319,24 +2319,24 @@
     }
 
     /**
-     * Gets the disabled state for widgets in keyguard for the given admin,
+     * Gets the disabled state for features in keyguard for the given admin,
      * or the aggregate of all active admins if who is null.
      */
-    public int getKeyguardWidgetsDisabled(ComponentName who, int userHandle) {
+    public int getKeyguardDisabledFeatures(ComponentName who, int userHandle) {
         enforceCrossUserPermission(userHandle);
         synchronized (this) {
             if (who != null) {
                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
-                return (admin != null) ? admin.disableKeyguardWidgets : 0;
+                return (admin != null) ? admin.disabledKeyguardFeatures : 0;
             }
 
-            // Determine whether or not keyguard widgets are disabled for any active admins.
+            // Determine which keyguard features are disabled for any active admins.
             DevicePolicyData policy = getUserData(userHandle);
             final int N = policy.mAdminList.size();
             int which = 0;
             for (int i = 0; i < N; i++) {
                 ActiveAdmin admin = policy.mAdminList.get(i);
-                which |= admin.disableKeyguardWidgets;
+                which |= admin.disabledKeyguardFeatures;
             }
             return which;
         }