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/Android.mk b/Android.mk
index 552103d..78c9c1d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -338,6 +338,7 @@
core/java/com/android/internal/backup/IObbBackupService.aidl \
core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl \
core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl \
+ core/java/com/android/internal/policy/IKeyguardDismissCallback.aidl \
core/java/com/android/internal/policy/IKeyguardExitCallback.aidl \
core/java/com/android/internal/policy/IKeyguardService.aidl \
core/java/com/android/internal/policy/IKeyguardStateCallback.aidl \
diff --git a/api/current.txt b/api/current.txt
index 8a00273..40b57a3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4817,6 +4817,7 @@
public class KeyguardManager {
method public android.content.Intent createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence);
+ method public void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler);
method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult);
method public boolean inKeyguardRestrictedInputMode();
method public boolean isDeviceLocked();
@@ -4826,12 +4827,19 @@
method public deprecated android.app.KeyguardManager.KeyguardLock newKeyguardLock(java.lang.String);
}
+ public static abstract class KeyguardManager.KeyguardDismissCallback {
+ ctor public KeyguardManager.KeyguardDismissCallback();
+ method public void onDismissCancelled();
+ method public void onDismissError();
+ method public void onDismissSucceeded();
+ }
+
public deprecated class KeyguardManager.KeyguardLock {
method public void disableKeyguard();
method public void reenableKeyguard();
}
- public static abstract interface KeyguardManager.OnKeyguardExitResult {
+ public static abstract deprecated interface KeyguardManager.OnKeyguardExitResult {
method public abstract void onKeyguardExitResult(boolean);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 3ecc8aa..60d98a7 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4971,6 +4971,7 @@
public class KeyguardManager {
method public android.content.Intent createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence);
+ method public void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler);
method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult);
method public boolean inKeyguardRestrictedInputMode();
method public boolean isDeviceLocked();
@@ -4980,12 +4981,19 @@
method public deprecated android.app.KeyguardManager.KeyguardLock newKeyguardLock(java.lang.String);
}
+ public static abstract class KeyguardManager.KeyguardDismissCallback {
+ ctor public KeyguardManager.KeyguardDismissCallback();
+ method public void onDismissCancelled();
+ method public void onDismissError();
+ method public void onDismissSucceeded();
+ }
+
public deprecated class KeyguardManager.KeyguardLock {
method public void disableKeyguard();
method public void reenableKeyguard();
}
- public static abstract interface KeyguardManager.OnKeyguardExitResult {
+ public static abstract deprecated interface KeyguardManager.OnKeyguardExitResult {
method public abstract void onKeyguardExitResult(boolean);
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 13b0c94..be55a94 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -4827,6 +4827,7 @@
public class KeyguardManager {
method public android.content.Intent createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence);
+ method public void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler);
method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult);
method public boolean inKeyguardRestrictedInputMode();
method public boolean isDeviceLocked();
@@ -4836,12 +4837,19 @@
method public deprecated android.app.KeyguardManager.KeyguardLock newKeyguardLock(java.lang.String);
}
+ public static abstract class KeyguardManager.KeyguardDismissCallback {
+ ctor public KeyguardManager.KeyguardDismissCallback();
+ method public void onDismissCancelled();
+ method public void onDismissError();
+ method public void onDismissSucceeded();
+ }
+
public deprecated class KeyguardManager.KeyguardLock {
method public void disableKeyguard();
method public void reenableKeyguard();
}
- public static abstract interface KeyguardManager.OnKeyguardExitResult {
+ public static abstract deprecated interface KeyguardManager.OnKeyguardExitResult {
method public abstract void onKeyguardExitResult(boolean);
}
diff --git a/cmds/wm/src/com/android/commands/wm/Wm.java b/cmds/wm/src/com/android/commands/wm/Wm.java
index 84fb626..8defb33 100644
--- a/cmds/wm/src/com/android/commands/wm/Wm.java
+++ b/cmds/wm/src/com/android/commands/wm/Wm.java
@@ -274,7 +274,7 @@
}
private void runDismissKeyguard() throws Exception {
- mWm.dismissKeyguard();
+ mWm.dismissKeyguard(null /* callback */);
}
private int parseDimension(String s) throws NumberFormatException {
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 82be7ab..1a36d1a 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -31,6 +31,7 @@
import android.app.ITaskStackListener;
import android.app.IUiAutomationConnection;
import android.app.IUidObserver;
+
import android.app.IUserSwitchObserver;
import android.app.Notification;
import android.app.PendingIntent;
@@ -65,6 +66,7 @@
import android.service.voice.IVoiceInteractionSession;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.os.IResultReceiver;
+import com.android.internal.policy.IKeyguardDismissCallback;
import java.util.List;
@@ -571,6 +573,7 @@
void setPictureInPictureAspectRatio(in IBinder token, float aspectRatio);
boolean requestAutoFillData(in IResultReceiver receiver, in Bundle receiverExtras,
in IBinder activityToken);
+ void dismissKeyguard(in IBinder token, in IKeyguardDismissCallback callback);
// WARNING: when these transactions are updated, check if they are any callers on the native
// side. If so, make sure they are using the correct transaction ids.
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 725cc29..036b47c 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -17,24 +17,32 @@
package android.app;
import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.app.trust.ITrustManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
import android.os.Binder;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
import android.os.RemoteException;
import android.os.IBinder;
import android.os.IUserManager;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.UserHandle;
-import android.os.UserManager;
+import android.util.Log;
import android.view.IWindowManager;
import android.view.IOnKeyguardExitResult;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerGlobal;
+import com.android.internal.policy.IKeyguardDismissCallback;
+
/**
* Class that can be used to lock and unlock the keyboard. Get an instance of this
* class by calling {@link android.content.Context#getSystemService(java.lang.String)}
@@ -43,10 +51,13 @@
* {@link android.app.KeyguardManager.KeyguardLock}.
*/
public class KeyguardManager {
- private IWindowManager mWM;
- private ITrustManager mTrustManager;
- private IUserManager mUserManager;
- private Context mContext;
+
+ private static final String TAG = "KeyguardManager";
+
+ private final Context mContext;
+ private final IWindowManager mWM;
+ private final IActivityManager mAm;
+ private final ITrustManager mTrustManager;
/**
* Intent used to prompt user for device credentials.
@@ -125,8 +136,8 @@
}
/**
- * @deprecated Use {@link android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUARD}
- * and/or {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED}
+ * @deprecated Use {@link LayoutParams#FLAG_DISMISS_KEYGUARD}
+ * and/or {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED}
* instead; this allows you to seamlessly hide the keyguard as your application
* moves in and out of the foreground and does not require that any special
* permissions be requested.
@@ -190,9 +201,11 @@
}
/**
+ * @deprecated Use {@link KeyguardDismissCallback}
* Callback passed to {@link KeyguardManager#exitKeyguardSecurely} to notify
* caller of result.
*/
+ @Deprecated
public interface OnKeyguardExitResult {
/**
@@ -202,19 +215,41 @@
void onKeyguardExitResult(boolean success);
}
+ /**
+ * Callback passed to {@link KeyguardManager#dismissKeyguard} to notify caller of result.
+ */
+ public static abstract class KeyguardDismissCallback {
+
+ /**
+ * Called when dismissing Keyguard is currently not feasible, i.e. when Keyguard is not
+ * available, not showing or when the activity requesting the Keyguard dismissal isn't
+ * showing or isn't showing behind Keyguard.
+ */
+ public void onDismissError() { }
+
+ /**
+ * Called when dismissing Keyguard has succeeded and the device is now unlocked.
+ */
+ public void onDismissSucceeded() { }
+
+ /**
+ * Called when dismissing Keyguard has been cancelled, i.e. when the user cancelled the
+ * operation or the bouncer was hidden for some other reason.
+ */
+ public void onDismissCancelled() { }
+ }
KeyguardManager(Context context) throws ServiceNotFoundException {
mContext = context;
mWM = WindowManagerGlobal.getWindowManagerService();
+ mAm = ActivityManager.getService();
mTrustManager = ITrustManager.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.TRUST_SERVICE));
- mUserManager = IUserManager.Stub.asInterface(
- ServiceManager.getServiceOrThrow(Context.USER_SERVICE));
}
/**
- * @deprecated Use {@link android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUARD}
- * and/or {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED}
+ * @deprecated Use {@link LayoutParams#FLAG_DISMISS_KEYGUARD}
+ * and/or {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED}
* instead; this allows you to seamlessly hide the keyguard as your application
* moves in and out of the foreground and does not require that any special
* permissions be requested.
@@ -296,9 +331,8 @@
* @hide
*/
public boolean isDeviceLocked(int userId) {
- ITrustManager trustManager = getTrustManager();
try {
- return trustManager.isDeviceLocked(userId);
+ return mTrustManager.isDeviceLocked(userId);
} catch (RemoteException e) {
return false;
}
@@ -322,25 +356,63 @@
* @hide
*/
public boolean isDeviceSecure(int userId) {
- ITrustManager trustManager = getTrustManager();
try {
- return trustManager.isDeviceSecure(userId);
+ return mTrustManager.isDeviceSecure(userId);
} catch (RemoteException e) {
return false;
}
}
- private synchronized ITrustManager getTrustManager() {
- if (mTrustManager == null) {
- mTrustManager = ITrustManager.Stub.asInterface(
- ServiceManager.getService(Context.TRUST_SERVICE));
+ /**
+ * If the device is currently locked (see {@link #isKeyguardLocked()}, requests the Keyguard to
+ * be dismissed.
+ * <p>
+ * If the Keyguard is not secure or the device is currently in a trusted state, calling this
+ * method will immediately dismiss the Keyguard without any user interaction.
+ * <p>
+ * If the Keyguard is secure and the device is not in a trusted state, this will bring up the
+ * UI so the user can enter their credentials.
+ *
+ * @param activity The activity requesting the dismissal. The activity must be either visible
+ * by using {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} or must be in a state in
+ * which it would be visible if Keyguard would not be hiding it. If that's not
+ * the case, the request will fail immediately and
+ * {@link KeyguardDismissCallback#onDismissError} will be invoked.
+ * @param callback The callback to be called if the request to dismiss Keyguard was successful
+ * or {@code null} if the caller isn't interested in knowing the result.
+ * @param handler The handler to invoke the callback on, or {@code null} to use the main
+ * handler.
+ */
+ public void dismissKeyguard(@NonNull Activity activity,
+ @Nullable KeyguardDismissCallback callback, @Nullable Handler handler) {
+ try {
+ final Handler actualHandler = handler != null
+ ? handler
+ : new Handler(Looper.getMainLooper());
+ mAm.dismissKeyguard(activity.getActivityToken(), new IKeyguardDismissCallback.Stub() {
+ @Override
+ public void onDismissError() throws RemoteException {
+ actualHandler.post(callback::onDismissError);
+ }
+
+ @Override
+ public void onDismissSucceeded() throws RemoteException {
+ actualHandler.post(callback::onDismissSucceeded);
+ }
+
+ @Override
+ public void onDismissCancelled() throws RemoteException {
+ actualHandler.post(callback::onDismissCancelled);
+ }
+ });
+ } catch (RemoteException e) {
+ Log.i(TAG, "Failed to dismiss keyguard: " + e);
}
- return mTrustManager;
}
/**
- * @deprecated Use {@link android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUARD}
- * and/or {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED}
+ * @deprecated Use {@link LayoutParams#FLAG_DISMISS_KEYGUARD}
+ * and/or {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED}
* instead; this allows you to seamlessly hide the keyguard as your application
* moves in and out of the foreground and does not require that any special
* permissions be requested.
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index bccb822..bd1ad8e 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -20,6 +20,7 @@
import com.android.internal.os.IResultReceiver;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
+import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
import android.content.res.CompatibilityInfo;
@@ -210,8 +211,7 @@
boolean isKeyguardLocked();
boolean isKeyguardSecure();
boolean inKeyguardRestrictedInputMode();
- void dismissKeyguard();
- void keyguardGoingAway(int flags);
+ void dismissKeyguard(IKeyguardDismissCallback callback);
// Requires INTERACT_ACROSS_USERS_FULL permission
void setSwitchingUser(boolean switching);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 2971280..b8408dd 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.app.KeyguardManager;
import android.app.Presentation;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -911,16 +912,17 @@
public static final int FLAG_TURN_SCREEN_ON = 0x00200000;
/** Window flag: when set the window will cause the keyguard to
- * be dismissed, only if it is not a secure lock keyguard. Because such
+ * be dismissed, only if it is not a secure lock keyguard. Because such
* a keyguard is not needed for security, it will never re-appear if
* the user navigates to another window (in contrast to
* {@link #FLAG_SHOW_WHEN_LOCKED}, which will only temporarily
* hide both secure and non-secure keyguards but ensure they reappear
* when the user moves to another UI that doesn't hide them).
* If the keyguard is currently active and is secure (requires an
- * unlock pattern) than the user will still need to confirm it before
+ * unlock credential) than the user will still need to confirm it before
* seeing this window, unless {@link #FLAG_SHOW_WHEN_LOCKED} has
* also been set.
+ * @see KeyguardManager#dismissKeyguard
*/
public static final int FLAG_DISMISS_KEYGUARD = 0x00400000;
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 82379c4..3171019 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -17,6 +17,7 @@
package android.view;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.ActivityManager.StackId;
import android.content.Context;
@@ -31,6 +32,7 @@
import android.os.RemoteException;
import android.view.animation.Animation;
+import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
import java.io.PrintWriter;
@@ -1162,8 +1164,10 @@
/**
* Ask the policy to dismiss the keyguard, if it is currently shown.
+ *
+ * @param callback Callback to be informed about the result.
*/
- public void dismissKeyguardLw();
+ public void dismissKeyguardLw(@Nullable IKeyguardDismissCallback callback);
/**
* Ask the policy whether the Keyguard has drawn. If the Keyguard is disabled, this method
diff --git a/core/java/com/android/internal/policy/IKeyguardDismissCallback.aidl b/core/java/com/android/internal/policy/IKeyguardDismissCallback.aidl
new file mode 100644
index 0000000..635c504
--- /dev/null
+++ b/core/java/com/android/internal/policy/IKeyguardDismissCallback.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2016 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 IKeyguardDismissCallback {
+ void onDismissError();
+ void onDismissSucceeded();
+ void onDismissCancelled();
+}
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl
index 788103d..a019ea1 100644
--- a/core/java/com/android/internal/policy/IKeyguardService.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardService.aidl
@@ -16,6 +16,7 @@
package com.android.internal.policy;
import com.android.internal.policy.IKeyguardDrawnCallback;
+import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IKeyguardStateCallback;
import com.android.internal.policy.IKeyguardExitCallback;
@@ -34,7 +35,7 @@
void addStateMonitorCallback(IKeyguardStateCallback callback);
void verifyUnlock(IKeyguardExitCallback callback);
- void dismiss(boolean allowWhileOccluded);
+ void dismiss(IKeyguardDismissCallback callback);
void onDreamingStarted();
void onDreamingStopped();
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 21f68f5..e036128 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -26,6 +26,7 @@
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.R;
import com.android.systemui.assist.AssistManager;
+import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
@@ -89,9 +90,10 @@
}
public KeyguardBouncer createKeyguardBouncer(Context context, ViewMediatorCallback callback,
- LockPatternUtils lockPatternUtils, StatusBarWindowManager windowManager,
- ViewGroup container) {
- return new KeyguardBouncer(context, callback, lockPatternUtils, windowManager, container);
+ LockPatternUtils lockPatternUtils,
+ ViewGroup container, DismissCallbackRegistry dismissCallbackRegistry) {
+ return new KeyguardBouncer(context, callback, lockPatternUtils, container,
+ dismissCallbackRegistry);
}
public ScrimController createScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
new file mode 100644
index 0000000..262d29d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2016 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.systemui.keyguard;
+
+import com.android.internal.policy.IKeyguardDismissCallback;
+
+import java.util.ArrayList;
+
+/**
+ * Registry holding the current set of {@link IKeyguardDismissCallback}s.
+ */
+public class DismissCallbackRegistry {
+
+ private final ArrayList<DismissCallbackWrapper> mDismissCallbacks = new ArrayList<>();
+
+ public void addCallback(IKeyguardDismissCallback callback) {
+ mDismissCallbacks.add(new DismissCallbackWrapper(callback));
+ }
+
+ public void notifyDismissCancelled() {
+ for (int i = mDismissCallbacks.size() - 1; i >= 0; i--) {
+ mDismissCallbacks.get(i).notifyDismissCancelled();
+ }
+ mDismissCallbacks.clear();
+ }
+
+ public void notifyDismissSucceeded() {
+ for (int i = mDismissCallbacks.size() - 1; i >= 0; i--) {
+ mDismissCallbacks.get(i).notifyDismissSucceeded();
+ }
+ mDismissCallbacks.clear();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackWrapper.java b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackWrapper.java
new file mode 100644
index 0000000..8a91144
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackWrapper.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 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.systemui.keyguard;
+
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.policy.IKeyguardDismissCallback;
+
+/**
+ * A light wrapper around {@link IKeyguardDismissCallback} handling {@link RemoteException}s.
+ */
+public class DismissCallbackWrapper {
+
+ private static final String TAG = "DismissCallbackWrapper";
+
+ private IKeyguardDismissCallback mCallback;
+
+ public DismissCallbackWrapper(IKeyguardDismissCallback callback) {
+ mCallback = callback;
+ }
+
+ public void notifyDismissError() {
+ try {
+ mCallback.onDismissError();
+ } catch (RemoteException e) {
+ Log.i(TAG, "Failed to call callback", e);
+ }
+ }
+
+ public void notifyDismissCancelled() {
+ try {
+ mCallback.onDismissCancelled();
+ } catch (RemoteException e) {
+ Log.i(TAG, "Failed to call callback", e);
+ }
+ }
+
+ public void notifyDismissSucceeded() {
+ try {
+ mCallback.onDismissSucceeded();
+ } catch (RemoteException e) {
+ Log.i(TAG, "Failed to call callback", e);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index fe9f55f..3532f41 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -26,6 +26,7 @@
import android.os.Trace;
import android.util.Log;
+import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IKeyguardDrawnCallback;
import com.android.internal.policy.IKeyguardExitCallback;
import com.android.internal.policy.IKeyguardService;
@@ -89,9 +90,9 @@
}
@Override // Binder interface
- public void dismiss(boolean allowWhileOccluded) {
+ public void dismiss(IKeyguardDismissCallback callback) {
checkPermission();
- mKeyguardViewMediator.dismiss(allowWhileOccluded);
+ mKeyguardViewMediator.dismiss(callback);
}
@Override // Binder interface
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 34dc63f..9bbdfda 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -25,7 +25,6 @@
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.PendingIntent;
-import android.app.SearchManager;
import android.app.StatusBarManager;
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
@@ -48,20 +47,18 @@
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
-import android.os.storage.StorageManager;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
-import android.view.IWindowManager;
import android.view.ViewGroup;
-import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicy;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
+import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IKeyguardDrawnCallback;
import com.android.internal.policy.IKeyguardExitCallback;
import com.android.internal.policy.IKeyguardStateCallback;
@@ -252,6 +249,7 @@
* var being non-null as an indicator that there is an in progress request.
*/
private IKeyguardExitCallback mExitSecureCallback;
+ private final DismissCallbackRegistry mDismissCallbackRegistry = new DismissCallbackRegistry();
// the properties of the keyguard
@@ -347,7 +345,7 @@
UserInfo info = UserManager.get(mContext).getUserInfo(userId);
if (info != null && (info.isGuest() || info.isDemo())) {
// If we just switched to a guest, try to dismiss keyguard.
- dismiss(false /* allowWhileOccluded */);
+ dismiss(null /* callback */);
}
}
}
@@ -515,7 +513,7 @@
return;
}
- tryKeyguardDone(true);
+ tryKeyguardDone();
if (strongAuth) {
mUpdateMonitor.reportSuccessfulStrongAuthUnlockAttempt();
}
@@ -565,10 +563,7 @@
Trace.beginSection("KeyguardViewMediator.mViewMediatorCallback#readyForKeyguardDone");
if (mKeyguardDonePending) {
mKeyguardDonePending = false;
-
- // Somebody has called keyguardDonePending before, which means that we are
- // authenticated
- tryKeyguardDone(true);
+ tryKeyguardDone();
}
Trace.endSection();
}
@@ -1252,16 +1247,21 @@
/**
* Dismiss the keyguard through the security layers.
- * @param allowWhileOccluded if true, dismiss the keyguard even if it's currently occluded.
+ * @param callback Callback to be informed about the result
*/
- public void handleDismiss(boolean allowWhileOccluded) {
- if (mShowing && (allowWhileOccluded || !mOccluded)) {
+ private void handleDismiss(IKeyguardDismissCallback callback) {
+ if (mShowing) {
+ if (callback != null) {
+ mDismissCallbackRegistry.addCallback(callback);
+ }
mStatusBarKeyguardViewManager.dismissAndCollapse();
+ } else if (callback != null) {
+ new DismissCallbackWrapper(callback).notifyDismissError();
}
}
- public void dismiss(boolean allowWhileOccluded) {
- mHandler.obtainMessage(DISMISS, allowWhileOccluded ? 1 : 0, 0).sendToTarget();
+ public void dismiss(IKeyguardDismissCallback callback) {
+ mHandler.obtainMessage(DISMISS, callback).sendToTarget();
}
/**
@@ -1394,12 +1394,12 @@
}
};
- public void keyguardDone(boolean authenticated) {
+ public void keyguardDone() {
Trace.beginSection("KeyguardViewMediator#keyguardDone");
- if (DEBUG) Log.d(TAG, "keyguardDone(" + authenticated +")");
+ if (DEBUG) Log.d(TAG, "keyguardDone()");
userActivity();
EventLog.writeEvent(70000, 2);
- Message msg = mHandler.obtainMessage(KEYGUARD_DONE, authenticated ? 1 : 0);
+ Message msg = mHandler.obtainMessage(KEYGUARD_DONE);
mHandler.sendMessage(msg);
Trace.endSection();
}
@@ -1455,7 +1455,7 @@
break;
case KEYGUARD_DONE:
Trace.beginSection("KeyguardViewMediator#handleMessage KEYGUARD_DONE");
- handleKeyguardDone(msg.arg1 != 0);
+ handleKeyguardDone();
Trace.endSection();
break;
case KEYGUARD_DONE_DRAWING:
@@ -1474,7 +1474,7 @@
}
break;
case DISMISS:
- handleDismiss(msg.arg1 == 1 ? true : false /* allowWhileOccluded */);
+ handleDismiss((IKeyguardDismissCallback) msg.obj);
break;
case START_KEYGUARD_EXIT_ANIM:
Trace.beginSection("KeyguardViewMediator#handleMessage START_KEYGUARD_EXIT_ANIM");
@@ -1492,9 +1492,9 @@
}
};
- private void tryKeyguardDone(boolean authenticated) {
+ private void tryKeyguardDone() {
if (!mKeyguardDonePending && mHideAnimationRun && !mHideAnimationRunning) {
- handleKeyguardDone(authenticated);
+ handleKeyguardDone();
} else if (!mHideAnimationRun) {
mHideAnimationRun = true;
mHideAnimationRunning = true;
@@ -1506,7 +1506,7 @@
* @see #keyguardDone
* @see #KEYGUARD_DONE
*/
- private void handleKeyguardDone(boolean authenticated) {
+ private void handleKeyguardDone() {
Trace.beginSection("KeyguardViewMediator#handleKeyguardDone");
final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
if (mLockPatternUtils.isSecure(currentUser)) {
@@ -1517,9 +1517,7 @@
resetKeyguardDonePendingLocked();
}
- if (authenticated) {
- mUpdateMonitor.clearFailedUnlockAttempts();
- }
+ mUpdateMonitor.clearFailedUnlockAttempts();
mUpdateMonitor.clearFingerprintRecognized();
if (mGoingToSleep) {
@@ -1528,22 +1526,21 @@
}
if (mExitSecureCallback != null) {
try {
- mExitSecureCallback.onKeyguardExitResult(authenticated);
+ mExitSecureCallback.onKeyguardExitResult(true /* authenciated */);
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onKeyguardExitResult(" + authenticated + ")", e);
+ Slog.w(TAG, "Failed to call onKeyguardExitResult()", e);
}
mExitSecureCallback = null;
- if (authenticated) {
- // after succesfully exiting securely, no need to reshow
- // the keyguard when they've released the lock
- mExternallyEnabled = true;
- mNeedToReshowWhenReenabled = false;
- updateInputRestricted();
- }
+ // after succesfully exiting securely, no need to reshow
+ // the keyguard when they've released the lock
+ mExternallyEnabled = true;
+ mNeedToReshowWhenReenabled = false;
+ updateInputRestricted();
}
+ mDismissCallbackRegistry.notifyDismissSucceeded();
handleHide();
Trace.endSection();
}
@@ -1690,7 +1687,7 @@
private final Runnable mHideAnimationFinishedRunnable = () -> {
mHideAnimationRunning = false;
- tryKeyguardDone(true);
+ tryKeyguardDone();
};
/**
@@ -1912,7 +1909,7 @@
public void onWakeAndUnlocking() {
Trace.beginSection("KeyguardViewMediator#onWakeAndUnlocking");
mWakeAndUnlocking = true;
- keyguardDone(true /* authenticated */);
+ keyguardDone();
Trace.endSection();
}
@@ -1921,7 +1918,8 @@
ScrimController scrimController,
FingerprintUnlockController fingerprintUnlockController) {
mStatusBarKeyguardViewManager.registerStatusBar(phoneStatusBar, container,
- statusBarWindowManager, scrimController, fingerprintUnlockController);
+ statusBarWindowManager, scrimController, fingerprintUnlockController,
+ mDismissCallbackRegistry);
return mStatusBarKeyguardViewManager;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 34b8371..2124011 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -37,6 +37,7 @@
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.DejankUtils;
import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.keyguard.DismissCallbackRegistry;
import static com.android.keyguard.KeyguardHostView.OnDismissAction;
import static com.android.keyguard.KeyguardSecurityModel.SecurityMode;
@@ -48,17 +49,17 @@
final static private String TAG = "KeyguardBouncer";
- protected Context mContext;
- protected ViewMediatorCallback mCallback;
- protected LockPatternUtils mLockPatternUtils;
- protected ViewGroup mContainer;
- private StatusBarWindowManager mWindowManager;
+ protected final Context mContext;
+ protected final ViewMediatorCallback mCallback;
+ protected final LockPatternUtils mLockPatternUtils;
+ protected final ViewGroup mContainer;
+ private final FalsingManager mFalsingManager;
+ private final DismissCallbackRegistry mDismissCallbackRegistry;
protected KeyguardHostView mKeyguardView;
protected ViewGroup mRoot;
private boolean mShowingSoon;
private int mBouncerPromptReason;
- private FalsingManager mFalsingManager;
- private KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
+ private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@Override
public void onStrongAuthStateChanged(int userId) {
@@ -67,15 +68,15 @@
};
public KeyguardBouncer(Context context, ViewMediatorCallback callback,
- LockPatternUtils lockPatternUtils, StatusBarWindowManager windowManager,
- ViewGroup container) {
+ LockPatternUtils lockPatternUtils, ViewGroup container,
+ DismissCallbackRegistry dismissCallbackRegistry) {
mContext = context;
mCallback = callback;
mLockPatternUtils = lockPatternUtils;
mContainer = container;
- mWindowManager = windowManager;
KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
mFalsingManager = FalsingManager.getInstance(mContext);
+ mDismissCallbackRegistry = dismissCallbackRegistry;
}
public void show(boolean resetSecuritySelection) {
@@ -169,6 +170,9 @@
}
public void hide(boolean destroyView) {
+ if (isShowing()) {
+ mDismissCallbackRegistry.notifyDismissCancelled();
+ }
mFalsingManager.onBouncerHidden();
cancelShowRunnable();
if (mKeyguardView != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 69decd7..a82ffb7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -33,6 +33,7 @@
import com.android.systemui.DejankUtils;
import com.android.keyguard.LatencyTracker;
import com.android.systemui.SystemUIFactory;
+import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.RemoteInputController;
@@ -102,14 +103,15 @@
public void registerStatusBar(PhoneStatusBar phoneStatusBar,
ViewGroup container, StatusBarWindowManager statusBarWindowManager,
ScrimController scrimController,
- FingerprintUnlockController fingerprintUnlockController) {
+ FingerprintUnlockController fingerprintUnlockController,
+ DismissCallbackRegistry dismissCallbackRegistry) {
mPhoneStatusBar = phoneStatusBar;
mContainer = container;
mStatusBarWindowManager = statusBarWindowManager;
mScrimController = scrimController;
mFingerprintUnlockController = fingerprintUnlockController;
mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
- mViewMediatorCallback, mLockPatternUtils, mStatusBarWindowManager, container);
+ mViewMediatorCallback, mLockPatternUtils, container, dismissCallbackRegistry);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index fafbdd1..0396613 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -92,20 +92,6 @@
return mCanSkipBouncer;
}
- public void unlock() {
- try {
- WindowManagerGlobal.getWindowManagerService().dismissKeyguard();
- } catch (RemoteException e) {
- }
- }
-
- public void lock() {
- try {
- WindowManagerGlobal.getWindowManagerService().lockNow(null /* options */);
- } catch (RemoteException e) {
- }
- }
-
public void notifyKeyguardState(boolean showing, boolean secure, boolean occluded) {
if (mShowing == showing && mSecure == secure && mOccluded == occluded) return;
mShowing = showing;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java
new file mode 100644
index 0000000..131a70b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2016 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.systemui.keyguard;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.policy.IKeyguardDismissCallback;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * runtest systemui -c com.android.systemui.keyguard.DismissCallbackRegistryTest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DismissCallbackRegistryTest {
+
+ private final DismissCallbackRegistry mDismissCallbackRegistry = new DismissCallbackRegistry();
+ private @Mock IKeyguardDismissCallback mMockCallback;
+ private @Mock IKeyguardDismissCallback mMockCallback2;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void testCancelled() throws Exception {
+ mDismissCallbackRegistry.addCallback(mMockCallback);
+ mDismissCallbackRegistry.notifyDismissCancelled();
+ verify(mMockCallback).onDismissCancelled();
+ }
+
+ @Test
+ public void testCancelled_multiple() throws Exception {
+ mDismissCallbackRegistry.addCallback(mMockCallback);
+ mDismissCallbackRegistry.addCallback(mMockCallback2);
+ mDismissCallbackRegistry.notifyDismissCancelled();
+ verify(mMockCallback).onDismissCancelled();
+ verify(mMockCallback2).onDismissCancelled();
+ }
+
+ @Test
+ public void testSucceeded() throws Exception {
+ mDismissCallbackRegistry.addCallback(mMockCallback);
+ mDismissCallbackRegistry.notifyDismissSucceeded();
+ verify(mMockCallback).onDismissSucceeded();
+ }
+
+ @Test
+ public void testSucceeded_multiple() throws Exception {
+ mDismissCallbackRegistry.addCallback(mMockCallback);
+ mDismissCallbackRegistry.addCallback(mMockCallback2);
+ mDismissCallbackRegistry.notifyDismissSucceeded();
+ verify(mMockCallback).onDismissSucceeded();
+ verify(mMockCallback2).onDismissSucceeded();
+ }
+
+ @Test
+ public void testOnlyOnce() throws Exception {
+ mDismissCallbackRegistry.addCallback(mMockCallback);
+ mDismissCallbackRegistry.notifyDismissSucceeded();
+ mDismissCallbackRegistry.notifyDismissSucceeded();
+ verify(mMockCallback, times(1)).onDismissSucceeded();
+ }
+}
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
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 4596210..a0ded87 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -20,6 +20,7 @@
import android.graphics.Rect;
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.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
@@ -516,11 +517,7 @@
}
@Override
- public void dismissKeyguard() {
- }
-
- @Override
- public void keyguardGoingAway(int flags) throws RemoteException {
+ public void dismissKeyguard(IKeyguardDismissCallback callback) throws RemoteException {
}
@Override