Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22dbfda9 authored by Andy Stadler's avatar Andy Stadler
Browse files

Add internal plumbing to DPM for encryption

* Add code to persist per-admin setting
* Add hooks for OS-level tie-in (is supported, get / set status)
* Add 3rd API call to get OS status (irrespective of admin settings)
* Remove "REQUESTED" status, no longer relevant with 3rd API
* Fixed bug that impacted global proxy settings
* Update api/11.xml to match current.xml

Bug: 3346770
Change-Id: I56bdf9a7894f6ca4842402c7b82ddb3caf4b37b9
parent db7f3867
Loading
Loading
Loading
Loading
+265 −16
Original line number Diff line number Diff line
@@ -30672,6 +30672,17 @@
<parameter name="listener" type="android.app.FragmentManager.OnBackStackChangedListener">
</parameter>
</method>
<method name="beginTransaction"
 return="android.app.FragmentTransaction"
 abstract="true"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="countBackStackEntries"
 return="int"
 abstract="true"
@@ -30782,7 +30793,7 @@
</method>
<method name="openTransaction"
 return="android.app.FragmentTransaction"
 abstract="true"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
@@ -37816,7 +37827,7 @@
</parameter>
</method>
<method name="getStorageEncryption"
 return="int"
 return="boolean"
 abstract="false"
 native="false"
 synchronized="false"
@@ -37828,6 +37839,17 @@
<parameter name="admin" type="android.content.ComponentName">
</parameter>
</method>
<method name="getStorageEncryptionStatus"
 return="int"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="hasGrantedPolicy"
 return="boolean"
 abstract="false"
@@ -38168,7 +38190,7 @@
 type="int"
 transient="false"
 volatile="false"
 value="3"
 value="2"
 static="true"
 final="true"
 deprecated="not deprecated"
@@ -38179,7 +38201,7 @@
 type="int"
 transient="false"
 volatile="false"
 value="4"
 value="3"
 static="true"
 final="true"
 deprecated="not deprecated"
@@ -38197,17 +38219,6 @@
 visibility="public"
>
</field>
<field name="ENCRYPTION_STATUS_REQUESTED"
 type="int"
 transient="false"
 volatile="false"
 value="2"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="ENCRYPTION_STATUS_UNSUPPORTED"
 type="int"
 transient="false"
@@ -86359,7 +86370,7 @@
<method name="updateTexImage"
 return="void"
 abstract="false"
 native="true"
 native="false"
 synchronized="false"
 static="false"
 final="false"
@@ -95617,6 +95628,17 @@
 visibility="public"
>
</field>
<field name="TOUCHABLE_INSETS_REGION"
 type="int"
 transient="false"
 volatile="false"
 value="3"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="TOUCHABLE_INSETS_VISIBLE"
 type="int"
 transient="false"
@@ -95648,6 +95670,16 @@
 visibility="public"
>
</field>
<field name="touchableRegion"
 type="android.graphics.Region"
 transient="false"
 volatile="false"
 static="false"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="visibleTopInsets"
 type="int"
 transient="false"
@@ -167174,6 +167206,38 @@
<parameter name="dimX" type="int">
</parameter>
</method>
<method name="setFromFieldPacker"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="xoff" type="int">
</parameter>
<parameter name="fp" type="android.renderscript.FieldPacker">
</parameter>
</method>
<method name="setFromFieldPacker"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="xoff" type="int">
</parameter>
<parameter name="component_number" type="int">
</parameter>
<parameter name="fp" type="android.renderscript.FieldPacker">
</parameter>
</method>
<method name="syncAll"
 return="void"
 abstract="false"
@@ -172934,6 +172998,49 @@
 deprecated="not deprecated"
 visibility="public"
>
<method name="bindAllocation"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="va" type="android.renderscript.Allocation">
</parameter>
<parameter name="slot" type="int">
</parameter>
</method>
<method name="invoke"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="protected"
>
<parameter name="slot" type="int">
</parameter>
</method>
<method name="invoke"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="protected"
>
<parameter name="slot" type="int">
</parameter>
<parameter name="v" type="android.renderscript.FieldPacker">
</parameter>
</method>
<method name="setTimeZone"
 return="void"
 abstract="false"
@@ -172947,6 +173054,111 @@
<parameter name="timeZone" type="java.lang.String">
</parameter>
</method>
<method name="setVar"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="index" type="int">
</parameter>
<parameter name="v" type="float">
</parameter>
</method>
<method name="setVar"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="index" type="int">
</parameter>
<parameter name="v" type="double">
</parameter>
</method>
<method name="setVar"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="index" type="int">
</parameter>
<parameter name="v" type="int">
</parameter>
</method>
<method name="setVar"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="index" type="int">
</parameter>
<parameter name="v" type="long">
</parameter>
</method>
<method name="setVar"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="index" type="int">
</parameter>
<parameter name="v" type="boolean">
</parameter>
</method>
<method name="setVar"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="index" type="int">
</parameter>
<parameter name="o" type="android.renderscript.BaseObj">
</parameter>
</method>
<method name="setVar"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="index" type="int">
</parameter>
<parameter name="v" type="android.renderscript.FieldPacker">
</parameter>
</method>
</class>
<class name="Script.Builder"
 extends="java.lang.Object"
