summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Roos <roosa@google.com>2018-11-20 20:07:55 +0100
committerAdrian Roos <roosa@google.com>2018-11-29 18:24:09 +0000
commit1c8e3c0bd314b29cca8b92655c87d847da266683 (patch)
treebf3bb6955ddb42f7652313d180d20afb060e7280
parent509d06a6415b9f6a628d3ebac9f7047de8f7d34c (diff)
KeyguardDisableHandler: make properly user aware
Also fixes an issue where the disable handler was not properly updated after adding a secure lockscreen. Also fixes an issue where the disable handler was not properly updated after the device policy changes for users other than USER_SYSTEM. Also prevents adding new privileged usages of the API. Also removes a workaround that prevented Keyguard from re-engaging if it timed out while the it was disabled. The workaround is no longer necessary because the in-call UI is now using the SHOW_WHEN_LOCKED API instead of disabling the keyguard. Change-Id: Ib2644252b3806de4cb09f03991d789b83e924a11 Fixes: 119322269 Test: atest KeyguardDisableHandlerTest CtsActivityManagerDeviceTestCases:KeyguardTests
-rw-r--r--core/java/android/app/KeyguardManager.java40
-rw-r--r--core/java/android/view/IWindowManager.aidl6
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java28
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java2
-rw-r--r--services/core/java/com/android/server/utils/UserTokenWatcher.java166
-rw-r--r--services/core/java/com/android/server/wm/KeyguardDisableHandler.java189
-rw-r--r--services/core/java/com/android/server/wm/LockTaskController.java38
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerInternal.java5
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java66
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/KeyguardDisableHandlerTest.java225
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java11
-rw-r--r--tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java5
12 files changed, 603 insertions, 178 deletions
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index f8309bcd3267..1ae0f52ac74e 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -270,14 +270,14 @@ public class KeyguardManager {
}
/**
+ * Handle returned by {@link KeyguardManager#newKeyguardLock} that allows
+ * you to disable / reenable the keyguard.
+ *
* @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.
- *
- * Handle returned by {@link KeyguardManager#newKeyguardLock} that allows
- * you to disable / reenable the keyguard.
*/
@Deprecated
public class KeyguardLock {
@@ -303,7 +303,7 @@ public class KeyguardManager {
@RequiresPermission(Manifest.permission.DISABLE_KEYGUARD)
public void disableKeyguard() {
try {
- mWM.disableKeyguard(mToken, mTag);
+ mWM.disableKeyguard(mToken, mTag, mContext.getUserId());
} catch (RemoteException ex) {
}
}
@@ -322,16 +322,17 @@ public class KeyguardManager {
@RequiresPermission(Manifest.permission.DISABLE_KEYGUARD)
public void reenableKeyguard() {
try {
- mWM.reenableKeyguard(mToken);
+ mWM.reenableKeyguard(mToken, mContext.getUserId());
} catch (RemoteException ex) {
}
}
}
/**
- * @deprecated Use {@link KeyguardDismissCallback}
* Callback passed to {@link KeyguardManager#exitKeyguardSecurely} to notify
* caller of result.
+ *
+ * @deprecated Use {@link KeyguardDismissCallback}
*/
@Deprecated
public interface OnKeyguardExitResult {
@@ -380,12 +381,6 @@ public class KeyguardManager {
}
/**
- * @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.
- *
* Enables you to lock or unlock the keyguard. Get an instance of this class by
* calling {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
* This class is wrapped by {@link android.app.KeyguardManager KeyguardManager}.
@@ -394,6 +389,12 @@ public class KeyguardManager {
*
* @return A {@link KeyguardLock} handle to use to disable and reenable the
* keyguard.
+ *
+ * @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.
*/
@Deprecated
public KeyguardLock newKeyguardLock(String tag) {
@@ -430,13 +431,12 @@ public class KeyguardManager {
}
/**
- * @deprecated Use {@link #isKeyguardLocked()} instead.
- *
* If keyguard screen is showing or in restricted key input mode (i.e. in
* keyguard password emergency screen). When in such mode, certain keys,
* such as the Home key and the right soft keys, don't work.
*
* @return true if in keyguard restricted input mode.
+ * @deprecated Use {@link #isKeyguardLocked()} instead.
*/
public boolean inKeyguardRestrictedInputMode() {
return isKeyguardLocked();
@@ -588,12 +588,6 @@ public class KeyguardManager {
}
/**
- * @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.
- *
* Exit the keyguard securely. The use case for this api is that, after
* disabling the keyguard, your app, which was granted permission to
* disable the keyguard and show a limited amount of information deemed
@@ -606,6 +600,12 @@ public class KeyguardManager {
* @param callback Lets you know whether the operation was successful and
* it is safe to launch anything that would normally be considered safe
* once the user has gotten past the keyguard.
+
+ * @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.
*/
@Deprecated
@RequiresPermission(Manifest.permission.DISABLE_KEYGUARD)
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 308a00020db9..85a6faab0749 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -116,8 +116,10 @@ interface IWindowManager
void stopFreezingScreen();
// these require DISABLE_KEYGUARD permission
- void disableKeyguard(IBinder token, String tag);
- void reenableKeyguard(IBinder token);
+ /** @deprecated use Activity.setShowWhenLocked instead. */
+ void disableKeyguard(IBinder token, String tag, int userId);
+ /** @deprecated use Activity.setShowWhenLocked instead. */
+ void reenableKeyguard(IBinder token, int userId);
void exitKeyguardSecurely(IOnKeyguardExitResult callback);
boolean isKeyguardLocked();
boolean isKeyguardSecure();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 3b9110d31c6f..880197836392 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -406,24 +406,6 @@ public class KeyguardViewMediator extends SystemUI {
}
@Override
- public void onPhoneStateChanged(int phoneState) {
- synchronized (KeyguardViewMediator.this) {
- if (TelephonyManager.CALL_STATE_IDLE == phoneState // call ending
- && !mDeviceInteractive // screen off
- && mExternallyEnabled) { // not disabled by any app
-
- // note: this is a way to gracefully reenable the keyguard when the call
- // ends and the screen is off without always reenabling the keyguard
- // each time the screen turns off while in call (and having an occasional ugly
- // flicker while turning back on the screen and disabling the keyguard again).
- if (DEBUG) Log.d(TAG, "screen is off and call ended, let's make sure the "
- + "keyguard is showing");
- doKeyguardLocked(null);
- }
- }
- }
-
- @Override
public void onClockVisibilityChanged() {
adjustStatusBarLocked();
}
@@ -1313,15 +1295,7 @@ public class KeyguardViewMediator extends SystemUI {
if (!mExternallyEnabled) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
- // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes
- // for an occasional ugly flicker in this situation:
- // 1) receive a call with the screen on (no keyguard) or make a call
- // 2) screen times out
- // 3) user hits key to turn screen back on
- // instead, we reenable the keyguard when we know the screen is off and the call
- // ends (see the broadcast receiver below)
- // TODO: clean this up when we have better support at the window manager level
- // for apps that wish to be on top of the keyguard
+ mNeedToReshowWhenReenabled = true;
return;
}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index adfa8d546166..ea8c7922d831 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -112,6 +112,7 @@ import com.android.server.locksettings.LockSettingsStorage.PersistentData;
import com.android.server.locksettings.recoverablekeystore.RecoverableKeyStoreManager;
import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationResult;
import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationToken;
+import com.android.server.wm.WindowManagerInternal;
import libcore.util.HexEncoding;
@@ -1870,6 +1871,7 @@ public class LockSettingsService extends ILockSettings.Stub {
DevicePolicyManager dpm = (DevicePolicyManager)
mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
dpm.reportPasswordChanged(userId);
+ LocalServices.getService(WindowManagerInternal.class).reportPasswordChanged(userId);
});
}
diff --git a/services/core/java/com/android/server/utils/UserTokenWatcher.java b/services/core/java/com/android/server/utils/UserTokenWatcher.java
new file mode 100644
index 000000000000..a3e58f802845
--- /dev/null
+++ b/services/core/java/com/android/server/utils/UserTokenWatcher.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2018 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.server.utils;
+
+import android.annotation.UserIdInt;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.TokenWatcher;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.io.PrintWriter;
+
+/**
+ * Multi-user aware {@link TokenWatcher}.
+ *
+ * {@link UserTokenWatcher} is thread-safe.
+ */
+public final class UserTokenWatcher {
+
+ private final Callback mCallback;
+ private final Handler mHandler;
+ private final String mTag;
+
+ @GuardedBy("mWatchers")
+ private final SparseArray<TokenWatcher> mWatchers = new SparseArray<>(1);
+
+ public UserTokenWatcher(Callback callback, Handler handler, String tag) {
+ mCallback = callback;
+ mHandler = handler;
+ mTag = tag;
+ }
+
+ /**
+ * Record that this token has been acquired for the given user. When acquire is called, and
+ * the user's count goes from 0 to 1, the acquired callback is called on the given
+ * handler.
+ *
+ * Note that the same {@code token} can only be acquired once per user. If this
+ * {@code token} has already been acquired for the given user, no action is taken. The first
+ * subsequent call to {@link #release} will release this {@code token}
+ * immediately.
+ *
+ * @param token An IBinder object.
+ * @param tag A string used by the {@link #dump} method for debugging,
+ * to see who has references.
+ * @param userId A user id
+ */
+ public void acquire(IBinder token, String tag, @UserIdInt int userId) {
+ synchronized (mWatchers) {
+ TokenWatcher watcher = mWatchers.get(userId);
+ if (watcher == null) {
+ watcher = new InnerTokenWatcher(userId, mHandler, mTag);
+ mWatchers.put(userId, watcher);
+ }
+ watcher.acquire(token, tag);
+ }
+ }
+
+ /**
+ * Record that this token has been released for the given user. When release is called, and
+ * the user's count goes from 1 to 0, the released callback is called on the given
+ * handler.
+ *
+ * @param token An IBinder object.
+ * @param userId A user id
+ */
+ public void release(IBinder token, @UserIdInt int userId) {
+ synchronized (mWatchers) {
+ TokenWatcher watcher = mWatchers.get(userId);
+ if (watcher != null) {
+ watcher.release(token);
+ }
+ }
+ }
+
+ /**
+ * Returns whether the given user has any registered tokens that have not been cleaned up.
+ *
+ * @return true, if the given user has registered tokens.
+ */
+ public boolean isAcquired(@UserIdInt int userId) {
+ synchronized (mWatchers) {
+ TokenWatcher watcher = mWatchers.get(userId);
+ return watcher != null && watcher.isAcquired();
+ }
+ }
+
+ /**
+ * Dumps the current state.
+ */
+ public void dump(PrintWriter pw) {
+ synchronized (mWatchers) {
+ for (int i = 0; i < mWatchers.size(); i++) {
+ int userId = mWatchers.keyAt(i);
+ TokenWatcher watcher = mWatchers.valueAt(i);
+ if (watcher.isAcquired()) {
+ pw.print("User ");
+ pw.print(userId);
+ pw.println(":");
+ watcher.dump(new IndentingPrintWriter(pw, " "));
+ }
+ }
+ }
+ }
+
+ /**
+ * Callback for {@link UserTokenWatcher}.
+ */
+ public interface Callback {
+
+ /**
+ * Reports that the first token has been acquired for the given user.
+ */
+ void acquired(@UserIdInt int userId);
+
+ /**
+ * Reports that the last token has been release for the given user.
+ */
+ void released(@UserIdInt int userId);
+ }
+
+ private final class InnerTokenWatcher extends TokenWatcher {
+ private final int mUserId;
+
+ private InnerTokenWatcher(int userId, Handler handler, String tag) {
+ super(handler, tag);
+ this.mUserId = userId;
+ }
+
+ @Override
+ public void acquired() {
+ // We MUST NOT hold any locks while invoking the callbacks.
+ mCallback.acquired(mUserId);
+ }
+
+ @Override
+ public void released() {
+ // We MUST NOT hold any locks while invoking the callbacks.
+ mCallback.released(mUserId);
+
+ synchronized (mWatchers) {
+ final TokenWatcher watcher = mWatchers.get(mUserId);
+ if (watcher != null && !watcher.isAcquired()) {
+ mWatchers.remove(mUserId);
+ }
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/KeyguardDisableHandler.java b/services/core/java/com/android/server/wm/KeyguardDisableHandler.java
index 4a20f1a039ef..c9173a6430cc 100644
--- a/services/core/java/com/android/server/wm/KeyguardDisableHandler.java
+++ b/services/core/java/com/android/server/wm/KeyguardDisableHandler.java
@@ -19,113 +19,142 @@ package com.android.server.wm;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.TokenWatcher;
-import android.util.Log;
-import android.util.Pair;
+import android.os.Process;
+import android.os.UserHandle;
+import android.os.UserManagerInternal;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.LocalServices;
import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.utils.UserTokenWatcher;
+import com.android.server.wm.LockTaskController.LockTaskToken;
-public class KeyguardDisableHandler extends Handler {
+class KeyguardDisableHandler {
private static final String TAG = TAG_WITH_CLASS_NAME ? "KeyguardDisableHandler" : TAG_WM;
- private static final int ALLOW_DISABLE_YES = 1;
- private static final int ALLOW_DISABLE_NO = 0;
- private static final int ALLOW_DISABLE_UNKNOWN = -1; // check with DevicePolicyManager
- private int mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN; // sync'd by mKeyguardTokenWatcher
+ private final UserTokenWatcher mAppTokenWatcher;
+ private final UserTokenWatcher mSystemTokenWatcher;
- // Message.what constants
- static final int KEYGUARD_DISABLE = 1;
- static final int KEYGUARD_REENABLE = 2;
- static final int KEYGUARD_POLICY_CHANGED = 3;
+ private int mCurrentUser = UserHandle.USER_SYSTEM;
+ private Injector mInjector;
- final Context mContext;
- final WindowManagerPolicy mPolicy;
- KeyguardTokenWatcher mKeyguardTokenWatcher;
+ @VisibleForTesting
+ KeyguardDisableHandler(Injector injector, Handler handler) {
+ mInjector = injector;
+ mAppTokenWatcher = new UserTokenWatcher(mCallback, handler, TAG);
+ mSystemTokenWatcher = new UserTokenWatcher(mCallback, handler, TAG);
+ }
- public KeyguardDisableHandler(final Context context, final WindowManagerPolicy policy) {
- mContext = context;
- mPolicy = policy;
+ public void setCurrentUser(int user) {
+ synchronized (this) {
+ mCurrentUser = user;
+ updateKeyguardEnabledLocked(UserHandle.USER_ALL);
+ }
}
- @SuppressWarnings("unchecked")
- @Override
- public void handleMessage(Message msg) {
- if (mKeyguardTokenWatcher == null) {
- mKeyguardTokenWatcher = new KeyguardTokenWatcher(this);
+ void updateKeyguardEnabled(int userId) {
+ synchronized (this) {
+ updateKeyguardEnabledLocked(userId);
}
+ }
- switch (msg.what) {
- case KEYGUARD_DISABLE:
- final Pair<IBinder, String> pair = (Pair<IBinder, String>)msg.obj;
- mKeyguardTokenWatcher.acquire(pair.first, pair.second);
- break;
-
- case KEYGUARD_REENABLE:
- mKeyguardTokenWatcher.release((IBinder)msg.obj);
- break;
-
- case KEYGUARD_POLICY_CHANGED:
- mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN;
- if (mKeyguardTokenWatcher.isAcquired()) {
- // If we are currently disabled we need to know if the keyguard
- // should be re-enabled, so determine the allow state immediately.
- mKeyguardTokenWatcher.updateAllowState();
- if (mAllowDisableKeyguard != ALLOW_DISABLE_YES) {
- mPolicy.enableKeyguard(true);
- }
- } else {
- // lazily evaluate this next time we're asked to disable keyguard
- mPolicy.enableKeyguard(true);
- }
- break;
+ private void updateKeyguardEnabledLocked(int userId) {
+ if (mCurrentUser == userId || userId == UserHandle.USER_ALL) {
+ mInjector.enableKeyguard(shouldKeyguardBeEnabled(mCurrentUser));
}
}
- class KeyguardTokenWatcher extends TokenWatcher {
+ void disableKeyguard(IBinder token, String tag, int callingUid, int userId) {
+ UserTokenWatcher watcherForCaller = watcherForCallingUid(token, callingUid);
+ watcherForCaller.acquire(token, tag, mInjector.getProfileParentId(userId));
+ }
- public KeyguardTokenWatcher(final Handler handler) {
- super(handler, TAG);
- }
+ void reenableKeyguard(IBinder token, int callingUid, int userId) {
+ UserTokenWatcher watcherForCaller = watcherForCallingUid(token, callingUid);
+ watcherForCaller.release(token, mInjector.getProfileParentId(userId));
+ }
- public void updateAllowState() {
- // We fail safe and prevent disabling keyguard in the unlikely event this gets
- // called before DevicePolicyManagerService has started.
- DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
- Context.DEVICE_POLICY_SERVICE);
- if (dpm != null) {
- try {
- mAllowDisableKeyguard = dpm.getPasswordQuality(null,
- ActivityManager.getService().getCurrentUser().id)
- == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ?
- ALLOW_DISABLE_YES : ALLOW_DISABLE_NO;
- } catch (RemoteException re) {
- // Nothing much we can do
- }
- }
+ private UserTokenWatcher watcherForCallingUid(IBinder token, int callingUid) {
+ if (Process.isApplicationUid(callingUid)) {
+ return mAppTokenWatcher;
+ } else if (callingUid == Process.SYSTEM_UID && token instanceof LockTaskToken) {
+ // We allow the lock task token here as a legacy case, because it enforces its own
+ // security guarantees.
+ // NOTE: DO NOT add new usages of this API in system server. It is deprecated and
+ // easily misused.
+ return mSystemTokenWatcher;
+ } else {
+ throw new UnsupportedOperationException("Only apps can use the KeyguardLock API");
}
+ }
+
+ private boolean shouldKeyguardBeEnabled(int userId) {
+ final boolean dpmRequiresPassword = mInjector.dpmRequiresPassword(mCurrentUser);
+ final boolean keyguardSecure = mInjector.isKeyguardSecure(mCurrentUser);
+
+ final boolean allowedFromApps = !dpmRequiresPassword && !keyguardSecure;
+ // The system can disable the keyguard for lock task mode even if the keyguard is secure,
+ // because it enforces its own security guarantees.
+ final boolean allowedFromSystem = !dpmRequiresPassword;
+ final boolean shouldBeDisabled = allowedFromApps && mAppTokenWatcher.isAcquired(userId)
+ || allowedFromSystem && mSystemTokenWatcher.isAcquired(userId);
+ return !shouldBeDisabled;
+ }
+
+ // Callback happens on mHandler thread.
+ private final UserTokenWatcher.Callback mCallback = new UserTokenWatcher.Callback() {
@Override
- public void acquired() {
- if (mAllowDisableKeyguard == ALLOW_DISABLE_UNKNOWN) {
- updateAllowState();
- }
- if (mAllowDisableKeyguard == ALLOW_DISABLE_YES) {
- mPolicy.enableKeyguard(false);
- } else {
- Log.v(TAG, "Not disabling keyguard since device policy is enforced");
- }
+ public void acquired(int userId) {
+ updateKeyguardEnabled(userId);
}
@Override
- public void released() {
- mPolicy.enableKeyguard(true);
+ public void released(int userId) {
+ updateKeyguardEnabled(userId);
}
+ };
+
+ static KeyguardDisableHandler create(Context context, WindowManagerPolicy policy,
+ Handler handler) {
+ final UserManagerInternal userManager = LocalServices.getService(UserManagerInternal.class);
+ return new KeyguardDisableHandler(new Injector() {
+ @Override
+ public boolean dpmRequiresPassword(int userId) {
+ DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ return dpm == null || dpm.getPasswordQuality(null, userId)
+ != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+ }
+
+ @Override
+ public boolean isKeyguardSecure(int userId) {
+ return policy.isKeyguardSecure(userId);
+ }
+
+ @Override
+ public int getProfileParentId(int userId) {
+ return userManager.getProfileParentId(userId);
+ }
+
+ @Override
+ public void enableKeyguard(boolean enabled) {
+ policy.enableKeyguard(enabled);
+ }
+ }, handler);
+ }
+
+ interface Injector {
+ boolean dpmRequiresPassword(int userId);
+
+ boolean isKeyguardSecure(int userId);
+
+ int getProfileParentId(int userId);
+
+ void enableKeyguard(boolean enabled);
}
}
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index 41d0777d1c78..090451f08188 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -54,6 +54,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.provider.Settings;
import android.telecom.TelecomManager;
import android.util.Pair;
@@ -126,7 +127,7 @@ public class LockTaskController {
/** Tag used for disabling of keyguard */
private static final String LOCK_TASK_TAG = "Lock-to-App";
- private final IBinder mToken = new Binder();
+ private final IBinder mToken = new LockTaskToken();
private final ActivityStackSupervisor mSupervisor;
private final Context mContext;
@@ -180,6 +181,17 @@ public class LockTaskController {
*/
private final Handler mHandler;
+ /**
+ * Stores the user for which we're trying to dismiss the keyguard and then subsequently
+ * disable it.
+ *
+ * Tracking this ensures we don't mistakenly disable the keyguard if we've stopped trying to
+ * between the dismiss request and when it succeeds.
+ *
+ * Must only be accessed from the Handler thread.
+ */
+ private int mPendingDisableFromDismiss = UserHandle.USER_NULL;
+
LockTaskController(Context context, ActivityStackSupervisor supervisor,
Handler handler) {
mContext = context;
@@ -739,16 +751,18 @@ public class LockTaskController {
* Should only be called on the handler thread to avoid race.
*/
private void setKeyguardState(int lockTaskModeState, int userId) {
+ mPendingDisableFromDismiss = UserHandle.USER_NULL;
if (lockTaskModeState == LOCK_TASK_MODE_NONE) {
- mWindowManager.reenableKeyguard(mToken);
+ mWindowManager.reenableKeyguard(mToken, userId);
} else if (lockTaskModeState == LOCK_TASK_MODE_LOCKED) {
if (isKeyguardAllowed(userId)) {
- mWindowManager.reenableKeyguard(mToken);
+ mWindowManager.reenableKeyguard(mToken, userId);
} else {
// If keyguard is not secure and it is locked, dismiss the keyguard before
// disabling it, which avoids the platform to think the keyguard is still on.
if (mWindowManager.isKeyguardLocked() && !mWindowManager.isKeyguardSecure()) {
+ mPendingDisableFromDismiss = userId;
mWindowManager.dismissKeyguard(new IKeyguardDismissCallback.Stub() {
@Override
public void onDismissError() throws RemoteException {
@@ -758,7 +772,13 @@ public class LockTaskController {
@Override
public void onDismissSucceeded() throws RemoteException {
mHandler.post(
- () -> mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG));
+ () -> {
+ if (mPendingDisableFromDismiss == userId) {
+ mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG,
+ userId);
+ mPendingDisableFromDismiss = UserHandle.USER_NULL;
+ }
+ });
}
@Override
@@ -767,12 +787,12 @@ public class LockTaskController {
}
}, null);
} else {
- mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG);
+ mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG, userId);
}
}
} else { // lockTaskModeState == LOCK_TASK_MODE_PINNED
- mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG);
+ mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG, userId);
}
}
@@ -897,4 +917,10 @@ public class LockTaskController {
default: return "unknown=" + mLockTaskModeState;
}
}
+
+ /** Marker class for the token used to disable keyguard. */
+ static class LockTaskToken extends Binder {
+ private LockTaskToken() {
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index e83b8634925e..cf722a21b1ba 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -335,6 +335,11 @@ public abstract class WindowManagerInternal {
public abstract void registerAppTransitionListener(AppTransitionListener listener);
/**
+ * Reports that the password for the given user has changed.
+ */
+ public abstract void reportPasswordChanged(int userId);
+
+ /**
* Retrieves a height of input method window for given display.
*/
public abstract int getInputMethodWindowVisibleHeight(int displayId);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 39a8465a31b3..a119a2337af7 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -22,6 +22,7 @@ import static android.Manifest.permission.MANAGE_APP_TOKENS;
import static android.Manifest.permission.READ_FRAME_BUFFER;
import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
import static android.Manifest.permission.RESTRICTED_VR_ACCESS;
+import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.app.StatusBarManager.DISABLE_MASK;
@@ -71,7 +72,6 @@ import static com.android.internal.util.LatencyTracker.ACTION_ROTATE_SCREEN;
import static com.android.server.LockGuard.INDEX_WINDOW;
import static com.android.server.LockGuard.installLock;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
@@ -180,7 +180,6 @@ import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
import android.util.MergedConfiguration;
-import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -233,6 +232,7 @@ import com.android.internal.policy.IShortcutService;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.LatencyTracker;
+import com.android.internal.util.Preconditions;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.view.WindowManagerPolicyThread;
import com.android.server.AnimationThread;
@@ -394,7 +394,7 @@ public class WindowManagerService extends IWindowManager.Stub
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED:
- mKeyguardDisableHandler.sendEmptyMessage(KEYGUARD_POLICY_CHANGED);
+ mKeyguardDisableHandler.updateKeyguardEnabled(getSendingUserId());
break;
}
}
@@ -959,7 +959,7 @@ public class WindowManagerService extends IWindowManager.Stub
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
- mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
+ mKeyguardDisableHandler = KeyguardDisableHandler.create(mContext, mPolicy, mH);
mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
@@ -1038,7 +1038,7 @@ public class WindowManagerService extends IWindowManager.Stub
IntentFilter filter = new IntentFilter();
// Track changes to DevicePolicyManager state so we can enable/disable keyguard.
filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
- mContext.registerReceiver(mBroadcastReceiver, filter);
+ mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
mLatencyTracker = LatencyTracker.getInstance(context);
@@ -2800,45 +2800,38 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
- public void disableKeyguard(IBinder token, String tag) {
+ public void disableKeyguard(IBinder token, String tag, int userId) {
+ userId = mAmInternal.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, false /* allowAll */, ALLOW_FULL_ONLY, "disableKeyguard", null);
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires DISABLE_KEYGUARD permission");
}
- // If this isn't coming from the system then don't allow disabling the lockscreen
- // to bypass security.
- if (Binder.getCallingUid() != SYSTEM_UID && isKeyguardSecure()) {
- Log.d(TAG_WM, "current mode is SecurityMode, ignore disableKeyguard");
- return;
- }
-
- // If this isn't coming from the current profiles, ignore it.
- if (!isCurrentProfileLocked(UserHandle.getCallingUserId())) {
- Log.d(TAG_WM, "non-current profiles, ignore disableKeyguard");
- return;
- }
-
- if (token == null) {
- throw new IllegalArgumentException("token == null");
+ final int callingUid = Binder.getCallingUid();
+ final long origIdentity = Binder.clearCallingIdentity();
+ try {
+ mKeyguardDisableHandler.disableKeyguard(token, tag, callingUid, userId);
+ } finally {
+ Binder.restoreCallingIdentity(origIdentity);
}
-
- mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
- KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
}
@Override
- public void reenableKeyguard(IBinder token) {
+ public void reenableKeyguard(IBinder token, int userId) {
+ userId = mAmInternal.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, false /* allowAll */, ALLOW_FULL_ONLY, "reenableKeyguard", null);
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires DISABLE_KEYGUARD permission");
}
-
- if (token == null) {
- throw new IllegalArgumentException("token == null");
+ Preconditions.checkNotNull(token, "token is null");
+ final int callingUid = Binder.getCallingUid();
+ final long origIdentity = Binder.clearCallingIdentity();
+ try {
+ mKeyguardDisableHandler.reenableKeyguard(token, callingUid, userId);
+ } finally {
+ Binder.restoreCallingIdentity(origIdentity);
}
-
- mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
- KeyguardDisableHandler.KEYGUARD_REENABLE, token));
}
/**
@@ -3122,11 +3115,7 @@ public class WindowManagerService extends IWindowManager.Stub
mCurrentUserId = newUserId;
mCurrentProfileIds = currentProfileIds;
mPolicy.setCurrentUserLw(newUserId);
-
- // If keyguard was disabled, re-enable it
- // TODO: Keep track of keyguardEnabled state per user and use here...
- // e.g. enabled = mKeyguardDisableHandler.getEnabledStateForUser(newUserId);
- mPolicy.enableKeyguard(true);
+ mKeyguardDisableHandler.setCurrentUser(newUserId);
// Hide windows that should not be seen by the new user.
mRoot.switchUser();
@@ -7099,6 +7088,11 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
+ public void reportPasswordChanged(int userId) {
+ mKeyguardDisableHandler.updateKeyguardEnabled(userId);
+ }
+
+ @Override
public int getInputMethodWindowVisibleHeight(int displayId) {
synchronized (mGlobalLock) {
final DisplayContent dc = mRoot.getDisplayContent(displayId);
diff --git a/services/tests/wmtests/src/com/android/server/wm/KeyguardDisableHandlerTest.java b/services/tests/wmtests/src/com/android/server/wm/KeyguardDisableHandlerTest.java
new file mode 100644
index 000000000000..ce22788f7cb9
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/KeyguardDisableHandlerTest.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2018 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.server.wm;
+
+import static android.os.Process.FIRST_APPLICATION_UID;
+import static android.os.Process.NFC_UID;
+import static android.os.Process.SYSTEM_UID;
+import static android.os.UserHandle.USER_ALL;
+import static android.os.UserHandle.USER_SYSTEM;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.UserHandle;
+import android.util.SparseBooleanArray;
+
+import com.android.server.wm.LockTaskController.LockTaskToken;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.lang.reflect.Constructor;
+
+public class KeyguardDisableHandlerTest {
+
+ private KeyguardDisableHandler mKeyguardDisable;
+
+ private boolean mKeyguardEnabled;
+ private SparseBooleanArray mKeyguardSecure = new SparseBooleanArray();
+ private SparseBooleanArray mDpmRequiresPassword = new SparseBooleanArray();
+
+ @Before
+ public void setUp() throws Exception {
+ mKeyguardEnabled = true;
+
+ mKeyguardDisable = new KeyguardDisableHandler(new KeyguardDisableHandler.Injector() {
+ @Override
+ public boolean dpmRequiresPassword(int userId) {
+ return mDpmRequiresPassword.get(userId);
+ }
+
+ @Override
+ public boolean isKeyguardSecure(int userId) {
+ return mKeyguardSecure.get(userId);
+ }
+
+ @Override
+ public int getProfileParentId(int userId) {
+ return userId;
+ }
+
+ @Override
+ public void enableKeyguard(boolean enabled) {
+ mKeyguardEnabled = enabled;
+ }
+ }, mock(Handler.class)) {
+ @Override
+ public void disableKeyguard(IBinder token, String tag, int callingUid, int userId) {
+ super.disableKeyguard(token, tag, callingUid, userId);
+ // In the actual code, the update is posted to the handler thread. Eagerly update
+ // here to simplify the test.
+ updateKeyguardEnabled(userId);
+ }
+
+ @Override
+ public void reenableKeyguard(IBinder token, int callingUid, int userId) {
+ super.reenableKeyguard(token, callingUid, userId);
+ // In the actual code, the update is posted to the handler thread. Eagerly update
+ // here to simplify the test.
+ updateKeyguardEnabled(userId);
+ }
+ };
+ }
+
+ @Test
+ public void starts_enabled() {
+ assertTrue(mKeyguardEnabled);
+ mKeyguardDisable.updateKeyguardEnabled(USER_ALL);
+ assertTrue(mKeyguardEnabled);
+ }
+
+ @Test
+ public void disable_fromApp_disables() {
+ mKeyguardDisable.disableKeyguard(new Binder(), "Tag", FIRST_APPLICATION_UID, USER_SYSTEM);
+ assertFalse(mKeyguardEnabled);
+ }
+
+ @Test
+ public void disable_fromApp_secondaryUser_disables() {
+ mKeyguardDisable.setCurrentUser(1);
+ mKeyguardDisable.disableKeyguard(new Binder(), "Tag",
+ UserHandle.getUid(1, FIRST_APPLICATION_UID), 1);
+ assertFalse(mKeyguardEnabled);
+ }
+
+ @Test
+ public void disable_fromSystem_LockTask_disables() {
+ mKeyguardDisable.disableKeyguard(createLockTaskToken(), "Tag", SYSTEM_UID, USER_SYSTEM);
+ assertFalse(mKeyguardEnabled);
+ }
+
+ @Test
+ public void disable_fromSystem_genericToken_fails() {
+ try {
+ mKeyguardDisable.disableKeyguard(new Binder(), "Tag", SYSTEM_UID, USER_SYSTEM);
+ fail("Expected exception not thrown");
+ } catch (UnsupportedOperationException e) {
+ assertThat(e.getMessage(), containsString("Only apps can use the KeyguardLock API"));
+ }
+ assertTrue(mKeyguardEnabled);
+ }
+
+ @Test
+ public void disable_fromNonApp_genericToken_fails() {
+ try {
+ mKeyguardDisable.disableKeyguard(new Binder(), "Tag", NFC_UID, USER_SYSTEM);
+ fail("Expected exception not thrown");
+ } catch (UnsupportedOperationException e) {
+ assertThat(e.getMessage(), containsString("Only apps can use the KeyguardLock API"));
+ }
+ assertTrue(mKeyguardEnabled);
+ }
+
+ @Test
+ public void disable_fromApp_secure_staysEnabled() {
+ configureIsSecure(true, USER_SYSTEM);
+ mKeyguardDisable.disableKeyguard(new Binder(), "Tag", FIRST_APPLICATION_UID, USER_SYSTEM);
+ assertTrue(mKeyguardEnabled);
+ }
+
+ @Test
+ public void disable_fromApp_dpmRequiresPassword_staysEnabled() {
+ configureDpmRequiresPassword(true, USER_SYSTEM);
+ mKeyguardDisable.disableKeyguard(new Binder(), "Tag", FIRST_APPLICATION_UID, USER_SYSTEM);
+ assertTrue(mKeyguardEnabled);
+ }
+
+ @Test
+ public void disable_fromSystem_LockTask_secure_disables() {
+ configureIsSecure(true, USER_SYSTEM);
+ mKeyguardDisable.disableKeyguard(createLockTaskToken(), "Tag", SYSTEM_UID, USER_SYSTEM);
+ assertFalse(mKeyguardEnabled);
+ }
+
+ @Test
+ public void disable_fromSystem_LockTask_requiresDpm_staysEnabled() {
+ configureDpmRequiresPassword(true, USER_SYSTEM);
+ mKeyguardDisable.disableKeyguard(createLockTaskToken(), "Tag", SYSTEM_UID, USER_SYSTEM);
+ assertTrue(mKeyguardEnabled);
+ }
+
+ @Test
+ public void disable_fromApp_thenSecure_reenables() {
+ mKeyguardDisable.disableKeyguard(new Binder(), "Tag", FIRST_APPLICATION_UID, USER_SYSTEM);
+ configureIsSecure(true, USER_SYSTEM);
+ assertTrue(mKeyguardEnabled);
+ }
+
+ @Test
+ public void disable_fromSystem_LockTask_thenRequiresDpm_reenables() {
+ mKeyguardDisable.disableKeyguard(createLockTaskToken(), "Tag", SYSTEM_UID, USER_SYSTEM);
+ configureDpmRequiresPassword(true, USER_SYSTEM);
+ assertTrue(mKeyguardEnabled);
+ }
+
+ @Test
+ public void user_switch_to_enabledUser_applies_enabled() {
+ mKeyguardDisable.disableKeyguard(createLockTaskToken(), "Tag", SYSTEM_UID, USER_SYSTEM);
+ assertFalse("test setup failed", mKeyguardEnabled);
+ mKeyguardDisable.setCurrentUser(1);
+ assertTrue(mKeyguardEnabled);
+ }
+
+ @Test
+ public void user_switch_to_disabledUser_applies_disabled() {
+ mKeyguardDisable.disableKeyguard(createLockTaskToken(), "Tag",
+ SYSTEM_UID, 1);
+ assertTrue("test setup failed", mKeyguardEnabled);
+ mKeyguardDisable.setCurrentUser(1);
+ assertFalse(mKeyguardEnabled);
+ }
+
+ private void configureIsSecure(boolean secure, int userId) {
+ mKeyguardSecure.put(userId, secure);
+ mKeyguardDisable.updateKeyguardEnabled(userId);
+ }
+
+ private void configureDpmRequiresPassword(boolean requiresPassword, int userId) {
+ mDpmRequiresPassword.put(userId, requiresPassword);
+ mKeyguardDisable.updateKeyguardEnabled(userId);
+ }
+
+ private LockTaskToken createLockTaskToken() {
+ try {
+ final Constructor<LockTaskToken> constructor =
+ LockTaskToken.class.getDeclaredConstructor();
+ constructor.setAccessible(true);
+ return constructor.newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
index 33e6063bbb97..9d061e1084d6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
@@ -558,19 +558,20 @@ public class LockTaskControllerTest {
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// THEN keyguard should be disabled
- verify(mWindowManager).disableKeyguard(any(IBinder.class), anyString());
+ verify(mWindowManager).disableKeyguard(any(IBinder.class), anyString(), eq(TEST_USER_ID));
// WHEN keyguard is enabled for lock task mode
mLockTaskController.updateLockTaskFeatures(TEST_USER_ID, LOCK_TASK_FEATURE_KEYGUARD);
// THEN keyguard should be enabled
- verify(mWindowManager).reenableKeyguard(any(IBinder.class));
+ verify(mWindowManager).reenableKeyguard(any(IBinder.class), eq(TEST_USER_ID));
// WHEN keyguard is disabled again for lock task mode
mLockTaskController.updateLockTaskFeatures(TEST_USER_ID, LOCK_TASK_FEATURE_NONE);
// THEN keyguard should be disabled
- verify(mWindowManager, times(2)).disableKeyguard(any(IBinder.class), anyString());
+ verify(mWindowManager, times(2)).disableKeyguard(any(IBinder.class), anyString(),
+ eq(TEST_USER_ID));
}
@Test
@@ -651,7 +652,7 @@ public class LockTaskControllerTest {
private void verifyLockTaskStarted(int statusBarMask, int statusBarMask2) throws Exception {
// THEN the keyguard should have been disabled
- verify(mWindowManager).disableKeyguard(any(IBinder.class), anyString());
+ verify(mWindowManager).disableKeyguard(any(IBinder.class), anyString(), eq(TEST_USER_ID));
// THEN the status bar should have been disabled
verify(mStatusBarService).disable(eq(statusBarMask), any(IBinder.class),
eq(mContext.getPackageName()));
@@ -666,7 +667,7 @@ public class LockTaskControllerTest {
private void verifyLockTaskStopped(VerificationMode mode) throws Exception {
// THEN the keyguard should have been disabled
- verify(mWindowManager, mode).reenableKeyguard(any(IBinder.class));
+ verify(mWindowManager, mode).reenableKeyguard(any(IBinder.class), eq(TEST_USER_ID));
// THEN the status bar should have been disabled
verify(mStatusBarService, mode).disable(eq(StatusBarManager.DISABLE_NONE),
any(IBinder.class), eq(mContext.getPackageName()));
diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index 14312cf84693..369a002fa273 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -20,6 +20,7 @@ import android.content.res.Configuration;
import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.IWindowManager;
import junit.framework.TestCase;
@@ -107,7 +108,7 @@ public class WindowManagerPermissionTests extends TestCase {
public void testDISABLE_KEYGUARD() {
Binder token = new Binder();
try {
- mWm.disableKeyguard(token, "foo");
+ mWm.disableKeyguard(token, "foo", UserHandle.myUserId());
fail("IWindowManager.disableKeyguard did not throw SecurityException as"
+ " expected");
} catch (SecurityException e) {
@@ -117,7 +118,7 @@ public class WindowManagerPermissionTests extends TestCase {
}
try {
- mWm.reenableKeyguard(token);
+ mWm.reenableKeyguard(token, UserHandle.myUserId());
fail("IWindowManager.reenableKeyguard did not throw SecurityException as"
+ " expected");
} catch (SecurityException e) {