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

Commit 0e3a4591 authored by Brad Lassey's avatar Brad Lassey Committed by Android (Google) Code Review
Browse files

Merge "Implement device lock state listener" into main

parents 35e40bd5 6ea7c4f5
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -6235,6 +6235,7 @@ package android.app {
  }
  public class KeyguardManager {
    method @FlaggedApi("android.app.device_unlock_listener") @RequiresPermission(android.Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) public void addDeviceLockedStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.KeyguardManager.DeviceLockedStateListener);
    method @RequiresPermission(android.Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) public void addKeyguardLockedStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.KeyguardManager.KeyguardLockedStateListener);
    method @Deprecated public android.content.Intent createConfirmDeviceCredentialIntent(CharSequence, CharSequence);
    method @Deprecated @RequiresPermission(android.Manifest.permission.DISABLE_KEYGUARD) public void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult);
@@ -6244,10 +6245,15 @@ package android.app {
    method public boolean isKeyguardLocked();
    method public boolean isKeyguardSecure();
    method @Deprecated public android.app.KeyguardManager.KeyguardLock newKeyguardLock(String);
    method @FlaggedApi("android.app.device_unlock_listener") @RequiresPermission(android.Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) public void removeDeviceLockedStateListener(@NonNull android.app.KeyguardManager.DeviceLockedStateListener);
    method @RequiresPermission(android.Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) public void removeKeyguardLockedStateListener(@NonNull android.app.KeyguardManager.KeyguardLockedStateListener);
    method public void requestDismissKeyguard(@NonNull android.app.Activity, @Nullable android.app.KeyguardManager.KeyguardDismissCallback);
  }
  @FlaggedApi("android.app.device_unlock_listener") @java.lang.FunctionalInterface public static interface KeyguardManager.DeviceLockedStateListener {
    method public void onDeviceLockedStateChanged(boolean);
  }
  public abstract static class KeyguardManager.KeyguardDismissCallback {
    ctor public KeyguardManager.KeyguardDismissCallback();
    method public void onDismissCancelled();
+96 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.app;

import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -52,7 +53,9 @@ import android.view.IOnKeyguardExitResult;
import android.view.IWindowManager;
import android.view.WindowManagerGlobal;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.IDeviceLockedStateListener;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IKeyguardLockedStateListener;
import com.android.internal.util.Preconditions;
@@ -253,6 +256,26 @@ public class KeyguardManager {
    private final ArrayMap<KeyguardLockedStateListener, Executor>
            mKeyguardLockedStateListeners = new ArrayMap<>();

    private final IDeviceLockedStateListener mIDeviceLockedStateListener =
            new IDeviceLockedStateListener.Stub() {
                @Override
                public void onDeviceLockedStateChanged(boolean isDeviceLocked) {
                    if (!Flags.deviceUnlockListener()) {
                        return;
                    }
                    synchronized (mDeviceLockedStateListeners) {
                        mDeviceLockedStateListeners.forEach((listener, executor) -> {
                            executor.execute(
                                    () -> listener.onDeviceLockedStateChanged(isDeviceLocked));
                        });
                    }
                }
            };

    @GuardedBy("mDeviceLockedStateListeners")
    private final ArrayMap<DeviceLockedStateListener, Executor>
            mDeviceLockedStateListeners = new ArrayMap<>();

    /**
     * Get an intent to prompt the user to confirm credentials (pin, pattern, password or biometrics
     * if enrolled) for the current user of the device. The caller is expected to launch this
@@ -1370,4 +1393,77 @@ public class KeyguardManager {
            }
        }
    }


    /**
     * Listener for device locked state changes.
     */
    @FunctionalInterface
    @FlaggedApi(Flags.FLAG_DEVICE_UNLOCK_LISTENER)
    public interface DeviceLockedStateListener {
        /**
         * Callback function that executes when the device locked state changes.
         */
        void onDeviceLockedStateChanged(boolean isDeviceLocked);
    }


    /**
     * Registers a listener to execute when the device locked state changes.
     *
     * @param executor The {@link Executor} where the {@code listener} will be invoked
     * @param listener The listener to add to receive device locked state changes.
     *
     * @see #isDeviceLocked()
     * @see #removeDeviceLockedStateListener(DeviceLockedStateListener)
     */
    @RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE)
    @FlaggedApi(Flags.FLAG_DEVICE_UNLOCK_LISTENER)
    public void addDeviceLockedStateListener(@NonNull @CallbackExecutor Executor executor,
            @NonNull DeviceLockedStateListener listener) {
        if (!Flags.deviceUnlockListener()) {
            return;
        }

        synchronized (mDeviceLockedStateListeners) {
            mDeviceLockedStateListeners.put(listener, executor);
            if (mDeviceLockedStateListeners.size() > 1) {
                return;
            }
            try {
                mTrustManager.registerDeviceLockedStateListener(mIDeviceLockedStateListener,
                        mContext.getDeviceId());
            } catch (RemoteException re) {
                Log.d(TAG, "TrustManager service died", re);
            }
        }
    }

    /**
     * Unregisters a listener that executes when the device locked state changes.
     *
     * @param listener The listener to remove.
     *
     * @see #isDeviceLocked()
     * @see #addDeviceLockedStateListener(Executor, DeviceLockedStateListener)
     */
    @RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE)
    @FlaggedApi(Flags.FLAG_DEVICE_UNLOCK_LISTENER)
    public void removeDeviceLockedStateListener(@NonNull DeviceLockedStateListener listener) {
        if (!Flags.deviceUnlockListener()) {
            return;
        }

        synchronized (mDeviceLockedStateListeners) {
            mDeviceLockedStateListeners.remove(listener);
            if (!mDeviceLockedStateListeners.isEmpty()) {
                return;
            }
            try {
                mTrustManager.unregisterDeviceLockedStateListener(mIDeviceLockedStateListener);
            } catch (RemoteException re) {
                Log.d(TAG, "TrustManager service died", re);
            }
        }
    }
}
+10 −0
Original line number Diff line number Diff line
package: "android.app"
container: "system"

