Introduced DO_NOT_ASK_CREDENTIALS_ON_BOOT flag

A new flag for DPM.resetPassword() method that specifies that the
device should be decrypted without asking for the password or pattern.

Bug 19250601

Related CL in Settings App: https://googleplex-android-review.git.corp.google.com/#/c/670206

Change-Id: I9ca3472dc18e66e618ff772dee16ca4a450e9997
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 35b8a8ee..9e2da61 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1635,6 +1635,23 @@
     }
 
     /**
+     * Queries whether {@link #DO_NOT_ASK_CREDENTIALS_ON_BOOT} flag is set.
+     *
+     * @return true if DO_NOT_ASK_CREDENTIALS_ON_BOOT flag is set.
+     * @hide
+     */
+    public boolean getDoNotAskCredentialsOnBoot() {
+        if (mService != null) {
+            try {
+                return mService.getDoNotAskCredentialsOnBoot();
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed to call getDoNotAskCredentialsOnBoot()", e);
+            }
+        }
+        return false;
+    }
+
+    /**
      * Setting this to a value greater than zero enables a built-in policy
      * that will perform a device wipe after too many incorrect
      * device-unlock passwords have been entered.  This built-in policy combines
@@ -1711,6 +1728,16 @@
     public static final int RESET_PASSWORD_REQUIRE_ENTRY = 0x0001;
 
     /**
+     * Flag for {@link #resetPassword}: don't ask for user credentials on device boot.
+     * If the flag is set, the device can be booted without asking for user password.
+     * The absence of this flag does not change the current boot requirements. This flag
+     * can be set by the device owner only. If the app is not the device owner, the flag
+     * is ignored. Once the flag is set, it cannot be reverted back without resetting the
+     * device to factory defaults.
+     */
+    public static final int DO_NOT_ASK_CREDENTIALS_ON_BOOT = 0x0002;
+
+    /**
      * Force a new device unlock password (the password needed to access the
      * entire device, not for individual accounts) on the user.  This takes
      * effect immediately.
@@ -1733,7 +1760,8 @@
      * <p>Calling this from a managed profile will throw a security exception.
      *
      * @param password The new password for the user. Null or empty clears the password.
-     * @param flags May be 0 or {@link #RESET_PASSWORD_REQUIRE_ENTRY}.
+     * @param flags May be 0 or combination of {@link #RESET_PASSWORD_REQUIRE_ENTRY} and
+     *              {@link #DO_NOT_ASK_CREDENTIALS_ON_BOOT}.
      * @return Returns true if the password was applied, or false if it is
      * not acceptable for the current constraints.
      */
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 48ed45b..1f7498e 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -224,4 +224,5 @@
 
     boolean setKeyguardEnabledState(in ComponentName admin, boolean enabled);
     void setStatusBarEnabledState(in ComponentName who, boolean enabled);
+    boolean getDoNotAskCredentialsOnBoot();
 }
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index aa60eba..1096e34 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -24,7 +24,6 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
 import android.os.AsyncTask;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -32,7 +31,6 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.os.storage.IMountService;
 import android.os.storage.StorageManager;
 import android.provider.Settings;
@@ -544,8 +542,7 @@
             // Update the device encryption password.
             if (userId == UserHandle.USER_OWNER
                     && LockPatternUtils.isDeviceEncryptionEnabled()) {
-                final boolean required = isCredentialRequiredToDecrypt(true);
-                if (!required) {
+                if (!shouldEncryptWithCredentials(true)) {
                     clearEncryptionPassword();
                 } else {
                     String stringPattern = patternToString(pattern);
@@ -759,7 +756,7 @@
             // Update the device encryption password.
             if (userHandle == UserHandle.USER_OWNER
                     && LockPatternUtils.isDeviceEncryptionEnabled()) {
-                if (!isCredentialRequiredToDecrypt(true)) {
+                if (!shouldEncryptWithCredentials(true)) {
                     clearEncryptionPassword();
                 } else {
                     boolean numeric = computedQuality
@@ -1238,4 +1235,12 @@
         Settings.Global.putInt(mContext.getContentResolver(),
                 Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, required ? 1 : 0);
     }
+
+    private boolean isDoNotAskCredentialsOnBootSet() {
+        return mDevicePolicyManager.getDoNotAskCredentialsOnBoot();
+    }
+
+    private boolean shouldEncryptWithCredentials(boolean defaultValue) {
+        return isCredentialRequiredToDecrypt(defaultValue) && !isDoNotAskCredentialsOnBootSet();
+    }
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8f4d9a3..1f529ca 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2404,6 +2404,12 @@
         android:description="@string/permdesc_bindCarrierConfigService"
         android:protectionLevel="signature|system" />
 
+    <!-- Allows an application to query whether DO_NOT_ASK_CREDENTIALS_ON_BOOT
+         flag is set.
+         @hide -->
+    <permission android:name="android.permission.QUERY_DO_NOT_ASK_CREDENTIALS_ON_BOOT"
+                android:protectionLevel="signature" />
+
     <!-- The system process is explicitly the only one allowed to launch the
          confirmation UI for full backup/restore -->
     <uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 7123cc0..6f554f08 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1302,7 +1302,6 @@
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_sdcardWrite" product="default">Allows the app to write to the SD card.</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_use_sip">make/receive SIP calls</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->