Add device policy API to toggle Common Criteria mode

Common Criteria mode puts device into a state where certain
funtionalities are tuned or turned on to meet the higher security
requirement from Common Criteria certification. Device Owner
can use the new device policy API to toggle Common Criteria mode.

Bug: 137937540
Test: atest FrameworksServicesTests:DevicePolicyManagerTest
Test: atest SettingsProviderTest
Test: atest com.android.cts.devicepolicy.MixedDeviceOwnerTest#testCommonCriteriaMode
Test: atest com.android.cts.devicepolicy.OrgOwnedProfileOwnerTest#testCommonCriteriaMode
Change-Id: If07c053437e980ed3317d3838cc74e5bfd44efce
diff --git a/api/current.txt b/api/current.txt
index d9c305a..92a89e6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6831,6 +6831,7 @@
     method public boolean isApplicationHidden(@NonNull android.content.ComponentName, String);
     method public boolean isBackupServiceEnabled(@NonNull android.content.ComponentName);
     method @Deprecated public boolean isCallerApplicationRestrictionsManagingPackage();
+    method public boolean isCommonCriteriaModeEnabled(@NonNull android.content.ComponentName);
     method public boolean isDeviceIdAttestationSupported();
     method public boolean isDeviceOwnerApp(String);
     method public boolean isEphemeralUser(@NonNull android.content.ComponentName);
@@ -6879,6 +6880,7 @@
     method public void setBluetoothContactSharingDisabled(@NonNull android.content.ComponentName, boolean);
     method public void setCameraDisabled(@NonNull android.content.ComponentName, boolean);
     method @Deprecated public void setCertInstallerPackage(@NonNull android.content.ComponentName, @Nullable String) throws java.lang.SecurityException;
+    method public void setCommonCriteriaModeEnabled(@NonNull android.content.ComponentName, boolean);
     method public void setCrossProfileCalendarPackages(@NonNull android.content.ComponentName, @Nullable java.util.Set<java.lang.String>);
     method public void setCrossProfileCallerIdDisabled(@NonNull android.content.ComponentName, boolean);
     method public void setCrossProfileContactsSearchDisabled(@NonNull android.content.ComponentName, boolean);
diff --git a/api/module-app-current.txt b/api/module-app-current.txt
index 4307e67..db774ef 100644
--- a/api/module-app-current.txt
+++ b/api/module-app-current.txt
@@ -7,3 +7,11 @@
 
 }
 
+package android.provider {
+
+  public static final class Settings.Global extends android.provider.Settings.NameValueTable {
+    field public static final String COMMON_CRITERIA_MODE = "common_criteria_mode";
+  }
+
+}
+
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index be8e1d6..54a64ef 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -11493,4 +11493,48 @@
         }
         return Collections.emptyList();
     }
