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