Merge "Add role guarded APIs for subscribing to keyguard locked state in KeyguardManager." into tm-dev
This commit is contained in:
@@ -189,6 +189,7 @@ package android {
|
||||
field public static final String START_VIEW_APP_FEATURES = "android.permission.START_VIEW_APP_FEATURES";
|
||||
field public static final String START_VIEW_PERMISSION_USAGE = "android.permission.START_VIEW_PERMISSION_USAGE";
|
||||
field public static final String STATUS_BAR = "android.permission.STATUS_BAR";
|
||||
field public static final String SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE = "android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE";
|
||||
field public static final String SYSTEM_ALERT_WINDOW = "android.permission.SYSTEM_ALERT_WINDOW";
|
||||
field public static final String TRANSMIT_IR = "android.permission.TRANSMIT_IR";
|
||||
field public static final String UNINSTALL_SHORTCUT = "com.android.launcher.permission.UNINSTALL_SHORTCUT";
|
||||
@@ -5677,6 +5678,7 @@ package android.app {
|
||||
}
|
||||
|
||||
public class KeyguardManager {
|
||||
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);
|
||||
method @Deprecated public boolean inKeyguardRestrictedInputMode();
|
||||
@@ -5685,6 +5687,7 @@ package android.app {
|
||||
method public boolean isKeyguardLocked();
|
||||
method public boolean isKeyguardSecure();
|
||||
method @Deprecated public android.app.KeyguardManager.KeyguardLock newKeyguardLock(String);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -5700,6 +5703,10 @@ package android.app {
|
||||
method @Deprecated @RequiresPermission(android.Manifest.permission.DISABLE_KEYGUARD) public void reenableKeyguard();
|
||||
}
|
||||
|
||||
@java.lang.FunctionalInterface public static interface KeyguardManager.KeyguardLockedStateListener {
|
||||
method public void onKeyguardLockedStateChanged(boolean);
|
||||
}
|
||||
|
||||
@Deprecated public static interface KeyguardManager.OnKeyguardExitResult {
|
||||
method @Deprecated public void onKeyguardExitResult(boolean);
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ import android.view.WindowManager.LayoutParams;
|
||||
import android.view.WindowManagerGlobal;
|
||||
|
||||
import com.android.internal.policy.IKeyguardDismissCallback;
|
||||
import com.android.internal.policy.IKeyguardLockedStateListener;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.internal.widget.IWeakEscrowTokenActivatedListener;
|
||||
import com.android.internal.widget.IWeakEscrowTokenRemovedListener;
|
||||
@@ -183,6 +184,10 @@ public class KeyguardManager {
|
||||
})
|
||||
@interface LockTypes {}
|
||||
|
||||
// TODO(b/220379118): register only one binder listener and keep a map of listener to executor.
|
||||
private final ArrayMap<KeyguardLockedStateListener, IKeyguardLockedStateListener>
|
||||
mKeyguardLockedStateListeners = 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
|
||||
@@ -534,7 +539,7 @@ public class KeyguardManager {
|
||||
/**
|
||||
* Return whether the keyguard is currently locked.
|
||||
*
|
||||
* @return true if keyguard is locked.
|
||||
* @return {@code true} if the keyguard is locked.
|
||||
*/
|
||||
public boolean isKeyguardLocked() {
|
||||
try {
|
||||
@@ -550,7 +555,7 @@ public class KeyguardManager {
|
||||
*
|
||||
* <p>See also {@link #isDeviceSecure()} which ignores SIM locked states.
|
||||
*
|
||||
* @return true if a PIN, pattern or password is set or a SIM card is locked.
|
||||
* @return {@code true} if a PIN, pattern or password is set or a SIM card is locked.
|
||||
*/
|
||||
public boolean isKeyguardSecure() {
|
||||
try {
|
||||
@@ -565,7 +570,7 @@ public class KeyguardManager {
|
||||
* keyguard password emergency screen). When in such mode, certain keys,
|
||||
* such as the Home key and the right soft keys, don't work.
|
||||
*
|
||||
* @return true if in keyguard restricted input mode.
|
||||
* @return {@code true} if in keyguard restricted input mode.
|
||||
* @deprecated Use {@link #isKeyguardLocked()} instead.
|
||||
*/
|
||||
public boolean inKeyguardRestrictedInputMode() {
|
||||
@@ -576,7 +581,7 @@ public class KeyguardManager {
|
||||
* Returns whether the device is currently locked and requires a PIN, pattern or
|
||||
* password to unlock.
|
||||
*
|
||||
* @return true if unlocking the device currently requires a PIN, pattern or
|
||||
* @return {@code true} if unlocking the device currently requires a PIN, pattern or
|
||||
* password.
|
||||
*/
|
||||
public boolean isDeviceLocked() {
|
||||
@@ -603,7 +608,7 @@ public class KeyguardManager {
|
||||
*
|
||||
* <p>See also {@link #isKeyguardSecure} which treats SIM locked states as secure.
|
||||
*
|
||||
* @return true if a PIN, pattern or password was set.
|
||||
* @return {@code true} if a PIN, pattern or password was set.
|
||||
*/
|
||||
public boolean isDeviceSecure() {
|
||||
return isDeviceSecure(mContext.getUserId());
|
||||
@@ -762,7 +767,7 @@ public class KeyguardManager {
|
||||
* as the output of String#getBytes
|
||||
* @param complexity - complexity level imposed by the requester
|
||||
* as defined in {@code DevicePolicyManager.PasswordComplexity}
|
||||
* @return true if the password is valid, false otherwise
|
||||
* @return {@code true} if the password is valid, false otherwise
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(Manifest.permission.SET_INITIAL_LOCK)
|
||||
@@ -821,7 +826,7 @@ public class KeyguardManager {
|
||||
* as the output of String#getBytes
|
||||
* @param complexity - complexity level imposed by the requester
|
||||
* as defined in {@code DevicePolicyManager.PasswordComplexity}
|
||||
* @return true if the lock is successfully set, false otherwise
|
||||
* @return {@code true} if the lock is successfully set, false otherwise
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(Manifest.permission.SET_INITIAL_LOCK)
|
||||
@@ -903,8 +908,8 @@ public class KeyguardManager {
|
||||
/**
|
||||
* Remove a weak escrow token.
|
||||
*
|
||||
* @return true if the given handle refers to a valid weak token previously returned from
|
||||
* {@link #addWeakEscrowToken}, whether it's active or not. return false otherwise.
|
||||
* @return {@code true} if the given handle refers to a valid weak token previously returned
|
||||
* from {@link #addWeakEscrowToken}, whether it's active or not. return false otherwise.
|
||||
* @hide
|
||||
*/
|
||||
@RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
|
||||
@@ -944,7 +949,7 @@ public class KeyguardManager {
|
||||
/**
|
||||
* Register the given WeakEscrowTokenRemovedListener.
|
||||
*
|
||||
* @return true if the listener is registered successfully, return false otherwise.
|
||||
* @return {@code true} if the listener is registered successfully, return false otherwise.
|
||||
* @hide
|
||||
*/
|
||||
@RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
|
||||
@@ -982,7 +987,7 @@ public class KeyguardManager {
|
||||
/**
|
||||
* Unregister the given WeakEscrowTokenRemovedListener.
|
||||
*
|
||||
* @return true if the listener is unregistered successfully, return false otherwise.
|
||||
* @return {@code true} if the listener is unregistered successfully, return false otherwise.
|
||||
* @hide
|
||||
*/
|
||||
@RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
|
||||
@@ -1076,4 +1081,61 @@ public class KeyguardManager {
|
||||
throw new IllegalArgumentException("Unknown lock type " + lockType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for keyguard locked state changes.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface KeyguardLockedStateListener {
|
||||
/**
|
||||
* Callback function that executes when the keyguard locked state changes.
|
||||
*/
|
||||
void onKeyguardLockedStateChanged(boolean isKeyguardLocked);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a listener to execute when the keyguard visibility changes.
|
||||
*
|
||||
* @param listener The listener to add to receive keyguard visibility changes.
|
||||
*/
|
||||
@RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE)
|
||||
public void addKeyguardLockedStateListener(@NonNull @CallbackExecutor Executor executor,
|
||||
@NonNull KeyguardLockedStateListener listener) {
|
||||
synchronized (mKeyguardLockedStateListeners) {
|
||||
try {
|
||||
final IKeyguardLockedStateListener innerListener =
|
||||
new IKeyguardLockedStateListener.Stub() {
|
||||
@Override
|
||||
public void onKeyguardLockedStateChanged(boolean isKeyguardLocked) {
|
||||
executor.execute(
|
||||
() -> listener.onKeyguardLockedStateChanged(isKeyguardLocked));
|
||||
}
|
||||
};
|
||||
mWM.addKeyguardLockedStateListener(innerListener);
|
||||
mKeyguardLockedStateListeners.put(listener, innerListener);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a listener that executes when the keyguard visibility changes.
|
||||
*/
|
||||
@RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE)
|
||||
public void removeKeyguardLockedStateListener(@NonNull KeyguardLockedStateListener listener) {
|
||||
synchronized (mKeyguardLockedStateListeners) {
|
||||
IKeyguardLockedStateListener innerListener = mKeyguardLockedStateListeners.get(
|
||||
listener);
|
||||
if (innerListener == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mWM.removeKeyguardLockedStateListener(innerListener);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
mKeyguardLockedStateListeners.remove(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.view;
|
||||
|
||||
import com.android.internal.os.IResultReceiver;
|
||||
import com.android.internal.policy.IKeyguardDismissCallback;
|
||||
import com.android.internal.policy.IKeyguardLockedStateListener;
|
||||
import com.android.internal.policy.IShortcutService;
|
||||
|
||||
import android.app.IAssistDataReceiver;
|
||||
@@ -199,6 +200,9 @@ interface IWindowManager
|
||||
boolean isKeyguardSecure(int userId);
|
||||
void dismissKeyguard(IKeyguardDismissCallback callback, CharSequence message);
|
||||
|
||||
void addKeyguardLockedStateListener(in IKeyguardLockedStateListener listener);
|
||||
void removeKeyguardLockedStateListener(in IKeyguardLockedStateListener listener);
|
||||
|
||||
// Requires INTERACT_ACROSS_USERS_FULL permission
|
||||
void setSwitchingUser(boolean switching);
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.internal.policy;
|
||||
|
||||
oneway interface IKeyguardLockedStateListener {
|
||||
void onKeyguardLockedStateChanged(boolean isKeyguardLocked);
|
||||
}
|
||||
@@ -4119,6 +4119,13 @@
|
||||
<permission android:name="android.permission.MANAGE_HOTWORD_DETECTION"
|
||||
android:protectionLevel="internal|preinstalled" />
|
||||
|
||||
<!-- Allows an application to subscribe to keyguard locked (i.e., showing) state.
|
||||
<p>Protection level: internal|role
|
||||
<p>Intended for use by ROLE_ASSISTANT only.
|
||||
-->
|
||||
<permission android:name="android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE"
|
||||
android:protectionLevel="internal|role"/>
|
||||
|
||||
<!-- Must be required by a {@link android.service.autofill.AutofillService},
|
||||
to ensure that only the system can bind to it.
|
||||
<p>Protection level: signature
|
||||
|
||||
@@ -588,6 +588,9 @@
|
||||
<uses-permission android:name="android.permission.MANAGE_HOTWORD_DETECTION" />
|
||||
<uses-permission android:name="android.permission.BIND_HOTWORD_DETECTION_SERVICE" />
|
||||
|
||||
<!-- Permission required for CTS test - KeyguardLockedStateApiTest -->
|
||||
<uses-permission android:name="android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE" />
|
||||
|
||||
<uses-permission android:name="android.permission.MANAGE_APP_HIBERNATION"/>
|
||||
|
||||
<!-- Permission required for CTS test - ResourceObserverNativeTest -->
|
||||
|
||||
@@ -200,6 +200,7 @@ import android.os.PowerManager.ServiceType;
|
||||
import android.os.PowerManagerInternal;
|
||||
import android.os.PowerSaveState;
|
||||
import android.os.RemoteCallback;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.ServiceManager;
|
||||
@@ -288,6 +289,7 @@ import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.os.IResultReceiver;
|
||||
import com.android.internal.policy.IKeyguardDismissCallback;
|
||||
import com.android.internal.policy.IKeyguardLockedStateListener;
|
||||
import com.android.internal.policy.IShortcutService;
|
||||
import com.android.internal.policy.KeyInterceptionInfo;
|
||||
import com.android.internal.protolog.ProtoLogImpl;
|
||||
@@ -460,6 +462,10 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
|
||||
final private KeyguardDisableHandler mKeyguardDisableHandler;
|
||||
|
||||
private final RemoteCallbackList<IKeyguardLockedStateListener> mKeyguardLockedStateListeners =
|
||||
new RemoteCallbackList<>();
|
||||
private boolean mDispatchedKeyguardLockedState = false;
|
||||
|
||||
// VR Vr2d Display Id.
|
||||
int mVr2dDisplayId = INVALID_DISPLAY;
|
||||
boolean mVrModeEnabled = false;
|
||||
@@ -3029,6 +3035,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
@Override
|
||||
public void onKeyguardShowingAndNotOccludedChanged() {
|
||||
mH.sendEmptyMessage(H.RECOMPUTE_FOCUS);
|
||||
dispatchKeyguardLockedStateState();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -3218,6 +3225,50 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE)
|
||||
@Override
|
||||
public void addKeyguardLockedStateListener(IKeyguardLockedStateListener listener) {
|
||||
enforceSubscribeToKeyguardLockedStatePermission();
|
||||
boolean registered = mKeyguardLockedStateListeners.register(listener);
|
||||
if (!registered) {
|
||||
Slog.w(TAG, "Failed to register listener: " + listener);
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE)
|
||||
@Override
|
||||
public void removeKeyguardLockedStateListener(IKeyguardLockedStateListener listener) {
|
||||
enforceSubscribeToKeyguardLockedStatePermission();
|
||||
mKeyguardLockedStateListeners.unregister(listener);
|
||||
}
|
||||
|
||||
private void enforceSubscribeToKeyguardLockedStatePermission() {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE,
|
||||
Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE
|
||||
+ " permission required to read keyguard visibility");
|
||||
}
|
||||
|
||||
private void dispatchKeyguardLockedStateState() {
|
||||
mH.post(() -> {
|
||||
final boolean isKeyguardLocked = mPolicy.isKeyguardShowing();
|
||||
if (mDispatchedKeyguardLockedState == isKeyguardLocked) {
|
||||
return;
|
||||
}
|
||||
final int n = mKeyguardLockedStateListeners.beginBroadcast();
|
||||
for (int i = 0; i < n; i++) {
|
||||
try {
|
||||
mKeyguardLockedStateListeners.getBroadcastItem(i).onKeyguardLockedStateChanged(
|
||||
isKeyguardLocked);
|
||||
} catch (RemoteException e) {
|
||||
// Handled by the RemoteCallbackList.
|
||||
}
|
||||
}
|
||||
mKeyguardLockedStateListeners.finishBroadcast();
|
||||
mDispatchedKeyguardLockedState = isKeyguardLocked;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSwitchingUser(boolean switching) {
|
||||
if (!checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
|
||||
|
||||
Reference in New Issue
Block a user