Update DevicePolicyManager with ability to disable keyguard widgets

Change-Id: I5876e9e180b2a995aaa355fbbb2b67cebb86104d
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index 1c37414..c8062ca 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -50,23 +50,23 @@
  */
 public final class DeviceAdminInfo implements Parcelable {
     static final String TAG = "DeviceAdminInfo";
-    
+
     /**
      * A type of policy that this device admin can use: limit the passwords
      * that the user can select, via {@link DevicePolicyManager#setPasswordQuality}
      * and {@link DevicePolicyManager#setPasswordMinimumLength}.
-     * 
+     *
      * <p>To control this policy, the device admin must have a "limit-password"
      * tag in the "uses-policies" section of its meta-data.
      */
     public static final int USES_POLICY_LIMIT_PASSWORD = 0;
-    
+
     /**
      * A type of policy that this device admin can use: able to watch login
      * attempts from the user, via {@link DeviceAdminReceiver#ACTION_PASSWORD_FAILED},
      * {@link DeviceAdminReceiver#ACTION_PASSWORD_SUCCEEDED}, and
      * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts}.
-     * 
+     *
      * <p>To control this policy, the device admin must have a "watch-login"
      * tag in the "uses-policies" section of its meta-data.
      */
@@ -76,7 +76,7 @@
      * A type of policy that this device admin can use: able to reset the
      * user's password via
      * {@link DevicePolicyManager#resetPassword}.
-     * 
+     *
      * <p>To control this policy, the device admin must have a "reset-password"
      * tag in the "uses-policies" section of its meta-data.
      */
@@ -87,7 +87,7 @@
      * to lock via{@link DevicePolicyManager#lockNow} or limit the
      * maximum lock timeout for the device via
      * {@link DevicePolicyManager#setMaximumTimeToLock}.
-     * 
+     *
      * <p>To control this policy, the device admin must have a "force-lock"
      * tag in the "uses-policies" section of its meta-data.
      */
@@ -97,7 +97,7 @@
      * A type of policy that this device admin can use: able to factory
      * reset the device, erasing all of the user's data, via
      * {@link DevicePolicyManager#wipeData}.
-     * 
+     *
      * <p>To control this policy, the device admin must have a "wipe-data"
      * tag in the "uses-policies" section of its meta-data.
      */
@@ -138,13 +138,21 @@
      */
     public static final int USES_POLICY_DISABLE_CAMERA = 8;
 
+    /**
+     * A type of policy that this device admin can use: disables use of keyguard widgets.
+     *
+     * <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;
+
     /** @hide */
     public static class PolicyInfo {
         public final int ident;
         final public String tag;
         final public int label;
         final public int description;
-        
+
         public PolicyInfo(int identIn, String tagIn, int labelIn, int descriptionIn) {
             ident = identIn;
             tag = tagIn;
@@ -152,11 +160,11 @@
             description = descriptionIn;
         }
     }
-    
+
     static ArrayList<PolicyInfo> sPoliciesDisplayOrder = new ArrayList<PolicyInfo>();
     static HashMap<String, Integer> sKnownPolicies = new HashMap<String, Integer>();
     static SparseArray<PolicyInfo> sRevKnownPolicies = new SparseArray<PolicyInfo>();
-    
+
     static {
         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_WIPE_DATA, "wipe-data",
                 com.android.internal.R.string.policylab_wipeData,
@@ -185,6 +193,10 @@
         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_DISABLE_CAMERA, "disable-camera",
                 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));
 
         for (int i=0; i<sPoliciesDisplayOrder.size(); i++) {
             PolicyInfo pi = sPoliciesDisplayOrder.get(i);
@@ -192,25 +204,25 @@
             sKnownPolicies.put(pi.tag, pi.ident);
         }
     }
-    
+
     /**
      * The BroadcastReceiver that implements this device admin component.
      */
     final ResolveInfo mReceiver;
-    
+
     /**
      * Whether this should be visible to the user.
      */
     boolean mVisible;
-    
+
     /**
      * The policies this administrator needs access to.
      */
     int mUsesPolicies;
-    
+
     /**
      * Constructor.
-     * 
+     *
      * @param context The Context in which we are parsing the device admin.
      * @param receiver The ResolveInfo returned from the package manager about
      * this device admin's component.
@@ -219,9 +231,9 @@
             throws XmlPullParserException, IOException {
         mReceiver = receiver;
         ActivityInfo ai = receiver.activityInfo;
-        
+
         PackageManager pm = context.getPackageManager();
-        
+
         XmlResourceParser parser = null;
         try {
             parser = ai.loadXmlMetaData(pm, DeviceAdminReceiver.DEVICE_ADMIN_META_DATA);
@@ -229,30 +241,30 @@
                 throw new XmlPullParserException("No "
                         + DeviceAdminReceiver.DEVICE_ADMIN_META_DATA + " meta-data");
             }
-        
+
             Resources res = pm.getResourcesForApplication(ai.applicationInfo);
-            
+
             AttributeSet attrs = Xml.asAttributeSet(parser);
-            
+
             int type;
             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
                     && type != XmlPullParser.START_TAG) {
             }
-            
+
             String nodeName = parser.getName();
             if (!"device-admin".equals(nodeName)) {
                 throw new XmlPullParserException(
                         "Meta-data does not start with device-admin tag");
             }
-            
+
             TypedArray sa = res.obtainAttributes(attrs,
                     com.android.internal.R.styleable.DeviceAdmin);
 
             mVisible = sa.getBoolean(
                     com.android.internal.R.styleable.DeviceAdmin_visible, true);
-            
+
             sa.recycle();
-            
+
             int outerDepth = parser.getDepth();
             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
@@ -290,14 +302,14 @@
         mReceiver = ResolveInfo.CREATOR.createFromParcel(source);
         mUsesPolicies = source.readInt();
     }
-    
+
     /**
      * Return the .apk package that implements this device admin.
      */
     public String getPackageName() {
         return mReceiver.activityInfo.packageName;
     }
-    
+
     /**
      * Return the class name of the receiver component that implements
      * this device admin.
@@ -321,20 +333,20 @@
         return new ComponentName(mReceiver.activityInfo.packageName,
                 mReceiver.activityInfo.name);
     }
-    
+
     /**
      * Load the user-displayed label for this device admin.
-     * 
+     *
      * @param pm Supply a PackageManager used to load the device admin's
      * resources.
      */
     public CharSequence loadLabel(PackageManager pm) {
         return mReceiver.loadLabel(pm);
     }
-    
+
     /**
      * Load user-visible description associated with this device admin.
-     * 
+     *
      * @param pm Supply a PackageManager used to load the device admin's
      * resources.
      */
@@ -351,17 +363,17 @@
         }
         throw new NotFoundException();
     }
-    
+
     /**
      * Load the user-displayed icon for this device admin.
-     * 
+     *
      * @param pm Supply a PackageManager used to load the device admin's
      * resources.
      */
     public Drawable loadIcon(PackageManager pm) {
         return mReceiver.loadIcon(pm);
     }
-    
+
     /**
      * Returns whether this device admin would like to be visible to the
      * user, even when it is not enabled.
@@ -369,7 +381,7 @@
     public boolean isVisible() {
         return mVisible;
     }
-    
+
     /**
      * Return true if the device admin has requested that it be able to use
      * the given policy control.  The possible policy identifier inputs are:
@@ -382,7 +394,7 @@
     public boolean usesPolicy(int policyIdent) {
         return (mUsesPolicies & (1<<policyIdent)) != 0;
     }
-    
+
     /**
      * Return the XML tag name for the given policy identifier.  Valid identifiers
      * are as per {@link #usesPolicy(int)}.  If the given identifier is not
@@ -391,7 +403,7 @@
     public String getTagForPolicy(int policyIdent) {
         return sRevKnownPolicies.get(policyIdent).tag;
     }
-    
+
     /** @hide */
     public ArrayList<PolicyInfo> getUsedPolicies() {
         ArrayList<PolicyInfo> res = new ArrayList<PolicyInfo>();
@@ -403,25 +415,25 @@
         }
         return res;
     }
