Add explicit method to dismiss Keyguard
The flag is a bit clunky for most cases, and a method is more
clear.
Test: cts/hostsidetests/services/activityandwindowmanager/util/run-test
android.server.cts.KeyguardTests
Test: cts/hostsidetests/services/activityandwindowmanager/util/run-test
android.server.cts.KeyguardLockedTests
Test: runtest systemui -c
com.android.systemui.keyguard.DismissCallbackRegistryTest
Bug: 30961403
Bug: 27422134
Change-Id: I39de90c7cfecd99350a74f72cd76418e337f2b79
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8bd7506..1beffc4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -23,6 +23,8 @@
import android.app.WaitResult;
import android.graphics.PointF;
import android.os.IDeviceIdentifiersPolicyService;
+
+import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.telephony.TelephonyIntents;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
@@ -22530,6 +22532,17 @@
return rInfo != null && rInfo.activityInfo != null;
}
+ @Override
+ public void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback)
+ throws RemoteException {
+ final long callingId = Binder.clearCallingIdentity();
+ try {
+ mKeyguardController.dismissKeyguard(token, callback);
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+ }
+
/**
* Attach an agent to the specified process (proces name or PID)
*/
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 90b46ed..214a357 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -207,6 +207,8 @@
boolean keysPaused; // has key dispatching been paused for it?
int launchMode; // the launch mode activity attribute.
boolean visible; // does this activity's window need to be shown?
+ boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
+ // might hide this activity?
boolean sleeping; // have we told the activity to sleep?
boolean nowVisible; // is this activity's window visible?
boolean idle; // has the activity gone idle?
@@ -1248,9 +1250,15 @@
mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
}
- /** Return true if the input activity should be made visible */
- boolean shouldBeVisible(boolean behindTranslucentActivity, boolean stackVisibleBehind,
- ActivityRecord visibleBehind, boolean behindFullscreenActivity) {
+ /**
+ * @return true if the input activity should be made visible, ignoring any effect Keyguard
+ * might have on the visibility
+ *
+ * @see {@link ActivityStack#checkKeyguardVisibility}
+ */
+ boolean shouldBeVisibleIgnoringKeyguard(boolean behindTranslucentActivity,
+ boolean stackVisibleBehind, ActivityRecord visibleBehind,
+ boolean behindFullscreenActivity) {
if (!okToShowLocked()) {
return false;
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 473b1a3..005b8aa 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1660,13 +1660,15 @@
aboveTop = false;
// Check whether activity should be visible without Keyguard influence
- final boolean shouldBeVisible = r.shouldBeVisible(behindTranslucentActivity,
- stackVisibleBehind, visibleBehind, behindFullscreenActivity);
+ final boolean visibleIgnoringKeyguard = r.shouldBeVisibleIgnoringKeyguard(
+ behindTranslucentActivity, stackVisibleBehind, visibleBehind,
+ behindFullscreenActivity);
+ r.visibleIgnoringKeyguard = visibleIgnoringKeyguard;
// Now check whether it's really visible depending on Keyguard state.
- final boolean reallyVisible = checkKeyguardVisibility(r, shouldBeVisible,
- isTop);
- if (shouldBeVisible) {
+ final boolean reallyVisible = checkKeyguardVisibility(r,
+ visibleIgnoringKeyguard, isTop);
+ if (visibleIgnoringKeyguard) {
behindFullscreenActivity = updateBehindFullscreen(stackInvisible,
behindFullscreenActivity, task, r);
if (behindFullscreenActivity && !r.fullscreen) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 5d8d79f..b53a680 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -4075,7 +4075,7 @@
Settings.Secure.LOCK_TO_APP_EXIT_LOCKED) != 0;
if (mLockTaskModeState == LOCK_TASK_MODE_PINNED && shouldLockKeyguard) {
mWindowManager.lockNow(null);
- mWindowManager.dismissKeyguard();
+ mWindowManager.dismissKeyguard(null /* callback */);
new LockPatternUtils(mService.mContext)
.requireCredentialEntry(UserHandle.USER_ALL);
}
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index 9d8c383..5e02597 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -20,6 +20,8 @@
import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
@@ -29,6 +31,11 @@
import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_UNOCCLUDE;
import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.server.wm.WindowManagerService;
import java.io.PrintWriter;
@@ -42,6 +49,8 @@
*/
class KeyguardController {
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "KeyguardController" : TAG_AM;
+
private final ActivityManagerService mService;
private final ActivityStackSupervisor mStackSupervisor;
private WindowManagerService mWindowManager;
@@ -108,7 +117,6 @@
mWindowManager.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
false /* alwaysKeepCurrent */, convertTransitFlags(flags),
false /* forceOverride */);
- mWindowManager.keyguardGoingAway(flags);
mService.updateSleepIfNeededLocked();
// Some stack visibility might change (e.g. docked stack)
@@ -122,6 +130,23 @@
}
}
+ void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback) {
+ final ActivityRecord activityRecord = ActivityRecord.forTokenLocked(token);
+ if (activityRecord == null || !activityRecord.visibleIgnoringKeyguard) {
+ failCallback(callback);
+ return;
+ }
+ mWindowManager.dismissKeyguard(callback);
+ }
+
+ private void failCallback(IKeyguardDismissCallback callback) {
+ try {
+ callback.onDismissError();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call callback", e);
+ }
+ }
+
private int convertTransitFlags(int keyguardGoingAwayFlags) {
int result = 0;
if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0) {
@@ -215,7 +240,7 @@
*/
private void handleDismissKeyguard() {
if (mDismissingKeyguardActivity != null) {
- mWindowManager.dismissKeyguard();
+ mWindowManager.dismissKeyguard(null /* callback */);
// If we are about to unocclude the Keyguard, but we can dismiss it without security,
// we immediately dismiss the Keyguard so the activity gets shown without a flicker.
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index ccdda13..f48db05 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -216,6 +216,7 @@
import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
import com.android.internal.policy.PhoneWindow;
import com.android.internal.statusbar.IStatusBarService;
@@ -6631,12 +6632,18 @@
}
@Override
- public void dismissKeyguardLw() {
+ public void dismissKeyguardLw(IKeyguardDismissCallback callback) {
if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
// ask the keyguard to prompt the user to authenticate if necessary
- mKeyguardDelegate.dismiss(true /* allowWhileOccluded */);
+ mKeyguardDelegate.dismiss(callback);
+ } else if (callback != null) {
+ try {
+ callback.onDismissError();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call callback", e);
+ }
}
}
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index f37f987..1b4eaf5 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -15,6 +15,7 @@
import android.util.Slog;
import android.view.WindowManagerPolicy.OnKeyguardExitResult;
+import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IKeyguardDrawnCallback;
import com.android.internal.policy.IKeyguardExitCallback;
import com.android.internal.policy.IKeyguardService;
@@ -244,9 +245,9 @@
mKeyguardState.occluded = isOccluded;
}
- public void dismiss(boolean allowWhileOccluded) {
+ public void dismiss(IKeyguardDismissCallback callback) {
if (mKeyguardService != null) {
- mKeyguardService.dismiss(allowWhileOccluded);
+ mKeyguardService.dismiss(callback);
}
}
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
index c4a0dd3..0b839b8 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
@@ -22,6 +22,7 @@
import android.os.RemoteException;
import android.util.Slog;
+import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IKeyguardDrawnCallback;
import com.android.internal.policy.IKeyguardExitCallback;
import com.android.internal.policy.IKeyguardService;
@@ -73,9 +74,9 @@
}
@Override // Binder interface
- public void dismiss(boolean allowWhileOccluded) {
+ public void dismiss(IKeyguardDismissCallback callback) {
try {
- mService.dismiss(allowWhileOccluded);
+ mService.dismiss(callback);
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 00d8fba..50b0f38 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import android.Manifest;
+import android.Manifest.permission;
import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -128,6 +129,7 @@
import com.android.internal.R;
import com.android.internal.app.IAssistScreenshotReceiver;
import com.android.internal.os.IResultReceiver;
+import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.view.IInputContext;
@@ -3940,20 +3942,13 @@
}
@Override
- public void dismissKeyguard() {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires DISABLE_KEYGUARD permission");
- }
+ public void dismissKeyguard(IKeyguardDismissCallback callback) {
+ checkCallingPermission(permission.CONTROL_KEYGUARD, "dismissKeyguard");
synchronized(mWindowMap) {
- mPolicy.dismissKeyguardLw();
+ mPolicy.dismissKeyguardLw(callback);
}
}
- @Override
- public void keyguardGoingAway(int flags) {
- }
-
public void onKeyguardOccludedChanged(boolean occluded) {
synchronized (mWindowMap) {
mPolicy.onKeyguardOccludedChangedLw(occluded);
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index ed4c79f..1853a65 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -16,9 +16,11 @@
package com.android.server.wm;
+import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
import com.android.server.input.InputManagerService;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
@@ -528,8 +530,7 @@
}
@Override
- public void dismissKeyguardLw() {
-
+ public void dismissKeyguardLw(@Nullable IKeyguardDismissCallback callback) {
}
@Override