summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Grace Cheng <graciecheng@google.com> 2024-11-14 15:48:59 +0000
committer Grace Cheng <graciecheng@google.com> 2024-11-18 05:13:33 +0000
commit43300b49dce6cb286ce5535b59b116d2033affec (patch)
tree06ea35e541a06f5ef5930b72059a65fe479f264a
parent0e92f9364ff9eaf79d31f934029ca06ebdee9eaa (diff)
Define Secure Lock Device API surface
Secure Lock is a new feature that enables users to remotely lock down their mobile device via authorized clients into an enhanced security state, which restricts access to sensitive data (app notifications, widgets, quick settings, assistant, etc) and requires both credential and biometric authentication for device entry. This change introduces a new AuthenticationPolicyManager, which external clients will use to call into SecureLockDeviceService via AuthenticationPolicyService. SecureLockDeviceService implements the new enableSecureLockDevice and disableSecureLockDevice API methods, which currently have a placeholder no-op implementation that will be filled out at a later time. Bug: 373422357 API-Coverage-Bug: 376456619 Flag: android.security.secure_lockdown Test: atest AuthenticationPolicyServiceTest Ignore-AOSP-First: adding flag to security package Change-Id: I7d2c97a8f51cb8a4475761a6c04ce9f32b38fd19
-rw-r--r--core/api/system-current.txt31
-rw-r--r--core/java/android/app/SystemServiceRegistry.java21
-rw-r--r--core/java/android/content/Context.java22
-rw-r--r--core/java/android/security/authenticationpolicy/AuthenticationPolicyManager.java237
-rw-r--r--core/java/android/security/authenticationpolicy/DisableSecureLockDeviceParams.aidl21
-rw-r--r--core/java/android/security/authenticationpolicy/DisableSecureLockDeviceParams.java82
-rw-r--r--core/java/android/security/authenticationpolicy/EnableSecureLockDeviceParams.aidl21
-rw-r--r--core/java/android/security/authenticationpolicy/EnableSecureLockDeviceParams.java82
-rw-r--r--core/java/android/security/authenticationpolicy/IAuthenticationPolicyService.aidl32
-rw-r--r--core/java/android/security/authenticationpolicy/OWNERS1
-rw-r--r--services/core/java/com/android/server/security/authenticationpolicy/AuthenticationPolicyService.java49
-rw-r--r--services/core/java/com/android/server/security/authenticationpolicy/SecureLockDeviceService.java120
-rw-r--r--services/core/java/com/android/server/security/authenticationpolicy/SecureLockDeviceServiceInternal.java55
-rw-r--r--services/java/com/android/server/SystemServer.java7
-rw-r--r--services/tests/servicestests/src/com/android/server/security/authenticationpolicy/AuthenticationPolicyServiceTest.java18
15 files changed, 797 insertions, 2 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 9456f9f5eaea..433d80a22a6e 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -3870,6 +3870,7 @@ package android.content {
field public static final String APP_INTEGRITY_SERVICE = "app_integrity";
field public static final String APP_PREDICTION_SERVICE = "app_prediction";
field public static final String AUDIO_DEVICE_VOLUME_SERVICE = "audio_device_volume";
+ field @FlaggedApi("android.security.secure_lockdown") public static final String AUTHENTICATION_POLICY_SERVICE = "authentication_policy";
field public static final String BACKUP_SERVICE = "backup";
field public static final String BATTERY_STATS_SERVICE = "batterystats";
field public static final int BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS = 1048576; // 0x100000
@@ -12859,6 +12860,36 @@ package android.security.advancedprotection {
}
+package android.security.authenticationpolicy {
+
+ @FlaggedApi("android.security.secure_lockdown") public final class AuthenticationPolicyManager {
+ method @FlaggedApi("android.security.secure_lockdown") @RequiresPermission(android.Manifest.permission.MANAGE_SECURE_LOCK_DEVICE) public int disableSecureLockDevice(@NonNull android.security.authenticationpolicy.DisableSecureLockDeviceParams);
+ method @FlaggedApi("android.security.secure_lockdown") @RequiresPermission(android.Manifest.permission.MANAGE_SECURE_LOCK_DEVICE) public int enableSecureLockDevice(@NonNull android.security.authenticationpolicy.EnableSecureLockDeviceParams);
+ field @FlaggedApi("android.security.secure_lockdown") public static final int ERROR_ALREADY_ENABLED = 6; // 0x6
+ field @FlaggedApi("android.security.secure_lockdown") public static final int ERROR_INSUFFICIENT_BIOMETRICS = 5; // 0x5
+ field @FlaggedApi("android.security.secure_lockdown") public static final int ERROR_INVALID_PARAMS = 3; // 0x3
+ field @FlaggedApi("android.security.secure_lockdown") public static final int ERROR_NO_BIOMETRICS_ENROLLED = 4; // 0x4
+ field @FlaggedApi("android.security.secure_lockdown") public static final int ERROR_UNKNOWN = 0; // 0x0
+ field @FlaggedApi("android.security.secure_lockdown") public static final int ERROR_UNSUPPORTED = 2; // 0x2
+ field @FlaggedApi("android.security.secure_lockdown") public static final int SUCCESS = 1; // 0x1
+ }
+
+ @FlaggedApi("android.security.secure_lockdown") public final class DisableSecureLockDeviceParams implements android.os.Parcelable {
+ ctor public DisableSecureLockDeviceParams(@NonNull String);
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.security.authenticationpolicy.DisableSecureLockDeviceParams> CREATOR;
+ }
+
+ @FlaggedApi("android.security.secure_lockdown") public final class EnableSecureLockDeviceParams implements android.os.Parcelable {
+ ctor public EnableSecureLockDeviceParams(@NonNull String);
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.security.authenticationpolicy.EnableSecureLockDeviceParams> CREATOR;
+ }
+
+}
+
package android.security.forensic {
@FlaggedApi("android.security.afl_api") public class ForensicManager {
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 53a7dad76788..6a23349bf8aa 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -241,6 +241,8 @@ import android.security.advancedprotection.AdvancedProtectionManager;
import android.security.advancedprotection.IAdvancedProtectionService;
import android.security.attestationverification.AttestationVerificationManager;
import android.security.attestationverification.IAttestationVerificationManagerService;
+import android.security.authenticationpolicy.AuthenticationPolicyManager;
+import android.security.authenticationpolicy.IAuthenticationPolicyService;
import android.security.forensic.ForensicManager;
import android.security.forensic.IForensicService;
import android.security.keystore.KeyStoreManager;
@@ -1025,6 +1027,25 @@ public final class SystemServiceRegistry {
}
});
+ registerService(Context.AUTHENTICATION_POLICY_SERVICE,
+ AuthenticationPolicyManager.class,
+ new CachedServiceFetcher<AuthenticationPolicyManager>() {
+ @Override
+ public AuthenticationPolicyManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ if (!android.security.Flags.secureLockdown()) {
+ throw new ServiceNotFoundException(
+ Context.AUTHENTICATION_POLICY_SERVICE);
+ }
+
+ final IBinder binder = ServiceManager.getServiceOrThrow(
+ Context.AUTHENTICATION_POLICY_SERVICE);
+ final IAuthenticationPolicyService service =
+ IAuthenticationPolicyService.Stub.asInterface(binder);
+ return new AuthenticationPolicyManager(ctx.getOuterContext(), service);
+ }
+ });
+
registerService(Context.TV_INTERACTIVE_APP_SERVICE, TvInteractiveAppManager.class,
new CachedServiceFetcher<TvInteractiveAppManager>() {
@Override
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 6086f2455a31..5754e7e30c34 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -18,6 +18,7 @@ package android.content;
import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER;
import static android.content.flags.Flags.FLAG_ENABLE_BIND_PACKAGE_ISOLATED_PROCESS;
+import static android.security.Flags.FLAG_SECURE_LOCKDOWN;
import android.annotation.AttrRes;
import android.annotation.CallbackExecutor;
@@ -4256,6 +4257,7 @@ public abstract class Context {
FINGERPRINT_SERVICE,
//@hide: FACE_SERVICE,
BIOMETRIC_SERVICE,
+ AUTHENTICATION_POLICY_SERVICE,
MEDIA_ROUTER_SERVICE,
TELEPHONY_SERVICE,
TELEPHONY_SUBSCRIPTION_SERVICE,
@@ -4437,6 +4439,9 @@ public abstract class Context {
* web domain approval state.
* <dt> {@link #DISPLAY_HASH_SERVICE} ("display_hash")
* <dd> A {@link android.view.displayhash.DisplayHashManager} for management of display hashes.
+ * <dt> {@link #AUTHENTICATION_POLICY_SERVICE} ("authentication_policy")
+ * <dd> A {@link android.security.authenticationpolicy.AuthenticationPolicyManager}
+ * for managing authentication related policies on the device.
* </dl>
*
* <p>Note: System services obtained via this API may be closely associated with
@@ -4521,6 +4526,8 @@ public abstract class Context {
* @see android.content.pm.verify.domain.DomainVerificationManager
* @see #DISPLAY_HASH_SERVICE
* @see android.view.displayhash.DisplayHashManager
+ * @see #AUTHENTICATION_POLICY_SERVICE
+ * @see android.security.authenticationpolicy.AuthenticationPolicyManager
*/
// TODO(b/347269120): Re-add @Nullable
public abstract Object getSystemService(@ServiceName @NonNull String name);
@@ -4543,7 +4550,8 @@ public abstract class Context {
* {@link android.os.BatteryManager}, {@link android.app.job.JobScheduler},
* {@link android.app.usage.NetworkStatsManager},
* {@link android.content.pm.verify.domain.DomainVerificationManager},
- * {@link android.view.displayhash.DisplayHashManager}.
+ * {@link android.view.displayhash.DisplayHashManager}
+ * {@link android.security.authenticationpolicy.AuthenticationPolicyManager}.
* </p>
*
* <p>
@@ -5183,6 +5191,18 @@ public abstract class Context {
public static final String AUTH_SERVICE = "auth";
/**
+ * Use with {@link #getSystemService(String)} to retrieve an {@link
+ * android.security.authenticationpolicy.AuthenticationPolicyManager}.
+ * @see #getSystemService
+ * @see android.security.authenticationpolicy.AuthenticationPolicyManager
+ *
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(FLAG_SECURE_LOCKDOWN)
+ public static final String AUTHENTICATION_POLICY_SERVICE = "authentication_policy";
+
+ /**
* Use with {@link #getSystemService(String)} to retrieve a
* {@link android.hardware.fingerprint.FingerprintManager} for handling management
* of fingerprints.
diff --git a/core/java/android/security/authenticationpolicy/AuthenticationPolicyManager.java b/core/java/android/security/authenticationpolicy/AuthenticationPolicyManager.java
new file mode 100644
index 000000000000..75abd5fa4bb0
--- /dev/null
+++ b/core/java/android/security/authenticationpolicy/AuthenticationPolicyManager.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.security.authenticationpolicy;
+
+import static android.Manifest.permission.MANAGE_SECURE_LOCK_DEVICE;
+import static android.security.Flags.FLAG_SECURE_LOCKDOWN;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
+import android.os.RemoteException;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * AuthenticationPolicyManager is a centralized interface for managing authentication related
+ * policies on the device. This includes device locking capabilities to protect users in "at risk"
+ * environments.
+ *
+ * AuthenticationPolicyManager is designed to protect Android users by integrating with apps and
+ * key system components, such as the lock screen. It is not related to enterprise control surfaces
+ * and does not offer additional administrative controls.
+ *
+ * <p>
+ * To use this class, call {@link #enableSecureLockDevice} to enable secure lock on the device.
+ * This will require the caller to have the
+ * {@link android.Manifest.permission#MANAGE_SECURE_LOCK_DEVICE} permission.
+ *
+ * <p>
+ * To disable secure lock on the device, call {@link #disableSecureLockDevice}. This will require
+ * the caller to have the {@link android.Manifest.permission#MANAGE_SECURE_LOCK_DEVICE} permission.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(FLAG_SECURE_LOCKDOWN)
+@SystemService(Context.AUTHENTICATION_POLICY_SERVICE)
+public final class AuthenticationPolicyManager {
+ private static final String TAG = "AuthenticationPolicyManager";
+
+ @NonNull private final IAuthenticationPolicyService mAuthenticationPolicyService;
+ @NonNull private final Context mContext;
+
+ /**
+ * Error result code for {@link #enableSecureLockDevice} and {@link
+ * #disableSecureLockDevice}.
+ *
+ * Secure lock device request status unknown.
+ *
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(FLAG_SECURE_LOCKDOWN)
+ public static final int ERROR_UNKNOWN = 0;
+
+ /**
+ * Success result code for {@link #enableSecureLockDevice} and {@link #disableSecureLockDevice}.
+ *
+ * Secure lock device request successful.
+ *
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(FLAG_SECURE_LOCKDOWN)
+ public static final int SUCCESS = 1;
+
+ /**
+ * Error result code for {@link #enableSecureLockDevice} and {@link #disableSecureLockDevice}.
+ *
+ * Secure lock device is unsupported.
+ *
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(FLAG_SECURE_LOCKDOWN)
+ public static final int ERROR_UNSUPPORTED = 2;
+
+
+ /**
+ * Error result code for {@link #enableSecureLockDevice} and {@link #disableSecureLockDevice}.
+ *
+ * Invalid secure lock device request params provided.
+ *
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(FLAG_SECURE_LOCKDOWN)
+ public static final int ERROR_INVALID_PARAMS = 3;
+
+
+ /**
+ * Error result code for {@link #enableSecureLockDevice} and {@link #disableSecureLockDevice}.
+ *
+ * Secure lock device is unavailable because there are no biometrics enrolled on the device.
+ *
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(FLAG_SECURE_LOCKDOWN)
+ public static final int ERROR_NO_BIOMETRICS_ENROLLED = 4;
+
+ /**
+ * Error result code for {@link #enableSecureLockDevice} and {@link #disableSecureLockDevice}.
+ *
+ * Secure lock device is unavailable because the device has no biometric hardware or the
+ * biometric sensors do not meet
+ * {@link android.hardware.biometrics.BiometricManager.Authenticators#BIOMETRIC_STRONG}
+ *
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(FLAG_SECURE_LOCKDOWN)
+ public static final int ERROR_INSUFFICIENT_BIOMETRICS = 5;
+
+ /**
+ * Error result code for {@link #enableSecureLockDevice}.
+ *
+ * Secure lock is already enabled.
+ *
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(FLAG_SECURE_LOCKDOWN)
+ public static final int ERROR_ALREADY_ENABLED = 6;
+
+ /**
+ * Communicates the current status of a request to enable secure lock on the device.
+ *
+ * @hide
+ */
+ @IntDef(prefix = {"ENABLE_SECURE_LOCK_DEVICE_STATUS_"}, value = {
+ ERROR_UNKNOWN,
+ SUCCESS,
+ ERROR_UNSUPPORTED,
+ ERROR_INVALID_PARAMS,
+ ERROR_NO_BIOMETRICS_ENROLLED,
+ ERROR_INSUFFICIENT_BIOMETRICS,
+ ERROR_ALREADY_ENABLED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface EnableSecureLockDeviceRequestStatus {}
+
+ /**
+ * Communicates the current status of a request to disable secure lock on the device.
+ *
+ * @hide
+ */
+ @IntDef(prefix = {"DISABLE_SECURE_LOCK_DEVICE_STATUS_"}, value = {
+ ERROR_UNKNOWN,
+ SUCCESS,
+ ERROR_UNSUPPORTED,
+ ERROR_INVALID_PARAMS,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DisableSecureLockDeviceRequestStatus {}
+
+ /** @hide */
+ public AuthenticationPolicyManager(@NonNull Context context,
+ @NonNull IAuthenticationPolicyService authenticationPolicyService) {
+ mContext = context;
+ mAuthenticationPolicyService = authenticationPolicyService;
+ }
+
+ /**
+ * Called by a privileged component to remotely enable secure lock on the device.
+ *
+ * Secure lock is an enhanced security state that restricts access to sensitive data (app
+ * notifications, widgets, quick settings, assistant, etc) and requires multi-factor
+ * authentication for device entry, such as
+ * {@link android.hardware.biometrics.BiometricManager.Authenticators#DEVICE_CREDENTIAL} and
+ * {@link android.hardware.biometrics.BiometricManager.Authenticators#BIOMETRIC_STRONG}.
+ *
+ * If secure lock is already enabled when this method is called, it will return
+ * {@link ERROR_ALREADY_ENABLED}.
+ *
+ * @param params EnableSecureLockDeviceParams for caller to supply params related to the secure
+ * lock device request
+ * @return @EnableSecureLockDeviceRequestStatus int indicating the result of the secure lock
+ * device request
+ *
+ * @hide
+ */
+ @EnableSecureLockDeviceRequestStatus
+ @RequiresPermission(MANAGE_SECURE_LOCK_DEVICE)
+ @SystemApi
+ @FlaggedApi(FLAG_SECURE_LOCKDOWN)
+ public int enableSecureLockDevice(@NonNull EnableSecureLockDeviceParams params) {
+ try {
+ return mAuthenticationPolicyService.enableSecureLockDevice(params);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Called by a privileged component to disable secure lock on the device.
+ *
+ * If secure lock is already disabled when this method is called, it will return
+ * {@link SUCCESS}.
+ *
+ * @param params @DisableSecureLockDeviceParams for caller to supply params related to the
+ * secure lock device request
+ * @return @DisableSecureLockDeviceRequestStatus int indicating the result of the secure lock
+ * device request
+ *
+ * @hide
+ */
+ @DisableSecureLockDeviceRequestStatus
+ @RequiresPermission(MANAGE_SECURE_LOCK_DEVICE)
+ @SystemApi
+ @FlaggedApi(FLAG_SECURE_LOCKDOWN)
+ public int disableSecureLockDevice(@NonNull DisableSecureLockDeviceParams params) {
+ try {
+ return mAuthenticationPolicyService.disableSecureLockDevice(params);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+}
diff --git a/core/java/android/security/authenticationpolicy/DisableSecureLockDeviceParams.aidl b/core/java/android/security/authenticationpolicy/DisableSecureLockDeviceParams.aidl
new file mode 100644
index 000000000000..81f7726a500c
--- /dev/null
+++ b/core/java/android/security/authenticationpolicy/DisableSecureLockDeviceParams.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.security.authenticationpolicy;
+
+/**
+ * @hide
+ */
+parcelable DisableSecureLockDeviceParams; \ No newline at end of file
diff --git a/core/java/android/security/authenticationpolicy/DisableSecureLockDeviceParams.java b/core/java/android/security/authenticationpolicy/DisableSecureLockDeviceParams.java
new file mode 100644
index 000000000000..64a3f0f60f96
--- /dev/null
+++ b/core/java/android/security/authenticationpolicy/DisableSecureLockDeviceParams.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.authenticationpolicy;
+
+import static android.security.Flags.FLAG_SECURE_LOCKDOWN;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Parameters related to a request to disable secure lock on the device.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(FLAG_SECURE_LOCKDOWN)
+public final class DisableSecureLockDeviceParams implements Parcelable {
+
+ /**
+ * Client message associated with the request to disable secure lock on the device. This message
+ * will be shown on the device when secure lock mode is disabled.
+ */
+ private final @NonNull String mMessage;
+
+ /**
+ * Creates DisableSecureLockDeviceParams with the given params.
+ *
+ * @param message Allows clients to pass in a message with information about the request to
+ * disable secure lock on the device. This message will be shown to the user when
+ * secure lock mode is disabled. If an empty string is provided, it will default
+ * to a system-defined string (e.g. "Secure lock mode has been disabled.")
+ */
+ public DisableSecureLockDeviceParams(@NonNull String message) {
+ mMessage = message;
+ }
+
+ private DisableSecureLockDeviceParams(@NonNull Parcel in) {
+ mMessage = Objects.requireNonNull(in.readString8());
+ }
+
+ public static final @NonNull Creator<DisableSecureLockDeviceParams> CREATOR =
+ new Creator<DisableSecureLockDeviceParams>() {
+ @Override
+ public DisableSecureLockDeviceParams createFromParcel(Parcel in) {
+ return new DisableSecureLockDeviceParams(in);
+ }
+
+ @Override
+ public DisableSecureLockDeviceParams[] newArray(int size) {
+ return new DisableSecureLockDeviceParams[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString8(mMessage);
+ }
+}
diff --git a/core/java/android/security/authenticationpolicy/EnableSecureLockDeviceParams.aidl b/core/java/android/security/authenticationpolicy/EnableSecureLockDeviceParams.aidl
new file mode 100644
index 000000000000..9e496f82ec69
--- /dev/null
+++ b/core/java/android/security/authenticationpolicy/EnableSecureLockDeviceParams.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.security.authenticationpolicy;
+
+/**
+ * @hide
+ */
+parcelable EnableSecureLockDeviceParams; \ No newline at end of file
diff --git a/core/java/android/security/authenticationpolicy/EnableSecureLockDeviceParams.java b/core/java/android/security/authenticationpolicy/EnableSecureLockDeviceParams.java
new file mode 100644
index 000000000000..1d727727ce37
--- /dev/null
+++ b/core/java/android/security/authenticationpolicy/EnableSecureLockDeviceParams.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.security.authenticationpolicy;
+
+import static android.security.Flags.FLAG_SECURE_LOCKDOWN;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+
+/**
+ * Parameters related to a request to enable secure lock on the device.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(FLAG_SECURE_LOCKDOWN)
+public final class EnableSecureLockDeviceParams implements Parcelable {
+
+ /**
+ * Client message associated with the request to enable secure lock on the device. This message
+ * will be shown on the device when secure lock mode is enabled.
+ */
+ private final @NonNull String mMessage;
+
+ /**
+ * Creates EnableSecureLockDeviceParams with the given params.
+ *
+ * @param message Allows clients to pass in a message with information about the request to
+ * enable secure lock on the device. This message will be shown to the user when
+ * secure lock mode is enabled. If an empty string is provided, it will default
+ * to a system-defined string (e.g. "Device is securely locked remotely.")
+ */
+ public EnableSecureLockDeviceParams(@NonNull String message) {
+ mMessage = message;
+ }
+
+ private EnableSecureLockDeviceParams(@NonNull Parcel in) {
+ mMessage = Objects.requireNonNull(in.readString8());
+ }
+
+ public static final @NonNull Creator<EnableSecureLockDeviceParams> CREATOR =
+ new Creator<EnableSecureLockDeviceParams>() {
+ @Override
+ public EnableSecureLockDeviceParams createFromParcel(Parcel in) {
+ return new EnableSecureLockDeviceParams(in);
+ }
+
+ @Override
+ public EnableSecureLockDeviceParams[] newArray(int size) {
+ return new EnableSecureLockDeviceParams[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString8(mMessage);
+ }
+}
diff --git a/core/java/android/security/authenticationpolicy/IAuthenticationPolicyService.aidl b/core/java/android/security/authenticationpolicy/IAuthenticationPolicyService.aidl
new file mode 100644
index 000000000000..5ad4534c257a
--- /dev/null
+++ b/core/java/android/security/authenticationpolicy/IAuthenticationPolicyService.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.authenticationpolicy;
+
+import android.security.authenticationpolicy.EnableSecureLockDeviceParams;
+import android.security.authenticationpolicy.DisableSecureLockDeviceParams;
+
+/**
+ * Communication channel from AuthenticationPolicyManager to AuthenticationPolicyService.
+ * @hide
+ */
+interface IAuthenticationPolicyService {
+ @EnforcePermission("MANAGE_SECURE_LOCK_DEVICE")
+ int enableSecureLockDevice(in EnableSecureLockDeviceParams params);
+
+ @EnforcePermission("MANAGE_SECURE_LOCK_DEVICE")
+ int disableSecureLockDevice(in DisableSecureLockDeviceParams params);
+} \ No newline at end of file
diff --git a/core/java/android/security/authenticationpolicy/OWNERS b/core/java/android/security/authenticationpolicy/OWNERS
new file mode 100644
index 000000000000..4310d1a3a9db
--- /dev/null
+++ b/core/java/android/security/authenticationpolicy/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/security/authenticationpolicy/OWNERS \ No newline at end of file
diff --git a/services/core/java/com/android/server/security/authenticationpolicy/AuthenticationPolicyService.java b/services/core/java/com/android/server/security/authenticationpolicy/AuthenticationPolicyService.java
index b8a4a9c26feb..6798a6146ae0 100644
--- a/services/core/java/com/android/server/security/authenticationpolicy/AuthenticationPolicyService.java
+++ b/services/core/java/com/android/server/security/authenticationpolicy/AuthenticationPolicyService.java
@@ -16,8 +16,11 @@
package com.android.server.security.authenticationpolicy;
+import static android.Manifest.permission.MANAGE_SECURE_LOCK_DEVICE;
+
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST;
+import android.annotation.EnforcePermission;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -32,9 +35,14 @@ import android.hardware.biometrics.events.AuthenticationStoppedInfo;
import android.hardware.biometrics.events.AuthenticationSucceededInfo;
import android.os.Build;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
+import android.security.authenticationpolicy.AuthenticationPolicyManager;
+import android.security.authenticationpolicy.DisableSecureLockDeviceParams;
+import android.security.authenticationpolicy.EnableSecureLockDeviceParams;
+import android.security.authenticationpolicy.IAuthenticationPolicyService;
import android.util.Log;
import android.util.Slog;
import android.util.SparseIntArray;
@@ -74,6 +82,7 @@ public class AuthenticationPolicyService extends SystemService {
private final KeyguardManager mKeyguardManager;
private final WindowManagerInternal mWindowManager;
private final UserManagerInternal mUserManager;
+ private SecureLockDeviceServiceInternal mSecureLockDeviceService;
@VisibleForTesting
final SparseIntArray mFailedAttemptsForUser = new SparseIntArray();
private final SparseLongArray mLastLockedTimestamp = new SparseLongArray();
@@ -94,10 +103,16 @@ public class AuthenticationPolicyService extends SystemService {
mWindowManager = Objects.requireNonNull(
LocalServices.getService(WindowManagerInternal.class));
mUserManager = Objects.requireNonNull(LocalServices.getService(UserManagerInternal.class));
+ if (android.security.Flags.secureLockdown()) {
+ mSecureLockDeviceService = Objects.requireNonNull(
+ LocalServices.getService(SecureLockDeviceServiceInternal.class));
+ }
}
@Override
- public void onStart() {}
+ public void onStart() {
+ publishBinderService(Context.AUTHENTICATION_POLICY_SERVICE, mService);
+ }
@Override
public void onBootPhase(int phase) {
@@ -294,4 +309,36 @@ public class AuthenticationPolicyService extends SystemService {
// next successful primary or biometric auth happens
mLastLockedTimestamp.put(userId, SystemClock.elapsedRealtime());
}
+
+ private final IBinder mService = new IAuthenticationPolicyService.Stub() {
+ /**
+ * @see AuthenticationPolicyManager#enableSecureLockDevice(EnableSecureLockDeviceParams)
+ * @param params EnableSecureLockDeviceParams for caller to supply params related
+ * to the secure lock device request
+ * @return @EnableSecureLockDeviceRequestStatus int indicating the result of the Secure
+ * Lock Device request
+ */
+ @Override
+ @EnforcePermission(MANAGE_SECURE_LOCK_DEVICE)
+ @AuthenticationPolicyManager.EnableSecureLockDeviceRequestStatus
+ public int enableSecureLockDevice(EnableSecureLockDeviceParams params) {
+ enableSecureLockDevice_enforcePermission();
+ return mSecureLockDeviceService.enableSecureLockDevice(params);
+ }
+
+ /**
+ * @see AuthenticationPolicyManager#disableSecureLockDevice(DisableSecureLockDeviceParams)
+ * @param params @DisableSecureLockDeviceParams for caller to supply params related
+ * to the secure lock device request
+ * @return @DisableSecureLockDeviceRequestStatus int indicating the result of the Secure
+ * Lock Device request
+ */
+ @Override
+ @EnforcePermission(MANAGE_SECURE_LOCK_DEVICE)
+ @AuthenticationPolicyManager.DisableSecureLockDeviceRequestStatus
+ public int disableSecureLockDevice(DisableSecureLockDeviceParams params) {
+ disableSecureLockDevice_enforcePermission();
+ return mSecureLockDeviceService.disableSecureLockDevice(params);
+ }
+ };
}
diff --git a/services/core/java/com/android/server/security/authenticationpolicy/SecureLockDeviceService.java b/services/core/java/com/android/server/security/authenticationpolicy/SecureLockDeviceService.java
new file mode 100644
index 000000000000..7b89723deb6c
--- /dev/null
+++ b/services/core/java/com/android/server/security/authenticationpolicy/SecureLockDeviceService.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.security.authenticationpolicy;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.security.authenticationpolicy.AuthenticationPolicyManager;
+import android.security.authenticationpolicy.AuthenticationPolicyManager.DisableSecureLockDeviceRequestStatus;
+import android.security.authenticationpolicy.AuthenticationPolicyManager.EnableSecureLockDeviceRequestStatus;
+import android.security.authenticationpolicy.DisableSecureLockDeviceParams;
+import android.security.authenticationpolicy.EnableSecureLockDeviceParams;
+import android.util.Slog;
+
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
+
+/**
+ * System service for remotely calling secure lock on the device.
+ *
+ * Callers will access this class via
+ * {@link com.android.server.security.authenticationpolicy.AuthenticationPolicyService}.
+ *
+ * @see AuthenticationPolicyService
+ * @see AuthenticationPolicyManager#enableSecureLockDevice
+ * @see AuthenticationPolicyManager#disableSecureLockDevice
+ * @hide
+ */
+public class SecureLockDeviceService extends SecureLockDeviceServiceInternal {
+ private static final String TAG = "SecureLockDeviceService";
+ private final Context mContext;
+
+ public SecureLockDeviceService(@NonNull Context context) {
+ mContext = context;
+ }
+
+ private void start() {
+ // Expose private service for system components to use.
+ LocalServices.addService(SecureLockDeviceServiceInternal.class, this);
+ }
+
+ /**
+ * @see AuthenticationPolicyManager#enableSecureLockDevice
+ * @param params EnableSecureLockDeviceParams for caller to supply params related
+ * to the secure lock device request
+ * @return @EnableSecureLockDeviceRequestStatus int indicating the result of the
+ * secure lock device request
+ *
+ * @hide
+ */
+ @Override
+ @EnableSecureLockDeviceRequestStatus
+ public int enableSecureLockDevice(EnableSecureLockDeviceParams params) {
+ // (1) Call into system_server to lock device, configure allowed auth types
+ // for secure lock
+ // TODO: lock device, configure allowed authentication types for device entry
+ // (2) Call into framework to configure secure lock 2FA lockscreen
+ // update, UI & string updates
+ // TODO: implement 2FA lockscreen when SceneContainerFlag.isEnabled()
+ // TODO: implement 2FA lockscreen when !SceneContainerFlag.isEnabled()
+ // (3) Call into framework to configure keyguard security updates
+ // TODO: implement security updates
+ return AuthenticationPolicyManager.ERROR_UNSUPPORTED;
+ }
+
+ /**
+ * @see AuthenticationPolicyManager#disableSecureLockDevice
+ * @param params @DisableSecureLockDeviceParams for caller to supply params related
+ * to the secure lock device request
+ * @return @DisableSecureLockDeviceRequestStatus int indicating the result of the
+ * secure lock device request
+ *
+ * @hide
+ */
+ @Override
+ @DisableSecureLockDeviceRequestStatus
+ public int disableSecureLockDevice(DisableSecureLockDeviceParams params) {
+ // (1) Call into system_server to reset allowed auth types
+ // TODO: reset allowed authentication types for device entry;
+ // (2) Call into framework to disable secure lock 2FA lockscreen, reset UI
+ // & string updates
+ // TODO: implement reverting to normal lockscreen when SceneContainerFlag.isEnabled()
+ // TODO: implement reverting to normal lockscreen when !SceneContainerFlag.isEnabled()
+ // (3) Call into framework to revert keyguard security updates
+ // TODO: implement reverting security updates
+ return AuthenticationPolicyManager.ERROR_UNSUPPORTED;
+ }
+
+ /**
+ * System service lifecycle.
+ */
+ public static final class Lifecycle extends SystemService {
+ private final SecureLockDeviceService mService;
+
+ public Lifecycle(@NonNull Context context) {
+ super(context);
+ mService = new SecureLockDeviceService(context);
+ }
+
+ @Override
+ public void onStart() {
+ Slog.i(TAG, "Starting SecureLockDeviceService");
+ mService.start();
+ Slog.i(TAG, "Started SecureLockDeviceService");
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/security/authenticationpolicy/SecureLockDeviceServiceInternal.java b/services/core/java/com/android/server/security/authenticationpolicy/SecureLockDeviceServiceInternal.java
new file mode 100644
index 000000000000..b90370956d8b
--- /dev/null
+++ b/services/core/java/com/android/server/security/authenticationpolicy/SecureLockDeviceServiceInternal.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.security.authenticationpolicy;
+
+import android.security.authenticationpolicy.AuthenticationPolicyManager;
+import android.security.authenticationpolicy.AuthenticationPolicyManager.DisableSecureLockDeviceRequestStatus;
+import android.security.authenticationpolicy.AuthenticationPolicyManager.EnableSecureLockDeviceRequestStatus;
+import android.security.authenticationpolicy.DisableSecureLockDeviceParams;
+import android.security.authenticationpolicy.EnableSecureLockDeviceParams;
+
+/**
+ * Local system service interface for {@link SecureLockDeviceService}.
+ *
+ * <p>No permission / argument checks will be performed inside.
+ * Callers must check the calling app permission and the calling package name.
+ *
+ * @hide
+ */
+public abstract class SecureLockDeviceServiceInternal {
+ private static final String TAG = "SecureLockDeviceServiceInternal";
+
+ /**
+ * @see AuthenticationPolicyManager#enableSecureLockDevice(EnableSecureLockDeviceParams)
+ * @param params EnableSecureLockDeviceParams for caller to supply params related
+ * to the secure lock request
+ * @return @EnableSecureLockDeviceRequestStatus int indicating the result of the
+ * secure lock request
+ */
+ @EnableSecureLockDeviceRequestStatus
+ public abstract int enableSecureLockDevice(EnableSecureLockDeviceParams params);
+
+ /**
+ * @see AuthenticationPolicyManager#disableSecureLockDevice(DisableSecureLockDeviceParams)
+ * @param params @DisableSecureLockDeviceParams for caller to supply params related
+ * to the secure lock device request
+ * @return @DisableSecureLockDeviceRequestStatus int indicating the result of the
+ * secure lock device request
+ */
+ @DisableSecureLockDeviceRequestStatus
+ public abstract int disableSecureLockDevice(DisableSecureLockDeviceParams params);
+}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index da478f38498b..0dc1ac32c379 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -251,6 +251,7 @@ import com.android.server.security.KeyAttestationApplicationIdProviderService;
import com.android.server.security.KeyChainSystemService;
import com.android.server.security.advancedprotection.AdvancedProtectionService;
import com.android.server.security.authenticationpolicy.AuthenticationPolicyService;
+import com.android.server.security.authenticationpolicy.SecureLockDeviceService;
import com.android.server.security.forensic.ForensicService;
import com.android.server.security.rkp.RemoteProvisioningService;
import com.android.server.selinux.SelinuxAuditLogsService;
@@ -2659,6 +2660,12 @@ public final class SystemServer implements Dumpable {
mSystemServiceManager.startService(AuthService.class);
t.traceEnd();
+ if (android.security.Flags.secureLockdown()) {
+ t.traceBegin("StartSecureLockDeviceService.Lifecycle");
+ mSystemServiceManager.startService(SecureLockDeviceService.Lifecycle.class);
+ t.traceEnd();
+ }
+
if (android.adaptiveauth.Flags.enableAdaptiveAuth()) {
t.traceBegin("StartAuthenticationPolicyService");
mSystemServiceManager.startService(AuthenticationPolicyService.class);
diff --git a/services/tests/servicestests/src/com/android/server/security/authenticationpolicy/AuthenticationPolicyServiceTest.java b/services/tests/servicestests/src/com/android/server/security/authenticationpolicy/AuthenticationPolicyServiceTest.java
index 2238a1be97a1..ee8eb9b35088 100644
--- a/services/tests/servicestests/src/com/android/server/security/authenticationpolicy/AuthenticationPolicyServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/security/authenticationpolicy/AuthenticationPolicyServiceTest.java
@@ -19,12 +19,14 @@ package com.android.server.security.authenticationpolicy;
import static android.adaptiveauth.Flags.FLAG_ENABLE_ADAPTIVE_AUTH;
import static android.adaptiveauth.Flags.FLAG_REPORT_BIOMETRIC_AUTH_ATTEMPTS;
import static android.security.Flags.FLAG_REPORT_PRIMARY_AUTH_ATTEMPTS;
+import static android.security.authenticationpolicy.AuthenticationPolicyManager.ERROR_UNSUPPORTED;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST;
import static com.android.server.security.authenticationpolicy.AuthenticationPolicyService.MAX_ALLOWED_FAILED_AUTH_ATTEMPTS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assume.assumeTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -95,6 +97,8 @@ public class AuthenticationPolicyServiceTest {
private WindowManagerInternal mWindowManager;
@Mock
private UserManagerInternal mUserManager;
+ @Mock
+ private SecureLockDeviceServiceInternal mSecureLockDeviceService;
@Captor
ArgumentCaptor<LockSettingsStateListener> mLockSettingsStateListenerCaptor;
@@ -123,6 +127,11 @@ public class AuthenticationPolicyServiceTest {
LocalServices.addService(WindowManagerInternal.class, mWindowManager);
LocalServices.removeServiceForTest(UserManagerInternal.class);
LocalServices.addService(UserManagerInternal.class, mUserManager);
+ if (android.security.Flags.secureLockdown()) {
+ LocalServices.removeServiceForTest(SecureLockDeviceServiceInternal.class);
+ LocalServices.addService(SecureLockDeviceServiceInternal.class,
+ mSecureLockDeviceService);
+ }
mAuthenticationPolicyService = new AuthenticationPolicyService(
mContext, mLockPatternUtils);
@@ -136,6 +145,12 @@ public class AuthenticationPolicyServiceTest {
// Set PRIMARY_USER_ID as the parent of MANAGED_PROFILE_USER_ID
when(mUserManager.getProfileParentId(eq(MANAGED_PROFILE_USER_ID)))
.thenReturn(PRIMARY_USER_ID);
+ if (android.security.Flags.secureLockdown()) {
+ when(mSecureLockDeviceService.enableSecureLockDevice(any()))
+ .thenReturn(ERROR_UNSUPPORTED);
+ when(mSecureLockDeviceService.disableSecureLockDevice(any()))
+ .thenReturn(ERROR_UNSUPPORTED);
+ }
}
@After
@@ -143,6 +158,9 @@ public class AuthenticationPolicyServiceTest {
LocalServices.removeServiceForTest(LockSettingsInternal.class);
LocalServices.removeServiceForTest(WindowManagerInternal.class);
LocalServices.removeServiceForTest(UserManagerInternal.class);
+ if (android.security.Flags.secureLockdown()) {
+ LocalServices.removeServiceForTest(SecureLockDeviceServiceInternal.class);
+ }
}
@Test