flag {
     namespace: "wallet_integration"
     name: "device_unlock_listener"
     is_exported: true
     description: "Enable listener API for device unlock."
     bug: "296195355"
}
 No newline at end of file
+5 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.app.trust;

import android.app.trust.ITrustListener;
import android.hardware.biometrics.BiometricSourceType;
import com.android.internal.policy.IDeviceLockedStateListener;

/**
 * System private API to comunicate with trust service.
@@ -43,4 +44,8 @@ interface ITrustManager {
    boolean isActiveUnlockRunning(int userId);
    @EnforcePermission("ACCESS_FINE_LOCATION")
    boolean isInSignificantPlace();
    @EnforcePermission("SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE")
    void registerDeviceLockedStateListener(in IDeviceLockedStateListener listener, int deviceId);
    @EnforcePermission("SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE")
    void unregisterDeviceLockedStateListener(in IDeviceLockedStateListener listener);
}
+31 −0
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@ import android.os.Message;
import android.os.RemoteException;
import android.util.ArrayMap;

import com.android.internal.policy.IDeviceLockedStateListener;

import java.util.ArrayList;
import java.util.List;

@@ -258,6 +260,35 @@ public class TrustManager {
        }
    }

    /**
     * Registers a listener for device lock state events.
     *
     * Requires the {@link android.Manifest.permission#SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE}
     * permission.
     */
    public void registerDeviceLockedStateListener(final IDeviceLockedStateListener listener,
            int deviceId) {
        try {
            mService.registerDeviceLockedStateListener(listener, deviceId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Unregisters a listener for device lock state events.
     *
     * Requires the {@link android.Manifest.permission#SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE}
     * permission.
     */
    public void unregisterDeviceLockedStateListener(final IDeviceLockedStateListener listener) {
        try {
            mService.unregisterDeviceLockedStateListener(listener);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * @return whether {@param userId} has enabled and configured trust agents. Ignores short-term
     * unavailability of trust due to {@link LockPatternUtils.StrongAuthTracker}.
Loading