Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19cc3423 authored by Adrian Roos's avatar Adrian Roos Committed by Android (Google) Code Review
Browse files

Merge "KeyguardDisableHandler: make properly user aware"

parents d799f002 1c8e3c0b
Loading
Loading
Loading
Loading
+20 −20
Original line number Diff line number Diff line
@@ -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)
+4 −2
Original line number Diff line number Diff line
@@ -117,8 +117,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();
+1 −27
Original line number Diff line number Diff line
@@ -405,24 +405,6 @@ public class KeyguardViewMediator extends SystemUI {
        public void onUserInfoChanged(int userId) {
        }

        @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();
@@ -1316,15 +1298,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;
        }

+2 −0
Original line number Diff line number Diff line
@@ -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);
        });
    }

+166 −0
Original line number Diff line number Diff line
/*
 * 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);
                }
            }
        }
    }
}
Loading