diff options
author | Jorim Jaggi <jjaggi@google.com> | 2016-11-02 21:57:33 -0700 |
---|---|---|
committer | Jorim Jaggi <jjaggi@google.com> | 2016-11-23 16:27:35 +0100 |
commit | 241ae10b2189f449e57d8d660235ac56d8fb1b80 (patch) | |
tree | a6048e4406bff9ffc789c5a9af53a0eeea0718a6 | |
parent | d4f9d37424752a0774cdf9190dc12887c70daec2 (diff) |
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
32 files changed, 504 insertions, 136 deletions
diff --git a/Android.mk b/Android.mk index 552103d4d1a5..78c9c1db466c 100644 --- a/Android.mk +++ b/Android.mk @@ -338,6 +338,7 @@ LOCAL_SRC_FILES += \ 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 8a00273ba893..40b57a34ddea 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4817,6 +4817,7 @@ package android.app { 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 @@ package android.app { 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 3ecc8aa575c9..60d98a7265eb 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4971,6 +4971,7 @@ package android.app { 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 @@ package android.app { 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 13b0c941fb17..be55a949a5b7 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -4827,6 +4827,7 @@ package android.app { 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 @@ package android.app { 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 84fb626cc4c6..8defb331e289 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 @@ public class Wm extends BaseCommand { } 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 82be7abeb87d..1a36d1aa8449 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -31,6 +31,7 @@ import android.app.IStopUserCallback; 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.os.StrictMode; 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 @@ interface IActivityManager { 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 725cc29bd323..036b47cafe64 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 @@ import android.view.WindowManagerGlobal; * {@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 @@ public class KeyguardManager { } /** - * @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 @@ public class KeyguardManager { } /** + * @deprecated Use {@link KeyguardDismissCallback} * Callback passed to {@link KeyguardManager#exitKeyguardSecurely} to notify * caller of result. */ + @Deprecated public interface OnKeyguardExitResult { /** @@ -202,19 +215,41 @@ public class KeyguardManager { 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 @@ public class KeyguardManager { * @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 @@ public class KeyguardManager { * @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 bccb822a6519..bd1ad8e01b3c 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -20,6 +20,7 @@ import com.android.internal.app.IAssistScreenshotReceiver; 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 @@ interface IWindowManager 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 2971280f65d9..b8408dd7434b 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -18,6 +18,7 @@ package android.view; 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 interface WindowManager extends ViewManager { 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 82379c47a679..3171019e1a0e 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.Looper; 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 @@ public interface WindowManagerPolicy { /** * 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 000000000000..635c504fe51c --- /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 788103d2cc02..a019ea170484 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 @@ oneway interface IKeyguardService { 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 21f68f558c74..e03612802f9c 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.internal.widget.LockPatternUtils; 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 class SystemUIFactory { } 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 000000000000..262d29d1acd1 --- /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 000000000000..8a91144ccf33 --- /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 fe9f55f9a1ee..3532f41ae676 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.Process; 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 @@ public class KeyguardService extends Service { } @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 34dc63f12427..9bbdfda1d3cb 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.Activity; 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.SystemProperties; 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 @@ public class KeyguardViewMediator extends SystemUI { * 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 @@ public class KeyguardViewMediator extends SystemUI { 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 @@ public class KeyguardViewMediator extends SystemUI { return; } - tryKeyguardDone(true); + tryKeyguardDone(); if (strongAuth) { mUpdateMonitor.reportSuccessfulStrongAuthUnlockAttempt(); } @@ -565,10 +563,7 @@ public class KeyguardViewMediator extends SystemUI { 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 @@ public class KeyguardViewMediator extends SystemUI { /** * 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 class KeyguardViewMediator extends SystemUI { } }; - 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 @@ public class KeyguardViewMediator extends SystemUI { 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 @@ public class KeyguardViewMediator extends SystemUI { } 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 @@ public class KeyguardViewMediator extends SystemUI { } }; - 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 @@ public class KeyguardViewMediator extends SystemUI { * @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 @@ public class KeyguardViewMediator extends SystemUI { resetKeyguardDonePendingLocked(); } - if (authenticated) { - mUpdateMonitor.clearFailedUnlockAttempts(); - } + mUpdateMonitor.clearFailedUnlockAttempts(); mUpdateMonitor.clearFingerprintRecognized(); if (mGoingToSleep) { @@ -1528,22 +1526,21 @@ public class KeyguardViewMediator extends SystemUI { } 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 @@ public class KeyguardViewMediator extends SystemUI { private final Runnable mHideAnimationFinishedRunnable = () -> { mHideAnimationRunning = false; - tryKeyguardDone(true); + tryKeyguardDone(); }; /** @@ -1912,7 +1909,7 @@ public class KeyguardViewMediator extends SystemUI { public void onWakeAndUnlocking() { Trace.beginSection("KeyguardViewMediator#onWakeAndUnlocking"); mWakeAndUnlocking = true; - keyguardDone(true /* authenticated */); + keyguardDone(); Trace.endSection(); } @@ -1921,7 +1918,8 @@ public class KeyguardViewMediator extends SystemUI { 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 34b8371fe20a..21240118e5c6 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.R; 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 @@ public class KeyguardBouncer { 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 class KeyguardBouncer { }; 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 class KeyguardBouncer { } 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 69decd72c03a..a82ffb75c1a3 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.keyguard.ViewMediatorCallback; 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 class StatusBarKeyguardViewManager implements RemoteInputController.Callb 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 fafbdd101e5e..039661349910 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 @@ public class KeyguardMonitor extends KeyguardUpdateMonitorCallback 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 000000000000..131a70b2c109 --- /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 8bd75067bb94..1beffc4433e0 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.IActivityManager; 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 90b46edbe3c7..214a35799860 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 @@ final class ActivityRecord { 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 @@ final class ActivityRecord { 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 473b1a34a892..005b8aa16bd1 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 @@ final class ActivityStack extends ConfigurationContainer { 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 5d8d79fd52c2..b53a680c7f7a 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 @@ public class ActivityStackSupervisor extends ConfigurationContainer 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 9d8c3835b33f..5e02597f1991 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.app.ActivityManager.StackId.DOCKED_STACK_ID; 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_OCCLUDE; 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 @@ import java.util.ArrayList; */ 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 @@ class KeyguardController { 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 @@ class KeyguardController { } } + 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 @@ class KeyguardController { */ 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 ccdda1328a8d..f48db05adbd0 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 android.view.animation.AnimationUtils; 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 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @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 f37f98786fed..1b4eaf548809 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.Log; 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 @@ public class KeyguardServiceDelegate { 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 c4a0dd364d76..0b839b84e677 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.IBinder; 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 @@ public class KeyguardServiceWrapper implements IKeyguardService { } @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 00d8fba09a58..50b0f38897cb 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 android.view.inputmethod.InputMethodManagerInternal; 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 @@ public class WindowManagerService extends IWindowManager.Stub } @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 ed4c79f91ba2..1853a653ed1a 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 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { } @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 4596210b82d5..a0ded8745508 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.Point; 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 @@ public class IWindowManagerImpl implements IWindowManager { } @Override - public void dismissKeyguard() { - } - - @Override - public void keyguardGoingAway(int flags) throws RemoteException { + public void dismissKeyguard(IKeyguardDismissCallback callback) throws RemoteException { } @Override |