blob: c8558dda171d76fc5b6eea2eabe5d25dd3db0dde [file] [log] [blame]
/*
* Copyright (C) 2012 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 com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.app.admin.DevicePolicyCache;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
import android.os.Process;
import android.os.UserHandle;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
import com.android.server.pm.UserManagerInternal;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.utils.UserTokenWatcher;
import com.android.server.wm.LockTaskController.LockTaskToken;
class KeyguardDisableHandler {
private static final String TAG = TAG_WITH_CLASS_NAME ? "KeyguardDisableHandler" : TAG_WM;
private final UserTokenWatcher mAppTokenWatcher;
private final UserTokenWatcher mSystemTokenWatcher;
private int mCurrentUser = UserHandle.USER_SYSTEM;
private Injector mInjector;
@VisibleForTesting
KeyguardDisableHandler(Injector injector, Handler handler) {
mInjector = injector;
mAppTokenWatcher = new UserTokenWatcher(mCallback, handler, TAG);
mSystemTokenWatcher = new UserTokenWatcher(mCallback, handler, TAG);
}
public void setCurrentUser(int user) {
synchronized (this) {
mCurrentUser = user;
updateKeyguardEnabledLocked(UserHandle.USER_ALL);
}
}
void updateKeyguardEnabled(int userId) {
synchronized (this) {
updateKeyguardEnabledLocked(userId);
}
}
private void updateKeyguardEnabledLocked(int userId) {
if (mCurrentUser == userId || userId == UserHandle.USER_ALL) {
mInjector.enableKeyguard(shouldKeyguardBeEnabled(mCurrentUser));
}
}
void disableKeyguard(IBinder token, String tag, int callingUid, int userId) {
UserTokenWatcher watcherForCaller = watcherForCallingUid(token, callingUid);
watcherForCaller.acquire(token, tag, mInjector.getProfileParentId(userId));
}
void reenableKeyguard(IBinder token, int callingUid, int userId) {
UserTokenWatcher watcherForCaller = watcherForCallingUid(token, callingUid);
watcherForCaller.release(token, mInjector.getProfileParentId(userId));
}
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(int userId) {
updateKeyguardEnabled(userId);
}
@Override
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) {
return DevicePolicyCache.getInstance().getPasswordQuality(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);
}
}