summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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