+
+    /**
+     * Called by device owner or profile owner of an organization-owned managed profile to toggle
+     * Common Criteria mode for the device. When the device is in Common Criteria mode,
+     * certain device functionalities are tuned to meet the higher
+     * security level required by Common Criteria certification. For example:
+     * <ul>
+     * <li> Bluetooth long term key material is additionally integrity-protected with AES-GCM. </li>
+     * <li> WiFi configuration store is additionally integrity-protected with AES-GCM. </li>
+     * </ul>
+     * Common Criteria mode is disabled by default.
+     *
+     * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+     * @param enabled whether Common Criteria mode should be enabled or not.
+     */
+    public void setCommonCriteriaModeEnabled(@NonNull ComponentName admin, boolean enabled) {
+        throwIfParentInstance("setCommonCriteriaModeEnabled");
+        if (mService != null) {
+            try {
+                mService.setCommonCriteriaModeEnabled(admin, enabled);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Called by device owner or profile owner of an organization-owned managed profile to return
+     * whether Common Criteria mode is currently enabled for the device.
+     *
+     * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+     * @return {@code true} if Common Criteria mode is enabled, {@code false} otherwise.
+     */
+    public boolean isCommonCriteriaModeEnabled(@NonNull ComponentName admin) {
+        throwIfParentInstance("isCommonCriteriaModeEnabled");
+        if (mService != null) {
+            try {
+                return mService.isCommonCriteriaModeEnabled(admin);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return false;
+    }
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 21c9eb5..f649286 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -461,4 +461,7 @@
     void setProtectedPackages(in ComponentName admin, in List<String> packages);
 
     List<String> getProtectedPackages(in ComponentName admin);
+
+    void setCommonCriteriaModeEnabled(in ComponentName admin, boolean enabled);
+    boolean isCommonCriteriaModeEnabled(in ComponentName admin);
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1d759af..0e3dd3a 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -13929,6 +13929,19 @@
          */
         public static final String POWER_BUTTON_SUPPRESSION_DELAY_AFTER_GESTURE_WAKE =
                 "power_button_suppression_delay_after_gesture_wake";
+
+        /**
+         * An integer indicating whether the device is in Common Criteria mode. When enabled,
+         * certain device functionalities are tuned to meet the higher security level required
+         * by Common Criteria certification. Examples include:
+         *   Bluetooth long term key material is additionally integrity-protected with AES-GCM.
+         *   WiFi configuration store is additionally integrity-protected with AES-GCM.
+         * A value of 0 means Common Criteria mode is not enabled (default), a value of non-zero
+         * means Common Criteria mode is enabled.
+         * @hide
+         */
+        @SystemApi(client = SystemApi.Client.MODULE_APPS)
+        public static final String COMMON_CRITERIA_MODE = "common_criteria_mode";
     }
 
     /**
diff --git a/core/proto/android/stats/devicepolicy/device_policy_enums.proto b/core/proto/android/stats/devicepolicy/device_policy_enums.proto
index 0fca1d1..0ae11a1 100644
--- a/core/proto/android/stats/devicepolicy/device_policy_enums.proto
+++ b/core/proto/android/stats/devicepolicy/device_policy_enums.proto
@@ -155,4 +155,5 @@
   SET_AUTO_TIME_ZONE = 128;
   SET_PACKAGES_PROTECTED = 129;
   SET_FACTORY_RESET_PROTECTION = 130;
+  SET_COMMON_CRITERIA_MODE = 131;
 }
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 6ea2c74..a337570 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -195,6 +195,7 @@
                     Settings.Global.CERT_PIN_UPDATE_CONTENT_URL,
                     Settings.Global.CERT_PIN_UPDATE_METADATA_URL,
                     Settings.Global.COMPATIBILITY_MODE,
+                    Settings.Global.COMMON_CRITERIA_MODE,
                     Settings.Global.CONNECTIVITY_CHANGE_DELAY,
                     Settings.Global.CONNECTIVITY_METRICS_BUFFER_SIZE,
                     Settings.Global.CONNECTIVITY_SAMPLING_INTERVAL_IN_SECONDS,
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b8b0dbf..fc3c927 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -15051,4 +15051,29 @@
             Slog.d(LOG_TAG, message);
         }
     }
+
+    @Override
+    public void setCommonCriteriaModeEnabled(ComponentName admin, boolean enabled) {
+        synchronized (getLockObject()) {
+            getActiveAdminForCallerLocked(admin,
+                    DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER);
+        }
+        mInjector.binderWithCleanCallingIdentity(
+                () -> mInjector.settingsGlobalPutInt(Settings.Global.COMMON_CRITERIA_MODE,
+                        enabled ? 1 : 0));
+        DevicePolicyEventLogger
+                .createEvent(DevicePolicyEnums.SET_COMMON_CRITERIA_MODE)
+                .setAdmin(admin)
+                .setBoolean(enabled)
+                .write();
+    }
+
+    @Override
+    public boolean isCommonCriteriaModeEnabled(ComponentName admin) {
+        synchronized (getLockObject()) {
+            getActiveAdminForCallerLocked(admin,
+                    DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER);
+        }
+        return mInjector.settingsGlobalGetInt(Settings.Global.COMMON_CRITERIA_MODE, 0) != 0;
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index bfadeea..632a2c1 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -5721,6 +5721,31 @@
                 dpm.getAllCrossProfilePackages());
     }
 
+    public void testSetCommonCriteriaMode_asDeviceOwner() throws Exception {
+        setDeviceOwner();
+
+        dpm.setCommonCriteriaModeEnabled(admin1, true);
+        verify(getServices().settings).settingsGlobalPutInt(
+                Settings.Global.COMMON_CRITERIA_MODE, 1);
+
+        when(getServices().settings.settingsGlobalGetInt(Settings.Global.COMMON_CRITERIA_MODE, 0))
+                .thenReturn(1);
+        assertTrue(dpm.isCommonCriteriaModeEnabled(admin1));
+    }
+
+    public void testSetCommonCriteriaMode_asPoOfOrgOwnedDevice() throws Exception {
+        setupProfileOwner();
+        configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE);
+
+        dpm.setCommonCriteriaModeEnabled(admin1, true);
+        verify(getServices().settings).settingsGlobalPutInt(
+                Settings.Global.COMMON_CRITERIA_MODE, 1);
+
+        when(getServices().settings.settingsGlobalGetInt(Settings.Global.COMMON_CRITERIA_MODE, 0))
+                .thenReturn(1);
+        assertTrue(dpm.isCommonCriteriaModeEnabled(admin1));
+    }
+
     private void setCrossProfileAppsList(String... packages) {
         when(mContext.getResources()
                 .getStringArray(eq(R.array.cross_profile_apps)))