@@ -173078,6 +173290,32 @@
 deprecated="not deprecated"
 visibility="public"
>
<constructor name="ScriptC"
 type="android.renderscript.ScriptC"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="protected"
>
<parameter name="id" type="int">
</parameter>
<parameter name="rs" type="android.renderscript.RenderScript">
</parameter>
</constructor>
<constructor name="ScriptC"
 type="android.renderscript.ScriptC"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="protected"
>
<parameter name="rs" type="android.renderscript.RenderScript">
</parameter>
<parameter name="resources" type="android.content.res.Resources">
</parameter>
<parameter name="resourceID" type="int">
</parameter>
</constructor>
</class>
<class name="Short2"
 extends="java.lang.Object"
@@ -183534,6 +183772,17 @@
 visibility="public"
>
</method>
<method name="getObbDir"
 return="java.io.File"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="getPackageCodePath"
 return="java.lang.String"
 abstract="false"
+14 −14
Original line number Diff line number Diff line
@@ -37827,7 +37827,7 @@
</parameter>
</method>
<method name="getStorageEncryption"
 return="int"
 return="boolean"
 abstract="false"
 native="false"
 synchronized="false"
@@ -37839,6 +37839,17 @@
<parameter name="admin" type="android.content.ComponentName">
</parameter>
</method>
<method name="getStorageEncryptionStatus"
 return="int"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="hasGrantedPolicy"
 return="boolean"
 abstract="false"
@@ -38179,7 +38190,7 @@
 type="int"
 transient="false"
 volatile="false"
 value="3"
 value="2"
 static="true"
 final="true"
 deprecated="not deprecated"
@@ -38190,7 +38201,7 @@
 type="int"
 transient="false"
 volatile="false"
 value="4"
 value="3"
 static="true"
 final="true"
 deprecated="not deprecated"
@@ -38208,17 +38219,6 @@
 visibility="public"
>
</field>
<field name="ENCRYPTION_STATUS_REQUESTED"
 type="int"
 transient="false"
 volatile="false"
 value="2"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="ENCRYPTION_STATUS_UNSUPPORTED"
 type="int"
 transient="false"
