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

Commit 9a42e3af authored by Grace Cheng's avatar Grace Cheng Committed by Android (Google) Code Review
Browse files

Merge "Implement listener to notify clients of updates to secure lock device status" into main

parents ffe40e74 136096ae
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -12739,6 +12739,8 @@ package android.security.authenticationpolicy {
    method @FlaggedApi("android.security.secure_lockdown") @RequiresPermission(android.Manifest.permission.MANAGE_SECURE_LOCK_DEVICE) public int enableSecureLockDevice(@NonNull android.security.authenticationpolicy.EnableSecureLockDeviceParams);
    method @FlaggedApi("android.security.secure_lock_device") @RequiresPermission(android.Manifest.permission.MANAGE_SECURE_LOCK_DEVICE) public int isSecureLockDeviceAvailable();
    method @FlaggedApi("android.security.secure_lock_device") @RequiresPermission(android.Manifest.permission.MANAGE_SECURE_LOCK_DEVICE) public boolean isSecureLockDeviceEnabled();
    method @FlaggedApi("android.security.secure_lock_device") @RequiresPermission(android.Manifest.permission.MANAGE_SECURE_LOCK_DEVICE) public void registerSecureLockDeviceStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.security.authenticationpolicy.AuthenticationPolicyManager.SecureLockDeviceStatusListener);
    method @FlaggedApi("android.security.secure_lock_device") @RequiresPermission(android.Manifest.permission.MANAGE_SECURE_LOCK_DEVICE) public void unregisterSecureLockDeviceStatusListener(@NonNull android.security.authenticationpolicy.AuthenticationPolicyManager.SecureLockDeviceStatusListener);
    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
@@ -12749,9 +12751,15 @@ package android.security.authenticationpolicy {
    field @FlaggedApi("android.security.secure_lockdown") public static final int SUCCESS = 0; // 0x0
  }
  @FlaggedApi("android.security.secure_lock_device") public static interface AuthenticationPolicyManager.SecureLockDeviceStatusListener {
    method public void onSecureLockDeviceAvailableStatusChanged(int);
    method public void onSecureLockDeviceEnabledStatusChanged(boolean);
  }
  @FlaggedApi("android.security.secure_lockdown") public final class DisableSecureLockDeviceParams implements android.os.Parcelable {
    ctor public DisableSecureLockDeviceParams(@NonNull CharSequence);
    method public int describeContents();
    method @NonNull public CharSequence getMessage();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.security.authenticationpolicy.DisableSecureLockDeviceParams> CREATOR;
  }