-    
+
     /** @hide */
     public void writePoliciesToXml(XmlSerializer out)
             throws IllegalArgumentException, IllegalStateException, IOException {
         out.attribute(null, "flags", Integer.toString(mUsesPolicies));
     }
-    
+
     /** @hide */
     public void readPoliciesFromXml(XmlPullParser parser)
             throws XmlPullParserException, IOException {
         mUsesPolicies = Integer.parseInt(
                 parser.getAttributeValue(null, "flags"));
     }
-    
+
     public void dump(Printer pw, String prefix) {
         pw.println(prefix + "Receiver:");
         mReceiver.dump(pw, prefix + "  ");
     }
-    
+
     @Override
     public String toString() {
         return "DeviceAdminInfo{" + mReceiver.activityInfo.name + "}";
@@ -429,7 +441,7 @@
 
     /**
      * Used to package this object into a {@link Parcel}.
-     * 
+     *
      * @param dest The {@link Parcel} to be written.
      * @param flags The flags used for parceling.
      */
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 0b58396..4c55bb3 100755
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1155,6 +1155,16 @@
             = "android.app.action.START_ENCRYPTION";
 
     /**
+     * Widgets are enabled in keyguard
+     */
+    public static final int KEYGUARD_DISABLE_WIDGETS_NONE = 0;
+
+    /**
+     * Disable all keyguard widgets
+     */
+    public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 0x7fffffff;
+
+    /**
      * Called by an application that is administering the device to
      * request that the storage system be encrypted.
      *
@@ -1284,6 +1294,46 @@
     }
 
     /**
+     * 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.
+     *
+     * <p>The calling device admin must have requested
+     * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_WIDGETS} 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).
+     */
+    public void setKeyguardWidgetsDisabled(ComponentName admin, int which) {
+        if (mService != null) {
+            try {
+                mService.setKeyguardWidgetsDisabled(admin, which);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
+     * Determine whether or not widgets 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.
+     */
+    public int getKeyguardWidgetsDisabled(ComponentName admin) {
+        if (mService != null) {
+            try {
+                return mService.getKeyguardWidgetsDisabled(admin);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return KEYGUARD_DISABLE_WIDGETS_NONE;
+    }
+
+    /**
      * @hide
      */
     public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 9419a62..0b7ec12 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -48,7 +48,7 @@
 
     void setPasswordMinimumNonLetter(in ComponentName who, int length);
     int getPasswordMinimumNonLetter(in ComponentName who);
-    
+
     void setPasswordHistoryLength(in ComponentName who, int length);
     int getPasswordHistoryLength(in ComponentName who);
 
@@ -59,17 +59,17 @@
 
     boolean isActivePasswordSufficient();
     int getCurrentFailedPasswordAttempts();
-    
+
     void setMaximumFailedPasswordsForWipe(in ComponentName admin, int num);
     int getMaximumFailedPasswordsForWipe(in ComponentName admin);
-    
+
     boolean resetPassword(String password, int flags);
-    
+
     void setMaximumTimeToLock(in ComponentName who, long timeMs);
     long getMaximumTimeToLock(in ComponentName who);
-    
+
     void lockNow();
-    
+
     void wipeData(int flags);
 
     ComponentName setGlobalProxy(in ComponentName admin, String proxySpec, String exclusionList);
@@ -82,6 +82,9 @@
     void setCameraDisabled(in ComponentName who, boolean disabled);
     boolean getCameraDisabled(in ComponentName who);
 
+    void setKeyguardWidgetsDisabled(in ComponentName who, int which);
+    int getKeyguardWidgetsDisabled(in ComponentName who);
+
     void setActiveAdmin(in ComponentName policyReceiver, boolean refreshing);
     boolean isAdminActive(in ComponentName policyReceiver);
     List<ComponentName> getActiveAdmins();
@@ -89,7 +92,7 @@
     void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result);
     void removeActiveAdmin(in ComponentName policyReceiver);
     boolean hasGrantedPolicy(in ComponentName policyReceiver, int usesPolicy);
-    
+
     void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase,
         int numbers, int symbols, int nonletter);
     void reportFailedPasswordAttempt();
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 8e0eb15..80930b5 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -710,6 +710,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="policylab_disableCamera" />
   <java-symbol type="string" name="policylab_encryptedStorage" />
   <java-symbol type="string" name="policylab_expirePassword" />
@@ -719,6 +720,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="postalTypeCustom" />
   <java-symbol type="string" name="postalTypeHome" />
   <java-symbol type="string" name="postalTypeOther" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 381055f..d2951bf 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1693,6 +1693,10 @@
     <string name="policylab_disableCamera">Disable cameras</string>
     <!-- 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>
+    <!-- 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>
 
     <!-- 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. -->