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