@@ -12759,6 +12767,7 @@ package android.security.authenticationpolicy {
  @FlaggedApi("android.security.secure_lockdown") public final class EnableSecureLockDeviceParams implements android.os.Parcelable {
    ctor public EnableSecureLockDeviceParams(@NonNull CharSequence);
    method public int describeContents();
    method @NonNull public CharSequence getMessage();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.security.authenticationpolicy.EnableSecureLockDeviceParams> CREATOR;
  }
+174 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ import static android.Manifest.permission.MANAGE_SECURE_LOCK_DEVICE;
import static android.security.Flags.FLAG_SECURE_LOCKDOWN;
import static android.security.Flags.FLAG_SECURE_LOCK_DEVICE;

import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -26,10 +27,16 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.os.Binder;
import android.os.Build;
import android.os.RemoteException;
import android.util.Log;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;

/**
 * AuthenticationPolicyManager is a centralized interface for managing authentication related
@@ -59,6 +66,15 @@ import java.lang.annotation.RetentionPolicy;
 * {@link #isSecureLockDeviceEnabled}. This will require the caller to have the
 * {@link android.Manifest.permission#MANAGE_SECURE_LOCK_DEVICE} permission.
 *
 *
 * <p>
 * To listen for changes in the availability or enabled / disabled status of Secure Lock Device,
 * register a {@link SecureLockDeviceStatusListener} using
 * {@link #registerSecureLockDeviceStatusListener(Executor, SecureLockDeviceStatusListener)}.
 *
 * To unregister a previously registered listener, use
 * {@link #unregisterSecureLockDeviceStatusListener(SecureLockDeviceStatusListener)}.
 *
 * @hide
 */
@SystemApi
@@ -66,10 +82,20 @@ import java.lang.annotation.RetentionPolicy;
@SystemService(Context.AUTHENTICATION_POLICY_SERVICE)
public final class AuthenticationPolicyManager {
    private static final String TAG = "AuthenticationPolicyManager";
    private static final boolean DEBUG = Build.IS_DEBUGGABLE;


    @NonNull private final IAuthenticationPolicyService mAuthenticationPolicyService;
    @NonNull private final Context mContext;

    /**
     * Map to store registered client listeners and their corresponding AIDL stubs.
     */
    private final ConcurrentHashMap
            <SecureLockDeviceStatusListener, ISecureLockDeviceStatusListener.Stub>
            mSecureLockDeviceStatusListeners = new ConcurrentHashMap<>();


    /**
     * Success result code for {@link #enableSecureLockDevice} and {@link #disableSecureLockDevice}.
     *
@@ -214,6 +240,154 @@ public final class AuthenticationPolicyManager {
        mAuthenticationPolicyService = authenticationPolicyService;
    }

    /**
     * Listener for updates to Secure Lock Device status. Clients can implement this interface
     * and register it using {@link #registerSecureLockDeviceStatusListener(Executor,
     * SecureLockDeviceStatusListener)} to receive callbacks when the status of secure lock
     * device changes.
     *
     * @hide
     */
    @SystemApi
    @FlaggedApi(FLAG_SECURE_LOCK_DEVICE)
    public interface SecureLockDeviceStatusListener {
        /**
         * Called when the enabled state of secure lock device changes.
         * @param enabled true if secure lock device is now enabled, false otherwise.
         */
        void onSecureLockDeviceEnabledStatusChanged(boolean enabled);

        /**
         * Called when the availability of secure lock device changes for the listening user.
         * @param available An int of type
         * {@link AuthenticationPolicyManager.IsSecureLockDeviceAvailableRequestStatus} that
         *                  indicates if the listening user has the necessary requirements to
         *                  enable secure lock device ({@link #SUCCESS} if the user can enable
         *                  secure lock device).
         */
        void onSecureLockDeviceAvailableStatusChanged(int available);
    }

    /**
     * Registers a listener for updates to Secure Lock Device status, including whether secure
     * lock device is currently enabled / disabled, and whether the calling user meets the
     * prerequisites to enable secure lock device. The listener is immediately called with the
     * current status upon registration.
     *
     * @param executor The executor on which the listener callbacks will be invoked.
     * @param listener The listener to register for notifications about updates to secure lock
     *                 device status.
     *
     * @hide
     */
    @SystemApi
    @FlaggedApi(FLAG_SECURE_LOCK_DEVICE)
    @RequiresPermission(MANAGE_SECURE_LOCK_DEVICE)
    public void registerSecureLockDeviceStatusListener(
            @NonNull @CallbackExecutor Executor executor,
            @NonNull SecureLockDeviceStatusListener listener
    ) {
        Objects.requireNonNull(executor, "Executor cannot be null");
        Objects.requireNonNull(listener, "Listener cannot be null");

        if (mSecureLockDeviceStatusListeners.containsKey(listener)) {
            if (DEBUG) {
                Log.d(TAG, "registerSecureLockDeviceStatusListener: listener already registered");
            }
            return;
        }

        ISecureLockDeviceStatusListener.Stub stub = new ISecureLockDeviceStatusListener.Stub() {
            @Override
            public void onSecureLockDeviceEnabledStatusChanged(boolean enabled) {
                if (!mSecureLockDeviceStatusListeners.containsKey(listener)) {
                    if (DEBUG) {
                        Log.d(TAG, "Listener " + listener + " no longer registered. Skipping "
                                + "onSecureLockDeviceEnabledStatusChanged(" + enabled + ")");
                    }
                    return;
                }
                final long identity = Binder.clearCallingIdentity();
                try {
                    executor.execute(() ->
                            listener.onSecureLockDeviceEnabledStatusChanged(enabled));
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }

            @Override
            public void onSecureLockDeviceAvailableStatusChanged(int available) {
                if (!mSecureLockDeviceStatusListeners.containsKey(listener)) {
                    if (DEBUG) {
                        Log.d(TAG, "Listener " + listener + " no longer registered. Skipping "
                                + "onSecureLockDeviceAvailableStatusChanged(" + available + ")");
                    }
                    return;
                }
                final long identity = Binder.clearCallingIdentity();
                try {
                    executor.execute(() ->
                            listener.onSecureLockDeviceAvailableStatusChanged(available));
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
        };

        mSecureLockDeviceStatusListeners.put(listener, stub);
        boolean serviceCallSuccessful = false;
        try {
            mAuthenticationPolicyService.registerSecureLockDeviceStatusListener(mContext.getUser(),
                    stub);
            serviceCallSuccessful = true;
            if (DEBUG) {
                Log.d(TAG, "Registered listener: " + listener);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } finally {
            if (!serviceCallSuccessful) {
                mSecureLockDeviceStatusListeners.remove(listener);
                Log.w(TAG, "Failed to register listener " + listener + "with service, removing"
                        + " from local map.");
            }
        }
    }

    /**
     * Unregisters a previously registered listener for updates to Secure Lock Device status.
     *
     * @param listener The listener to unregister.
     * @throws IllegalArgumentException if the listener was not previously registered.
     *
     * @hide
     */
    @SystemApi
    @FlaggedApi(FLAG_SECURE_LOCK_DEVICE)
    @RequiresPermission(MANAGE_SECURE_LOCK_DEVICE)
    public void unregisterSecureLockDeviceStatusListener(
            @NonNull SecureLockDeviceStatusListener listener
    ) {
        Objects.requireNonNull(listener, "Listener cannot be null");
        ISecureLockDeviceStatusListener.Stub stub =
                mSecureLockDeviceStatusListeners.remove(listener);

        if (stub == null) {
            Log.d(TAG, "unregisterSecureLockDeviceStatusListener: listener not registered");
            return;
        }

        try {
            mAuthenticationPolicyService.unregisterSecureLockDeviceStatusListener(stub);
            if (DEBUG) {
                Log.d(TAG, "Unregistered listener: " + listener);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Called by a privileged component to indicate if secure lock device is available for the
     * calling user.
+5 −0
Original line number Diff line number Diff line
@@ -64,6 +64,11 @@ public final class DisableSecureLockDeviceParams implements Parcelable {
        mMessage = Objects.requireNonNull(in.readCharSequence());
    }

    @NonNull
    public CharSequence getMessage() {
        return mMessage;
    }

    public static final @NonNull Creator<DisableSecureLockDeviceParams> CREATOR =
            new Creator<DisableSecureLockDeviceParams>() {
                @Override
+5 −1
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@ import java.util.Objects;
@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.
@@ -64,6 +63,11 @@ public final class EnableSecureLockDeviceParams implements Parcelable {
        mMessage = Objects.requireNonNull(in.readCharSequence());
    }

    @NonNull
    public CharSequence getMessage() {
        return mMessage;
    }

    public static final @NonNull Creator<EnableSecureLockDeviceParams> CREATOR =
            new Creator<EnableSecureLockDeviceParams>() {
                @Override
+8 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.security.authenticationpolicy;
import android.os.UserHandle;
import android.security.authenticationpolicy.EnableSecureLockDeviceParams;
import android.security.authenticationpolicy.DisableSecureLockDeviceParams;
import android.security.authenticationpolicy.ISecureLockDeviceStatusListener;

/**
 * Communication channel from AuthenticationPolicyManager to AuthenticationPolicyService.
@@ -36,4 +37,11 @@ interface IAuthenticationPolicyService {

    @EnforcePermission("MANAGE_SECURE_LOCK_DEVICE")
    boolean isSecureLockDeviceEnabled();

    @EnforcePermission("MANAGE_SECURE_LOCK_DEVICE")
    void registerSecureLockDeviceStatusListener(in UserHandle user,
            in ISecureLockDeviceStatusListener listener);

    @EnforcePermission("MANAGE_SECURE_LOCK_DEVICE")
    void unregisterSecureLockDeviceStatusListener(in ISecureLockDeviceStatusListener listener);
}
 No newline at end of file
Loading