/*
|
* 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 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;
|
|
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);
|
}
|
}
|