+44 −25
Original line number Diff line number Diff line
@@ -1093,38 +1093,32 @@ public class DevicePolicyManager {
    }

    /**
     * Result code for {@link #setStorageEncryption} and {@link #getStorageEncryption}:
     * Result code for {@link #setStorageEncryption} and {@link #getStorageEncryptionStatus}:
     * indicating that encryption is not supported.
     */
    public static final int ENCRYPTION_STATUS_UNSUPPORTED = 0;

    /**
     * Result code for {@link #setStorageEncryption} and {@link #getStorageEncryption}:
     * Result code for {@link #setStorageEncryption} and {@link #getStorageEncryptionStatus}:
     * indicating that encryption is supported, but is not currently active.
     */
    public static final int ENCRYPTION_STATUS_INACTIVE = 1;

    /**
     * Result code for {@link #setStorageEncryption} and {@link #getStorageEncryption}:
     * indicating that encryption is not currently active, but has been requested.
     */
    public static final int ENCRYPTION_STATUS_REQUESTED = 2;

    /**
     * Result code for {@link #setStorageEncryption} and {@link #getStorageEncryption}:
     * Result code for {@link #setStorageEncryption} and {@link #getStorageEncryptionStatus}:
     * indicating that encryption is not currently active, but is currently
     * being activated.  This is only reported by devices that support
     * encryption of data and only when the storage is currently
     * undergoing a process of becoming encrypted.  A device that must reboot and/or wipe data
     * to become encrypted will never return this value.
     */
    public static final int ENCRYPTION_STATUS_ACTIVATING = 3;
    public static final int ENCRYPTION_STATUS_ACTIVATING = 2;

    /**
     * Result code for {@link #setStorageEncryption} and {@link #getStorageEncryption}:
     * Result code for {@link #setStorageEncryption} and {@link #getStorageEncryptionStatus}:
     * indicating that encryption is active.
     */
    public static final int ENCRYPTION_STATUS_ACTIVE = 4;
    public static final int ENCRYPTION_STATUS_ACTIVE = 3;

    /**
     * Activity action: begin the process of encrypting data on the device.  This activity should
@@ -1139,14 +1133,7 @@ public class DevicePolicyManager {

    /**
     * Called by an application that is administering the device to
     * request that the storage system be encrypted.  Depending
     * on the returned status code, the caller may proceed in different
     * ways.  If the result is {@link #ENCRYPTION_STATUS_UNSUPPORTED}, the
     * storage system does not support encryption.  If the
     * result is {@link #ENCRYPTION_STATUS_REQUESTED}, use {@link
     * #ACTION_START_ENCRYPTION} to begin the process of encrypting or decrypting the
     * storage.  If the result is {@link #ENCRYPTION_STATUS_ACTIVATING} or
     * {@link #ENCRYPTION_STATUS_ACTIVE}, no further action is required.
     * request that the storage system be encrypted.
     *
     * <p>When multiple device administrators attempt to control device
     * encryption, the most secure, supported setting will always be
@@ -1167,7 +1154,10 @@ public class DevicePolicyManager {
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param encrypt true to request encryption, false to release any previous request
     * @return current status of encryption
     * @return the new request status (for all active admins) - will be one of
     * {@link #ENCRYPTION_STATUS_UNSUPPORTED}, {@link #ENCRYPTION_STATUS_INACTIVE}, or
     * {@link #ENCRYPTION_STATUS_ACTIVE}.  This is the value of the requests;  Use
     * {@link #getStorageEncryptionStatus()} to query the actual device state.
     */
    public int setStorageEncryption(ComponentName admin, boolean encrypt) {
        if (mService != null) {
@@ -1182,12 +1172,14 @@ public class DevicePolicyManager {

    /**
     * Called by an application that is administering the device to
     * determine the encryption status of a specific storage system.
     * determine the requested setting for secure storage.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @return current status of encryption
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.  If null,
     * this will return the requested encryption setting as an aggregate of all active
     * administrators.
     * @return true if the admin(s) are requesting encryption, false if not.
     */
    public int getStorageEncryption(ComponentName admin) {
    public boolean getStorageEncryption(ComponentName admin) {
        if (mService != null) {
            try {
                return mService.getStorageEncryption(admin);
@@ -1195,6 +1187,33 @@ public class DevicePolicyManager {
                Log.w(TAG, "Failed talking with device policy service", e);
            }
        }
        return false;
    }

    /**
     * Called by an application that is administering the device to
     * determine the current encryption status of the device.
     *
     * Depending on the returned status code, the caller may proceed in different
     * ways.  If the result is {@link #ENCRYPTION_STATUS_UNSUPPORTED}, the
     * storage system does not support encryption.  If the
     * result is {@link #ENCRYPTION_STATUS_INACTIVE}, use {@link
     * #ACTION_START_ENCRYPTION} to begin the process of encrypting or decrypting the
     * storage.  If the result is {@link #ENCRYPTION_STATUS_ACTIVATING} or
     * {@link #ENCRYPTION_STATUS_ACTIVE}, no further action is required.
     *
     * @return current status of encryption.  The value will be one of
     * {@link #ENCRYPTION_STATUS_UNSUPPORTED}, {@link #ENCRYPTION_STATUS_INACTIVE},
     * {@link #ENCRYPTION_STATUS_ACTIVATING}, or{@link #ENCRYPTION_STATUS_ACTIVE}.
     */
    public int getStorageEncryptionStatus() {
        if (mService != null) {
            try {
                return mService.getStorageEncryptionStatus();
            } catch (RemoteException e) {
                Log.w(TAG, "Failed talking with device policy service", e);
            }
        }
        return ENCRYPTION_STATUS_UNSUPPORTED;
    }

+2 −1
Original line number Diff line number Diff line
@@ -76,7 +76,8 @@ interface IDevicePolicyManager {
    ComponentName getGlobalProxyAdmin();

    int setStorageEncryption(in ComponentName who, boolean encrypt);
    int getStorageEncryption(in ComponentName who);
    boolean getStorageEncryption(in ComponentName who);
    int getStorageEncryptionStatus();

    void setActiveAdmin(in ComponentName policyReceiver, boolean refreshing);
    boolean isAdminActive(in ComponentName policyReceiver);
+89 −12
Original line number Diff line number Diff line
@@ -145,6 +145,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        int maximumFailedPasswordsForWipe = 0;
        long passwordExpirationTimeout = 0L;
        long passwordExpirationDate = 0L;
        boolean encryptionRequested = false;

        // TODO: review implementation decisions with frameworks team
        boolean specifiesGlobalProxy = false;
@@ -242,6 +243,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                out.attribute(null, "value", Long.toString(passwordExpirationDate));
                out.endTag(null, "password-expiration-date");
            }
            if (encryptionRequested) {
                out.startTag(null, "encryption-requested");
                out.attribute(null, "value", Boolean.toString(encryptionRequested));
                out.endTag(null, "encryption-requested");
            }
        }

        void readFromXml(XmlPullParser parser)
@@ -290,7 +296,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                    maximumFailedPasswordsForWipe = Integer.parseInt(
                            parser.getAttributeValue(null, "value"));
                } else if ("specifies-global-proxy".equals(tag)) {
                    specifiesGlobalProxy = Boolean.getBoolean(
                    specifiesGlobalProxy = Boolean.parseBoolean(
                            parser.getAttributeValue(null, "value"));
                } else if ("global-proxy-spec".equals(tag)) {
                    globalProxySpec =
@@ -304,6 +310,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                } else if ("password-expiration-date".equals(tag)) {
                    passwordExpirationDate = Long.parseLong(
                            parser.getAttributeValue(null, "value"));
                } else if ("encryption-requested".equals(tag)) {
                    encryptionRequested = Boolean.parseBoolean(
                            parser.getAttributeValue(null, "value"));
                } else {
                    Slog.w(TAG, "Unknown admin tag: " + tag);
                }
@@ -356,6 +365,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                pw.print(prefix); pw.print("globalProxyEclusionList=");
                        pw.println(globalProxyExclusionList);
            }
            pw.print(prefix); pw.print("encryptionRequested=");
                    pw.println(encryptionRequested);
        }
    }

@@ -1823,7 +1834,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    }

    /**
     * Set the storage encryption request.
     * Set the storage encryption request for a single admin.  Returns the new total request
     * status (for all admins).
     */
    public int setStorageEncryption(ComponentName who, boolean encrypt) {
        synchronized (this) {
@@ -1834,27 +1846,92 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
                    DeviceAdminInfo.USES_ENCRYPTED_STORAGE);

            // TODO: (1) Record the value for the admin so it's sticky
            // TODO: (2) Compute "max" for all admins (if any admin requests encryption, then
            //           we enable it.
            // TODO: (3) Work with filesystem / mount service to start/stop encryption
            // Quick exit:  If the filesystem does not support encryption, we can exit early.
            if (!isEncryptionSupported()) {
                return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
            }

            // (1) Record the value for the admin so it's sticky
            if (ap.encryptionRequested != encrypt) {
                ap.encryptionRequested = encrypt;
                saveSettingsLocked();
            }

            // (2) Compute "max" for all admins
            boolean newRequested = false;
            final int N = mAdminList.size();
            for (int i = 0; i < N; i++) {
                newRequested |= mAdminList.get(i).encryptionRequested;
            }

            // Notify OS of new request
            setEncryptionRequested(newRequested);

            // Return the new global request status
            return newRequested
                    ? DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE
                    : DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE;
        }
    }

    /**
     * Get the current storage encryption status for a given storage domain.
     * Get the current storage encryption request status for a given admin, or aggregate of all
     * active admins.
     */
    public int getStorageEncryption(ComponentName who) {
    public boolean getStorageEncryption(ComponentName who) {
        synchronized (this) {
            // Check for permissions if a particular caller is specified
            if (who != null) {
                getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_ENCRYPTED_STORAGE);
                // When checking for a single caller, status is based on caller's request
                ActiveAdmin ap = getActiveAdminForCallerLocked(who,
                        DeviceAdminInfo.USES_ENCRYPTED_STORAGE);
                return ap.encryptionRequested;
            }

            // If no particular caller is specified, return the aggregate set of requests.
            // This is short circuited by returning true on the first hit.
            final int N = mAdminList.size();
            for (int i = 0; i < N; i++) {
                if (mAdminList.get(i).encryptionRequested) {
                    return true;
                }
            }
            return false;
        }
    }

    /**
     * Get the current encryption status of the device.
     */
    public int getStorageEncryptionStatus() {
        return getEncryptionStatus();
    }

            // TODO: Work with filesystem / mount service to query encryption status
    /**
     * Hook to low-levels:  This should report if the filesystem supports encrypted storage.
     */
    private boolean isEncryptionSupported() {
        // Note, this can be implemented as
        //   return getEncryptionStatus() != DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
        // But is provided as a separate internal method if there's a faster way to do a
        // simple check for supported-or-not.
        return getEncryptionStatus() != DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
    }

    /**
     * Hook to low-levels:  Reporting the current status of encryption.
     * @return A value such as {@link DevicePolicyManager#ENCRYPTION_STATUS_UNSUPPORTED} or
     * {@link DevicePolicyManager#ENCRYPTION_STATUS_INACTIVE} or
     * {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE}.
     */
    private int getEncryptionStatus() {
        return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
    }

    /**
     * Hook to low-levels:  If needed, record the new admin setting for encryption.
     */
    private void setEncryptionRequested(boolean encrypt) {
    }

    @Override