summaryrefslogtreecommitdiffstats
path: root/packages/SystemUI/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'packages/SystemUI/src/com')
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java196
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardStatusBarBinder.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java1361
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java164
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java227
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java192
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java13
10 files changed, 1909 insertions, 310 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index cc87735..c7d29f0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -20,20 +20,20 @@ import com.android.internal.policy.IKeyguardExitCallback;
import com.android.internal.policy.IKeyguardService;
import com.android.internal.policy.IKeyguardServiceConstants;
import com.android.internal.policy.IKeyguardShowCallback;
-import com.android.systemui.statusbar.CommandQueue;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.StatusBarWindowManager;
-import android.app.ActivityManagerNative;
import android.app.Service;
-import android.app.StatusBarManager;
-import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.Debug;
import android.os.IBinder;
-import android.os.RemoteException;
import android.util.Log;
import android.view.MotionEvent;
+import android.view.ViewGroup;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -43,11 +43,12 @@ public class KeyguardService extends Service {
public static final String ACTION_STATUS_BAR_BIND = "action.status_bar_bind";
- private CommandQueue mCommandQueue;
- private StatusBarManager mStatusBarManager;
+ private KeyguardViewMediator mKeyguardViewMediator;
@Override
public void onCreate() {
+ LockPatternUtils lockPatternUtils = new LockPatternUtils(this);
+ mKeyguardViewMediator = new KeyguardViewMediator(this, lockPatternUtils);
}
@Override
@@ -67,205 +68,158 @@ public class KeyguardService extends Service {
}
}
- private final KeyguardStatusBarBinder mKeyguardStatusBarBinder =
- new KeyguardStatusBarBinder() {
+ private final KeyguardStatusBarBinder mKeyguardStatusBarBinder = new KeyguardStatusBarBinder() {
@Override
- public void register(CommandQueue commandQueue) {
- mCommandQueue = commandQueue;
- }
-
- @Override
- public void dismissKeyguard() {
- try {
- mBinder.dismiss();
- } catch (RemoteException e) {
- Log.e(TAG, "Could not dismiss keyguard", e);
- }
+ public void registerStatusBar(PhoneStatusBar phoneStatusBar, ViewGroup container,
+ StatusBarWindowManager statusBarWindowManager) {
+ mKeyguardViewMediator.registerStatusBar(phoneStatusBar, container,
+ statusBarWindowManager);
}
};
private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {
- /** Whether the Keyguard is visible. */
- private boolean mShowing;
-
- /**
- * Whether the Keyguard is hidden by a window with
- * {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED}. So mShowing might
- * be true, but also mHidden. So in the end, the Keyguard would not be visible.
- */
- private boolean mHidden;
- private boolean mShowingDream;
+ private boolean mIsOccluded;
@Override
- public synchronized boolean isShowing() {
- return mShowing;
+ public boolean isShowing() {
+ return mKeyguardViewMediator.isShowing();
}
@Override
- public synchronized boolean isSecure() {
- return true;
+ public boolean isSecure() {
+ return mKeyguardViewMediator.isSecure();
}
@Override
- public synchronized boolean isShowingAndNotHidden() {
- return mShowing && !mHidden;
+ public boolean isShowingAndNotOccluded() {
+ return mKeyguardViewMediator.isShowingAndNotOccluded();
}
@Override
- public synchronized boolean isInputRestricted() {
- return false;
+ public boolean isInputRestricted() {
+ return mKeyguardViewMediator.isInputRestricted();
}
@Override
- public synchronized void verifyUnlock(IKeyguardExitCallback callback) {
+ public void verifyUnlock(IKeyguardExitCallback callback) {
+ checkPermission();
+ mKeyguardViewMediator.verifyUnlock(callback);
}
@Override
- public synchronized void keyguardDone(boolean authenticated, boolean wakeup) {
+ public void keyguardDone(boolean authenticated, boolean wakeup) {
checkPermission();
- mShowing = false;
- adjustStatusBarLocked();
- if (mCommandQueue != null) {
- mCommandQueue.setKeyguardShown(false, null, true);
- }
+ mKeyguardViewMediator.keyguardDone(authenticated, wakeup);
}
@Override
- public synchronized int setHidden(boolean isHidden) {
+ public int setOccluded(boolean isOccluded) {
checkPermission();
- if (mHidden == isHidden) {
- return IKeyguardServiceConstants.KEYGUARD_SERVICE_HIDE_RESULT_NONE;
- }
- mHidden = isHidden;
- try {
- ActivityManagerNative.getDefault().setLockScreenShown(mShowing && !mHidden
- || mShowingDream);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not update activity manager lock screen state", e);
- }
- adjustStatusBarLocked();
- if (mCommandQueue != null) {
- mCommandQueue.setKeyguardShown(!isHidden, null, false);
+ synchronized (this) {
+ int result;
+ if (isOccluded && mKeyguardViewMediator.isShowing()
+ && !mIsOccluded) {
+ result = IKeyguardServiceConstants
+ .KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_UNSET_FLAGS;
+ } else if (!isOccluded && mKeyguardViewMediator.isShowing()
+ && mIsOccluded) {
+ result = IKeyguardServiceConstants
+ .KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_SET_FLAGS;
+ } else {
+ result = IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_NONE;
+ }
+ if (mIsOccluded != isOccluded) {
+ mKeyguardViewMediator.setOccluded(isOccluded);
+
+ // Cache the value so we always have a fresh view in whether Keyguard is occluded.
+ // If we would just call mKeyguardViewMediator.isOccluded(), this might be stale
+ // because that value gets updated in another thread.
+ mIsOccluded = isOccluded;
+ }
+ return result;
}
- return isShowingAndNotHidden()
- ? IKeyguardServiceConstants.KEYGUARD_SERVICE_HIDE_RESULT_SET_FLAGS
- : IKeyguardServiceConstants.KEYGUARD_SERVICE_HIDE_RESULT_UNSET_FLAGS;
}
@Override
- public synchronized void dismiss() {
+ public void dismiss() {
checkPermission();
- mShowing = false;
- adjustStatusBarLocked();
- if (mCommandQueue != null) {
- mCommandQueue.setKeyguardShown(false, null, true);
- }
+ mKeyguardViewMediator.dismiss();
}
@Override
- public synchronized void onDreamingStarted() {
+ public void onDreamingStarted() {
checkPermission();
- mShowingDream = true;
+ mKeyguardViewMediator.onDreamingStarted();
}
@Override
- public synchronized void onDreamingStopped() {
+ public void onDreamingStopped() {
checkPermission();
- mShowingDream = false;
+ mKeyguardViewMediator.onDreamingStopped();
}
@Override
- public synchronized void onScreenTurnedOff(int reason) {
+ public void onScreenTurnedOff(int reason) {
checkPermission();
+ mKeyguardViewMediator.onScreenTurnedOff(reason);
}
@Override
- public synchronized void onScreenTurnedOn(IKeyguardShowCallback callback) {
+ public void onScreenTurnedOn(IKeyguardShowCallback callback) {
checkPermission();
- mShowing = true;
- adjustStatusBarLocked();
- if (mCommandQueue != null) {
- mCommandQueue.setKeyguardShown(isShowingAndNotHidden(), callback, true);
- }
+ mKeyguardViewMediator.onScreenTurnedOn(callback);
}
@Override
- public synchronized void setKeyguardEnabled(boolean enabled) {
+ public void setKeyguardEnabled(boolean enabled) {
checkPermission();
+ mKeyguardViewMediator.setKeyguardEnabled(enabled);
}
@Override
- public synchronized boolean isDismissable() {
- return !isSecure();
+ public boolean isDismissable() {
+ return mKeyguardViewMediator.isDismissable();
}
@Override
- public synchronized void onSystemReady() {
+ public void onSystemReady() {
checkPermission();
+ mKeyguardViewMediator.onSystemReady();
}
@Override
- public synchronized void doKeyguardTimeout(Bundle options) {
+ public void doKeyguardTimeout(Bundle options) {
checkPermission();
+ mKeyguardViewMediator.doKeyguardTimeout(options);
}
@Override
- public synchronized void setCurrentUser(int userId) {
+ public void setCurrentUser(int userId) {
checkPermission();
+ mKeyguardViewMediator.setCurrentUser(userId);
}
@Override
- public synchronized void showAssistant() {
+ public void showAssistant() {
checkPermission();
}
@Override
- public synchronized void dispatch(MotionEvent event) {
+ public void dispatch(MotionEvent event) {
checkPermission();
}
@Override
- public synchronized void launchCamera() {
+ public void launchCamera() {
checkPermission();
}
@Override
- public synchronized void onBootCompleted() {
+ public void onBootCompleted() {
checkPermission();
- onScreenTurnedOn(null);
- }
-
- private void adjustStatusBarLocked() {
- if (mStatusBarManager == null) {
- mStatusBarManager = (StatusBarManager) getSystemService(Context.STATUS_BAR_SERVICE);
- }
- if (mStatusBarManager == null) {
- Log.w(TAG, "Could not get status bar manager");
- } else {
- // Disable aspects of the system/status/navigation bars that must not be re-enabled by
- // windows that appear on top, ever
- int flags = StatusBarManager.DISABLE_NONE;
- if (isShowing()) {
- // Permanently disable components not available when keyguard is enabled
- // (like recents). Temporary enable/disable (e.g. the "back" button) are
- // done in KeyguardHostView.
- flags |= StatusBarManager.DISABLE_RECENT;
- if (isSecure()) {
- // showing secure lockscreen; disable ticker and switch private notifications
- // to show their public versions, if available.
- flags |= StatusBarManager.DISABLE_PRIVATE_NOTIFICATIONS;
- }
- if (false) {
- flags |= StatusBarManager.DISABLE_SEARCH;
- }
- }
- if (isShowingAndNotHidden()) {
- flags |= StatusBarManager.DISABLE_HOME;
- }
- mStatusBarManager.disable(flags);
- }
+ mKeyguardViewMediator.onBootCompleted();
}
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardStatusBarBinder.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardStatusBarBinder.java
index 566943b..04b6c29 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardStatusBarBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardStatusBarBinder.java
@@ -16,17 +16,18 @@
package com.android.systemui.keyguard;
-import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.StatusBarWindowManager;
import android.os.Binder;
-import android.os.IBinder;
+import android.view.ViewGroup;
/**
* Communication interface from status bar to {@link com.android.systemui.keyguard.KeyguardService}.
*/
public abstract class KeyguardStatusBarBinder extends Binder {
- public abstract void register(CommandQueue commandQueue);
-
- public abstract void dismissKeyguard();
+ public abstract void registerStatusBar(PhoneStatusBar phoneStatusBar, ViewGroup container,
+ StatusBarWindowManager statusBarWindowManager);
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
new file mode 100644
index 0000000..39ec86f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -0,0 +1,1361 @@
+/*
+ * Copyright (C) 2014 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.systemui.keyguard;
+
+import android.app.Activity;
+import android.app.ActivityManagerNative;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.app.SearchManager;
+import android.app.StatusBarManager;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.media.AudioManager;
+import android.media.SoundPool;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+import android.util.EventLog;
+import android.util.Log;
+import android.util.Slog;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+
+import com.android.internal.policy.IKeyguardExitCallback;
+import com.android.internal.policy.IKeyguardShowCallback;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardDisplayManager;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.keyguard.MultiUserAvatarCache;
+import com.android.keyguard.ViewMediatorCallback;
+import com.android.keyguard.analytics.KeyguardAnalytics;
+import com.android.keyguard.analytics.Session;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.StatusBarWindowManager;
+
+import java.io.File;
+
+import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+import static com.android.keyguard.analytics.KeyguardAnalytics.SessionTypeAdapter;
+
+
+/**
+ * Mediates requests related to the keyguard. This includes queries about the
+ * state of the keyguard, power management events that effect whether the keyguard
+ * should be shown or reset, callbacks to the phone window manager to notify
+ * it of when the keyguard is showing, and events from the keyguard view itself
+ * stating that the keyguard was succesfully unlocked.
+ *
+ * Note that the keyguard view is shown when the screen is off (as appropriate)
+ * so that once the screen comes on, it will be ready immediately.
+ *
+ * Example queries about the keyguard:
+ * - is {movement, key} one that should wake the keygaurd?
+ * - is the keyguard showing?
+ * - are input events restricted due to the state of the keyguard?
+ *
+ * Callbacks to the phone window manager:
+ * - the keyguard is showing
+ *
+ * Example external events that translate to keyguard view changes:
+ * - screen turned off -> reset the keyguard, and show it so it will be ready
+ * next time the screen turns on
+ * - keyboard is slid open -> if the keyguard is not secure, hide it
+ *
+ * Events from the keyguard view:
+ * - user succesfully unlocked keyguard -> hide keyguard view, and no longer
+ * restrict input events.
+ *
+ * Note: in addition to normal power managment events that effect the state of
+ * whether the keyguard should be showing, external apps and services may request
+ * that the keyguard be disabled via {@link #setKeyguardEnabled(boolean)}. When
+ * false, this will override all other conditions for turning on the keyguard.
+ *
+ * Threading and synchronization:
+ * This class is created by the initialization routine of the {@link android.view.WindowManagerPolicy},
+ * and runs on its thread. The keyguard UI is created from that thread in the
+ * constructor of this class. The apis may be called from other threads, including the
+ * {@link com.android.server.input.InputManagerService}'s and {@link android.view.WindowManager}'s.
+ * Therefore, methods on this class are synchronized, and any action that is pointed
+ * directly to the keyguard UI is posted to a {@link android.os.Handler} to ensure it is taken on the UI
+ * thread of the keyguard.
+ */
+public class KeyguardViewMediator {
+ private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
+ final static boolean DEBUG = false;
+ private static final boolean ENABLE_ANALYTICS = Build.IS_DEBUGGABLE;
+ private final static boolean DBG_WAKE = false;
+
+ private final static String TAG = "KeyguardViewMediator";
+
+ private static final String DELAYED_KEYGUARD_ACTION =
+ "com.android.internal.policy.impl.PhoneWindowManager.DELAYED_KEYGUARD";
+
+ // used for handler messages
+ private static final int SHOW = 2;
+ private static final int HIDE = 3;
+ private static final int RESET = 4;
+ private static final int VERIFY_UNLOCK = 5;
+ private static final int NOTIFY_SCREEN_OFF = 6;
+ private static final int NOTIFY_SCREEN_ON = 7;
+ private static final int KEYGUARD_DONE = 9;
+ private static final int KEYGUARD_DONE_DRAWING = 10;
+ private static final int KEYGUARD_DONE_AUTHENTICATING = 11;
+ private static final int SET_OCCLUDED = 12;
+ private static final int KEYGUARD_TIMEOUT = 13;
+ private static final int DISMISS = 17;
+
+ /**
+ * The default amount of time we stay awake (used for all key input)
+ */
+ public static final int AWAKE_INTERVAL_DEFAULT_MS = 10000;
+
+ /**
+ * How long to wait after the screen turns off due to timeout before
+ * turning on the keyguard (i.e, the user has this much time to turn
+ * the screen back on without having to face the keyguard).
+ */
+ private static final int KEYGUARD_LOCK_AFTER_DELAY_DEFAULT = 5000;
+
+ /**
+ * How long we'll wait for the {@link ViewMediatorCallback#keyguardDoneDrawing()}
+ * callback before unblocking a call to {@link #setKeyguardEnabled(boolean)}
+ * that is reenabling the keyguard.
+ */
+ private static final int KEYGUARD_DONE_DRAWING_TIMEOUT_MS = 2000;
+
+ /**
+ * Allow the user to expand the status bar when the keyguard is engaged
+ * (without a pattern or password).
+ */
+ private static final boolean ENABLE_INSECURE_STATUS_BAR_EXPAND = true;
+
+ /**
+ * Allow the user to expand the status bar when a SECURE keyguard is engaged
+ * and {@link android.provider.Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS} is set
+ * (private notifications will be masked).
+ */
+ private static final boolean ENABLE_SECURE_STATUS_BAR_EXPAND = true;
+
+ /**
+ * Default value of {@link android.provider.Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS}.
+ */
+ private static final boolean ALLOW_NOTIFICATIONS_DEFAULT = false;
+
+ /**
+ * Secure setting whether analytics are collected on the keyguard.
+ */
+ private static final String KEYGUARD_ANALYTICS_SETTING = "keyguard_analytics";
+
+ /** The stream type that the lock sounds are tied to. */
+ private int mMasterStreamType;
+
+ private Context mContext;
+ private AlarmManager mAlarmManager;
+ private AudioManager mAudioManager;
+ private StatusBarManager mStatusBarManager;
+ private boolean mSwitchingUser;
+
+ private boolean mSystemReady;
+
+ // Whether the next call to playSounds() should be skipped. Defaults to
+ // true because the first lock (on boot) should be silent.
+ private boolean mSuppressNextLockSound = true;
+
+
+ /** High level access to the power manager for WakeLocks */
+ private PowerManager mPM;
+
+ /** UserManager for querying number of users */
+ private UserManager mUserManager;
+
+ /** SearchManager for determining whether or not search assistant is available */
+ private SearchManager mSearchManager;
+
+ /**
+ * Used to keep the device awake while to ensure the keyguard finishes opening before
+ * we sleep.
+ */
+ private PowerManager.WakeLock mShowKeyguardWakeLock;
+
+ private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+
+ private final KeyguardAnalytics mKeyguardAnalytics;
+
+ // these are protected by synchronized (this)
+
+ /**
+ * External apps (like the phone app) can tell us to disable the keygaurd.
+ */
+ private boolean mExternallyEnabled = true;
+
+ /**
+ * Remember if an external call to {@link #setKeyguardEnabled} with value
+ * false caused us to hide the keyguard, so that we need to reshow it once
+ * the keygaurd is reenabled with another call with value true.
+ */
+ private boolean mNeedToReshowWhenReenabled = false;
+
+ // cached value of whether we are showing (need to know this to quickly
+ // answer whether the input should be restricted)
+ private boolean mShowing;
+
+ // true if the keyguard is hidden by another window
+ private boolean mOccluded = false;
+
+ /**
+ * Helps remember whether the screen has turned on since the last time
+ * it turned off due to timeout. see {@link #onScreenTurnedOff(int)}
+ */
+ private int mDelayedShowingSequence;
+
+ /**
+ * If the user has disabled the keyguard, then requests to exit, this is
+ * how we'll ultimately let them know whether it was successful. We use this
+ * var being non-null as an indicator that there is an in progress request.
+ */
+ private IKeyguardExitCallback mExitSecureCallback;
+
+ // the properties of the keyguard
+
+ private KeyguardUpdateMonitor mUpdateMonitor;
+
+ private boolean mScreenOn;
+
+ // last known state of the cellular connection
+ private String mPhoneState = TelephonyManager.EXTRA_STATE_IDLE;
+
+ /**
+ * we send this intent when the keyguard is dismissed.
+ */
+ private static final Intent USER_PRESENT_INTENT = new Intent(Intent.ACTION_USER_PRESENT)
+ .addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
+ | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+
+ /**
+ * {@link #setKeyguardEnabled} waits on this condition when it reenables
+ * the keyguard.
+ */
+ private boolean mWaitingUntilKeyguardVisible = false;
+ private LockPatternUtils mLockPatternUtils;
+ private boolean mKeyguardDonePending = false;
+
+ private SoundPool mLockSounds;
+ private int mLockSoundId;
+ private int mUnlockSoundId;
+ private int mLockSoundStreamId;
+
+ /**
+ * Tracks value of {@link android.provider.Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS}.
+ */
+ private boolean mAllowNotificationsWhenSecure;
+
+ /**
+ * The volume applied to the lock/unlock sounds.
+ */
+ private final float mLockSoundVolume;
+
+ /**
+ * For managing external displays
+ */
+ private KeyguardDisplayManager mKeyguardDisplayManager;
+
+ KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
+
+ @Override
+ public void onUserSwitching(int userId) {
+ // Note that the mLockPatternUtils user has already been updated from setCurrentUser.
+ // We need to force a reset of the views, since lockNow (called by
+ // ActivityManagerService) will not reconstruct the keyguard if it is already showing.
+ synchronized (KeyguardViewMediator.this) {
+ mSwitchingUser = true;
+ resetStateLocked();
+ adjustStatusBarLocked();
+ // When we switch users we want to bring the new user to the biometric unlock even
+ // if the current user has gone to the backup.
+ KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
+ }
+ }
+
+ @Override
+ public void onUserSwitchComplete(int userId) {
+ mSwitchingUser = false;
+ }
+
+ @Override
+ public void onUserRemoved(int userId) {
+ mLockPatternUtils.removeUser(userId);
+ MultiUserAvatarCache.getInstance().clear(userId);
+ }
+
+ @Override
+ public void onUserInfoChanged(int userId) {
+ MultiUserAvatarCache.getInstance().clear(userId);
+ }
+
+ @Override
+ public void onPhoneStateChanged(int phoneState) {
+ synchronized (KeyguardViewMediator.this) {
+ if (TelephonyManager.CALL_STATE_IDLE == phoneState // call ending
+ && !mScreenOn // 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();
+ }
+
+ @Override
+ public void onDeviceProvisioned() {
+ sendUserPresentBroadcast();
+ }
+
+ @Override
+ public void onSimStateChanged(IccCardConstants.State simState) {
+ if (DEBUG) Log.d(TAG, "onSimStateChanged: " + simState);
+
+ switch (simState) {
+ case NOT_READY:
+ case ABSENT:
+ // only force lock screen in case of missing sim if user hasn't
+ // gone through setup wizard
+ synchronized (this) {
+ if (!mUpdateMonitor.isDeviceProvisioned()) {
+ if (!isShowing()) {
+ if (DEBUG) Log.d(TAG, "ICC_ABSENT isn't showing,"
+ + " we need to show the keyguard since the "
+ + "device isn't provisioned yet.");
+ doKeyguardLocked(null);
+ } else {
+ resetStateLocked();
+ }
+ }
+ }
+ break;
+ case PIN_REQUIRED:
+ case PUK_REQUIRED:
+ synchronized (this) {
+ if (!isShowing()) {
+ if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_LOCKED and keygaurd isn't "
+ + "showing; need to show keyguard so user can enter sim pin");
+ doKeyguardLocked(null);
+ } else {
+ resetStateLocked();
+ }
+ }
+ break;
+ case PERM_DISABLED:
+ synchronized (this) {
+ if (!isShowing()) {
+ if (DEBUG) Log.d(TAG, "PERM_DISABLED and "
+ + "keygaurd isn't showing.");
+ doKeyguardLocked(null);
+ } else {
+ if (DEBUG) Log.d(TAG, "PERM_DISABLED, resetStateLocked to"
+ + "show permanently disabled message in lockscreen.");
+ resetStateLocked();
+ }
+ }
+ break;
+ case READY:
+ synchronized (this) {
+ if (isShowing()) {
+ resetStateLocked();
+ }
+ }
+ break;
+ }
+ }
+
+ };
+
+ ViewMediatorCallback mViewMediatorCallback = new ViewMediatorCallback() {
+
+ public void userActivity() {
+ KeyguardViewMediator.this.userActivity();
+ }
+
+ public void userActivity(long holdMs) {
+ KeyguardViewMediator.this.userActivity(holdMs);
+ }
+
+ public void keyguardDone(boolean authenticated) {
+ KeyguardViewMediator.this.keyguardDone(authenticated, true);
+ }
+
+ public void keyguardDoneDrawing() {
+ mHandler.sendEmptyMessage(KEYGUARD_DONE_DRAWING);
+ }
+
+ @Override
+ public void setNeedsInput(boolean needsInput) {
+ mStatusBarKeyguardViewManager.setNeedsInput(needsInput);
+ }
+
+ @Override
+ public void onUserActivityTimeoutChanged() {
+ mStatusBarKeyguardViewManager.updateUserActivityTimeout();
+ }
+
+ @Override
+ public void keyguardDonePending() {
+ mKeyguardDonePending = true;
+ }
+
+ @Override
+ public void keyguardGone() {
+ mKeyguardDisplayManager.hide();
+ }
+ };
+
+ private void userActivity() {
+ userActivity(AWAKE_INTERVAL_DEFAULT_MS);
+ }
+
+ public void userActivity(long holdMs) {
+ // We ignore the hold time. Eventually we should remove it.
+ // Instead, the keyguard window has an explicit user activity timeout set on it.
+ mPM.userActivity(SystemClock.uptimeMillis(), false);
+ }
+
+ /**
+ * Construct a KeyguardViewMediator
+ * @param context
+ * @param lockPatternUtils optional mock interface for LockPatternUtils
+ */
+ public KeyguardViewMediator(Context context, LockPatternUtils lockPatternUtils) {
+ mContext = context;
+ mPM = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
+ mShowKeyguardWakeLock.setReferenceCounted(false);
+
+ mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DELAYED_KEYGUARD_ACTION));
+
+ mKeyguardDisplayManager = new KeyguardDisplayManager(context);
+
+ mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+
+ mUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
+
+ mLockPatternUtils = lockPatternUtils != null
+ ? lockPatternUtils : new LockPatternUtils(mContext);
+ mLockPatternUtils.setCurrentUser(UserHandle.USER_OWNER);
+
+ // Assume keyguard is showing (unless it's disabled) until we know for sure...
+ mShowing = (mUpdateMonitor.isDeviceProvisioned() || mLockPatternUtils.isSecure())
+ && !mLockPatternUtils.isLockScreenDisabled();
+
+ mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(mContext, mViewMediatorCallback,
+ lockPatternUtils);
+ WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+ final ContentResolver cr = mContext.getContentResolver();
+
+ if (ENABLE_ANALYTICS && !LockPatternUtils.isSafeModeEnabled() &&
+ Settings.Secure.getInt(cr, KEYGUARD_ANALYTICS_SETTING, 0) == 1) {
+ mKeyguardAnalytics = new KeyguardAnalytics(context, new SessionTypeAdapter() {
+
+ @Override
+ public int getSessionType() {
+ return mLockPatternUtils.isSecure() ? Session.TYPE_KEYGUARD_SECURE
+ : Session.TYPE_KEYGUARD_INSECURE;
+ }
+ }, new File(mContext.getCacheDir(), "keyguard_analytics.bin"));
+ } else {
+ mKeyguardAnalytics = null;
+ }
+
+ mScreenOn = mPM.isScreenOn();
+
+ mLockSounds = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0);
+ String soundPath = Settings.Global.getString(cr, Settings.Global.LOCK_SOUND);
+ if (soundPath != null) {
+ mLockSoundId = mLockSounds.load(soundPath, 1);
+ }
+ if (soundPath == null || mLockSoundId == 0) {
+ Log.w(TAG, "failed to load lock sound from " + soundPath);
+ }
+ soundPath = Settings.Global.getString(cr, Settings.Global.UNLOCK_SOUND);
+ if (soundPath != null) {
+ mUnlockSoundId = mLockSounds.load(soundPath, 1);
+ }
+ if (soundPath == null || mUnlockSoundId == 0) {
+ Log.w(TAG, "failed to load unlock sound from " + soundPath);
+ }
+ int lockSoundDefaultAttenuation = context.getResources().getInteger(
+ com.android.internal.R.integer.config_lockSoundVolumeDb);
+ mLockSoundVolume = (float)Math.pow(10, (float)lockSoundDefaultAttenuation/20);
+ }
+
+ /**
+ * Let us know that the system is ready after startup.
+ */
+ public void onSystemReady() {
+ mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
+ synchronized (this) {
+ if (DEBUG) Log.d(TAG, "onSystemReady");
+ mSystemReady = true;
+ mUpdateMonitor.registerCallback(mUpdateCallback);
+
+ // Suppress biometric unlock right after boot until things have settled if it is the
+ // selected security method, otherwise unsuppress it. It must be unsuppressed if it is
+ // not the selected security method for the following reason: if the user starts
+ // without a screen lock selected, the biometric unlock would be suppressed the first
+ // time they try to use it.
+ //
+ // Note that the biometric unlock will still not show if it is not the selected method.
+ // Calling setAlternateUnlockEnabled(true) simply says don't suppress it if it is the
+ // selected method.
+ if (mLockPatternUtils.usingBiometricWeak()
+ && mLockPatternUtils.isBiometricWeakInstalled()) {
+ if (DEBUG) Log.d(TAG, "suppressing biometric unlock during boot");
+ mUpdateMonitor.setAlternateUnlockEnabled(false);
+ } else {
+ mUpdateMonitor.setAlternateUnlockEnabled(true);
+ }
+
+ doKeyguardLocked(null);
+ }
+ // Most services aren't available until the system reaches the ready state, so we
+ // send it here when the device first boots.
+ maybeSendUserPresentBroadcast();
+ }
+
+ /**
+ * Called to let us know the screen was turned off.
+ * @param why either {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_USER},
+ * {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or
+ * {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}.
+ */
+ public void onScreenTurnedOff(int why) {
+ synchronized (this) {
+ mScreenOn = false;
+ if (DEBUG) Log.d(TAG, "onScreenTurnedOff(" + why + ")");
+
+ mKeyguardDonePending = false;
+
+ // Lock immediately based on setting if secure (user has a pin/pattern/password).
+ // This also "locks" the device when not secure to provide easy access to the
+ // camera while preventing unwanted input.
+ final boolean lockImmediately =
+ mLockPatternUtils.getPowerButtonInstantlyLocks() || !mLockPatternUtils.isSecure();
+
+ if (mExitSecureCallback != null) {
+ if (DEBUG) Log.d(TAG, "pending exit secure callback cancelled");
+ try {
+ mExitSecureCallback.onKeyguardExitResult(false);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
+ }
+ mExitSecureCallback = null;
+ if (!mExternallyEnabled) {
+ hideLocked();
+ }
+ } else if (mShowing) {
+ notifyScreenOffLocked();
+ resetStateLocked();
+ } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT
+ || (why == WindowManagerPolicy.OFF_BECAUSE_OF_USER && !lockImmediately)) {
+ doKeyguardLaterLocked();
+ } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) {
+ // Do not enable the keyguard if the prox sensor forced the screen off.
+ } else {
+ doKeyguardLocked(null);
+ }
+ if (ENABLE_ANALYTICS && mKeyguardAnalytics != null) {
+ mKeyguardAnalytics.getCallback().onScreenOff();
+ }
+ }
+ KeyguardUpdateMonitor.getInstance(mContext).dispatchScreenTurndOff(why);
+ }
+
+ private void doKeyguardLaterLocked() {
+ // if the screen turned off because of timeout or the user hit the power button
+ // and we don't need to lock immediately, set an alarm
+ // to enable it a little bit later (i.e, give the user a chance
+ // to turn the screen back on within a certain window without
+ // having to unlock the screen)
+ final ContentResolver cr = mContext.getContentResolver();
+
+ // From DisplaySettings
+ long displayTimeout = Settings.System.getInt(cr, SCREEN_OFF_TIMEOUT,
+ KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT);
+
+ // From SecuritySettings
+ final long lockAfterTimeout = Settings.Secure.getInt(cr,
+ Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
+ KEYGUARD_LOCK_AFTER_DELAY_DEFAULT);
+
+ // From DevicePolicyAdmin
+ final long policyTimeout = mLockPatternUtils.getDevicePolicyManager()
+ .getMaximumTimeToLock(null, mLockPatternUtils.getCurrentUser());
+
+ long timeout;
+ if (policyTimeout > 0) {
+ // policy in effect. Make sure we don't go beyond policy limit.
+ displayTimeout = Math.max(displayTimeout, 0); // ignore negative values
+ timeout = Math.min(policyTimeout - displayTimeout, lockAfterTimeout);
+ } else {
+ timeout = lockAfterTimeout;
+ }
+
+ if (timeout <= 0) {
+ // Lock now
+ mSuppressNextLockSound = true;
+ doKeyguardLocked(null);
+ } else {
+ // Lock in the future
+ long when = SystemClock.elapsedRealtime() + timeout;
+ Intent intent = new Intent(DELAYED_KEYGUARD_ACTION);
+ intent.putExtra("seq", mDelayedShowingSequence);
+ PendingIntent sender = PendingIntent.getBroadcast(mContext,
+ 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, sender);
+ if (DEBUG) Log.d(TAG, "setting alarm to turn off keyguard, seq = "
+ + mDelayedShowingSequence);
+ }
+ }
+
+ private void cancelDoKeyguardLaterLocked() {
+ mDelayedShowingSequence++;
+ }
+
+ /**
+ * Let's us know the screen was turned on.
+ */
+ public void onScreenTurnedOn(IKeyguardShowCallback callback) {
+ synchronized (this) {
+ mScreenOn = true;
+ cancelDoKeyguardLaterLocked();
+ if (DEBUG) Log.d(TAG, "onScreenTurnedOn, seq = " + mDelayedShowingSequence);
+ if (callback != null) {
+ notifyScreenOnLocked(callback);
+ }
+ }
+ KeyguardUpdateMonitor.getInstance(mContext).dispatchScreenTurnedOn();
+ maybeSendUserPresentBroadcast();
+ }
+
+ private void maybeSendUserPresentBroadcast() {
+ if (mSystemReady && mLockPatternUtils.isLockScreenDisabled()
+ && !mUserManager.isUserSwitcherEnabled()) {
+ // Lock screen is disabled because the user has set the preference to "None".
+ // In this case, send out ACTION_USER_PRESENT here instead of in
+ // handleKeyguardDone()
+ sendUserPresentBroadcast();
+ }
+ }
+
+ /**
+ * A dream started. We should lock after the usual screen-off lock timeout but only
+ * if there is a secure lock pattern.
+ */
+ public void onDreamingStarted() {
+ synchronized (this) {
+ if (mScreenOn && mLockPatternUtils.isSecure()) {
+ doKeyguardLaterLocked();
+ }
+ }
+ }
+
+ /**
+ * A dream stopped.
+ */
+ public void onDreamingStopped() {
+ synchronized (this) {
+ if (mScreenOn) {
+ cancelDoKeyguardLaterLocked();
+ }
+ }
+ }
+
+ /**
+ * Same semantics as {@link android.view.WindowManagerPolicy#enableKeyguard}; provide
+ * a way for external stuff to override normal keyguard behavior. For instance
+ * the phone app disables the keyguard when it receives incoming calls.
+ */
+ public void setKeyguardEnabled(boolean enabled) {
+ synchronized (this) {
+ if (DEBUG) Log.d(TAG, "setKeyguardEnabled(" + enabled + ")");
+
+ mExternallyEnabled = enabled;
+
+ if (!enabled && mShowing) {
+ if (mExitSecureCallback != null) {
+ if (DEBUG) Log.d(TAG, "in process of verifyUnlock request, ignoring");
+ // we're in the process of handling a request to verify the user
+ // can get past the keyguard. ignore extraneous requests to disable / reenable
+ return;
+ }
+
+ // hiding keyguard that is showing, remember to reshow later
+ if (DEBUG) Log.d(TAG, "remembering to reshow, hiding keyguard, "
+ + "disabling status bar expansion");
+ mNeedToReshowWhenReenabled = true;
+ hideLocked();
+ } else if (enabled && mNeedToReshowWhenReenabled) {
+ // reenabled after previously hidden, reshow
+ if (DEBUG) Log.d(TAG, "previously hidden, reshowing, reenabling "
+ + "status bar expansion");
+ mNeedToReshowWhenReenabled = false;
+
+ if (mExitSecureCallback != null) {
+ if (DEBUG) Log.d(TAG, "onKeyguardExitResult(false), resetting");
+ try {
+ mExitSecureCallback.onKeyguardExitResult(false);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
+ }
+ mExitSecureCallback = null;
+ resetStateLocked();
+ } else {
+ showLocked(null);
+
+ // block until we know the keygaurd is done drawing (and post a message
+ // to unblock us after a timeout so we don't risk blocking too long
+ // and causing an ANR).
+ mWaitingUntilKeyguardVisible = true;
+ mHandler.sendEmptyMessageDelayed(KEYGUARD_DONE_DRAWING, KEYGUARD_DONE_DRAWING_TIMEOUT_MS);
+ if (DEBUG) Log.d(TAG, "waiting until mWaitingUntilKeyguardVisible is false");
+ while (mWaitingUntilKeyguardVisible) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ if (DEBUG) Log.d(TAG, "done waiting for mWaitingUntilKeyguardVisible");
+ }
+ }
+ }
+ }
+
+ /**
+ * @see android.app.KeyguardManager#exitKeyguardSecurely
+ */
+ public void verifyUnlock(IKeyguardExitCallback callback) {
+ synchronized (this) {
+ if (DEBUG) Log.d(TAG, "verifyUnlock");
+ if (!mUpdateMonitor.isDeviceProvisioned()) {
+ // don't allow this api when the device isn't provisioned
+ if (DEBUG) Log.d(TAG, "ignoring because device isn't provisioned");
+ try {
+ callback.onKeyguardExitResult(false);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
+ }
+ } else if (mExternallyEnabled) {
+ // this only applies when the user has externally disabled the
+ // keyguard. this is unexpected and means the user is not
+ // using the api properly.
+ Log.w(TAG, "verifyUnlock called when not externally disabled");
+ try {
+ callback.onKeyguardExitResult(false);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
+ }
+ } else if (mExitSecureCallback != null) {
+ // already in progress with someone else
+ try {
+ callback.onKeyguardExitResult(false);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
+ }
+ } else {
+ mExitSecureCallback = callback;
+ verifyUnlockLocked();
+ }
+ }
+ }
+
+ /**
+ * Is the keyguard currently showing?
+ */
+ public boolean isShowing() {
+ return mShowing;
+ }
+
+ public boolean isOccluded() {
+ return mOccluded;
+ }
+
+ /**
+ * Is the keyguard currently showing and not being force hidden?
+ */
+ public boolean isShowingAndNotOccluded() {
+ return mShowing && !mOccluded;
+ }
+
+ /**
+ * Notify us when the keyguard is occluded by another window
+ */
+ public void setOccluded(boolean isOccluded) {
+ if (DEBUG) Log.d(TAG, "setOccluded " + isOccluded);
+ mUpdateMonitor.sendKeyguardVisibilityChanged(!isOccluded);
+ mHandler.removeMessages(SET_OCCLUDED);
+ Message msg = mHandler.obtainMessage(SET_OCCLUDED, (isOccluded ? 1 : 0), 0);
+ mHandler.sendMessage(msg);
+ }
+
+ /**
+ * Handles SET_OCCLUDED message sent by setOccluded()
+ */
+ private void handleSetOccluded(boolean isOccluded) {
+ synchronized (KeyguardViewMediator.this) {
+ if (mOccluded != isOccluded) {
+ mOccluded = isOccluded;
+ mStatusBarKeyguardViewManager.setOccluded(isOccluded);
+ updateActivityLockScreenState();
+ adjustStatusBarLocked();
+ }
+ if (ENABLE_ANALYTICS && mKeyguardAnalytics != null) {
+ mKeyguardAnalytics.getCallback().onSetOccluded(isOccluded);
+ }
+ }
+ }
+
+ /**
+ * Used by PhoneWindowManager to enable the keyguard due to a user activity timeout.
+ * This must be safe to call from any thread and with any window manager locks held.
+ */
+ public void doKeyguardTimeout(Bundle options) {
+ mHandler.removeMessages(KEYGUARD_TIMEOUT);
+ Message msg = mHandler.obtainMessage(KEYGUARD_TIMEOUT, options);
+ mHandler.sendMessage(msg);
+ }
+
+ /**
+ * Given the state of the keyguard, is the input restricted?
+ * Input is restricted when the keyguard is showing, or when the keyguard
+ * was suppressed by an app that disabled the keyguard or we haven't been provisioned yet.
+ */
+ public boolean isInputRestricted() {
+ return mShowing || mNeedToReshowWhenReenabled || !mUpdateMonitor.isDeviceProvisioned();
+ }
+
+ /**
+ * Enable the keyguard if the settings are appropriate.
+ */
+ private void doKeyguardLocked(Bundle options) {
+ // if another app is disabling us, don't show
+ 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
+ return;
+ }
+
+ // note whether notification access should be allowed
+ mAllowNotificationsWhenSecure = ENABLE_SECURE_STATUS_BAR_EXPAND
+ && 0 != Settings.Global.getInt(
+ mContext.getContentResolver(),
+ Settings.Global.LOCK_SCREEN_SHOW_NOTIFICATIONS,
+ ALLOW_NOTIFICATIONS_DEFAULT ? 1 : 0);
+
+ // if the keyguard is already showing, don't bother
+ if (mStatusBarKeyguardViewManager.isShowing()) {
+ if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
+ return;
+ }
+
+ // if the setup wizard hasn't run yet, don't show
+ final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim",
+ false);
+ final boolean provisioned = mUpdateMonitor.isDeviceProvisioned();
+ final IccCardConstants.State state = mUpdateMonitor.getSimState();
+ final boolean lockedOrMissing = state.isPinLocked()
+ || ((state == IccCardConstants.State.ABSENT
+ || state == IccCardConstants.State.PERM_DISABLED)
+ && requireSim);
+
+ if (!lockedOrMissing && !provisioned) {
+ if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned"
+ + " and the sim is not locked or missing");
+ return;
+ }
+
+ if (!mUserManager.isUserSwitcherEnabled()
+ && mLockPatternUtils.isLockScreenDisabled() && !lockedOrMissing) {
+ if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
+ return;
+ }
+
+ if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
+ showLocked(options);
+ }
+
+ /**
+ * Dismiss the keyguard through the security layers.
+ */
+ public void handleDismiss() {
+ if (mShowing && !mOccluded) {
+ mStatusBarKeyguardViewManager.dismiss();
+ }
+ }
+
+ public void dismiss() {
+ mHandler.sendEmptyMessage(DISMISS);
+ }
+
+ /**
+ * Send message to keyguard telling it to reset its state.
+ * @see #handleReset
+ */
+ private void resetStateLocked() {
+ if (DEBUG) Log.e(TAG, "resetStateLocked");
+ Message msg = mHandler.obtainMessage(RESET);
+ mHandler.sendMessage(msg);
+ }
+
+ /**
+ * Send message to keyguard telling it to verify unlock
+ * @see #handleVerifyUnlock()
+ */
+ private void verifyUnlockLocked() {
+ if (DEBUG) Log.d(TAG, "verifyUnlockLocked");
+ mHandler.sendEmptyMessage(VERIFY_UNLOCK);
+ }
+
+
+ /**
+ * Send a message to keyguard telling it the screen just turned on.
+ * @see #onScreenTurnedOff(int)
+ * @see #handleNotifyScreenOff
+ */
+ private void notifyScreenOffLocked() {
+ if (DEBUG) Log.d(TAG, "notifyScreenOffLocked");
+ mHandler.sendEmptyMessage(NOTIFY_SCREEN_OFF);
+ }
+
+ /**
+ * Send a message to keyguard telling it the screen just turned on.
+ * @see #onScreenTurnedOn
+ * @see #handleNotifyScreenOn
+ */
+ private void notifyScreenOnLocked(IKeyguardShowCallback result) {
+ if (DEBUG) Log.d(TAG, "notifyScreenOnLocked");
+ Message msg = mHandler.obtainMessage(NOTIFY_SCREEN_ON, result);
+ mHandler.sendMessage(msg);
+ }
+
+ /**
+ * Send message to keyguard telling it to show itself
+ * @see #handleShow
+ */
+ private void showLocked(Bundle options) {
+ if (DEBUG) Log.d(TAG, "showLocked");
+ // ensure we stay awake until we are finished displaying the keyguard
+ mShowKeyguardWakeLock.acquire();
+ Message msg = mHandler.obtainMessage(SHOW, options);
+ mHandler.sendMessage(msg);
+ }
+
+ /**
+ * Send message to keyguard telling it to hide itself
+ * @see #handleHide()
+ */
+ private void hideLocked() {
+ if (DEBUG) Log.d(TAG, "hideLocked");
+ Message msg = mHandler.obtainMessage(HIDE);
+ mHandler.sendMessage(msg);
+ }
+
+ public boolean isSecure() {
+ return mLockPatternUtils.isSecure()
+ || KeyguardUpdateMonitor.getInstance(mContext).isSimPinSecure();
+ }
+
+ /**
+ * Update the newUserId. Call while holding WindowManagerService lock.
+ * NOTE: Should only be called by KeyguardViewMediator in response to the user id changing.
+ *
+ * @param newUserId The id of the incoming user.
+ */
+ public void setCurrentUser(int newUserId) {
+ mLockPatternUtils.setCurrentUser(newUserId);
+ }
+
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (DELAYED_KEYGUARD_ACTION.equals(intent.getAction())) {
+ final int sequence = intent.getIntExtra("seq", 0);
+ if (DEBUG) Log.d(TAG, "received DELAYED_KEYGUARD_ACTION with seq = "
+ + sequence + ", mDelayedShowingSequence = " + mDelayedShowingSequence);
+ synchronized (KeyguardViewMediator.this) {
+ if (mDelayedShowingSequence == sequence) {
+ // Don't play lockscreen SFX if the screen went off due to timeout.
+ mSuppressNextLockSound = true;
+ doKeyguardLocked(null);
+ }
+ }
+ }
+ }
+ };
+
+ public void keyguardDone(boolean authenticated, boolean wakeup) {
+ if (DEBUG) Log.d(TAG, "keyguardDone(" + authenticated + ")");
+ EventLog.writeEvent(70000, 2);
+ synchronized (this) {
+ mKeyguardDonePending = false;
+ }
+ Message msg = mHandler.obtainMessage(KEYGUARD_DONE, authenticated ? 1 : 0, wakeup ? 1 : 0);
+ mHandler.sendMessage(msg);
+ }
+
+ /**
+ * This handler will be associated with the policy thread, which will also
+ * be the UI thread of the keyguard. Since the apis of the policy, and therefore
+ * this class, can be called by other threads, any action that directly
+ * interacts with the keyguard ui should be posted to this handler, rather
+ * than called directly.
+ */
+ private Handler mHandler = new Handler(Looper.myLooper(), null, true /*async*/) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case SHOW:
+ handleShow((Bundle) msg.obj);
+ break;
+ case HIDE:
+ handleHide();
+ break;
+ case RESET:
+ handleReset();
+ break;
+ case VERIFY_UNLOCK:
+ handleVerifyUnlock();
+ break;
+ case NOTIFY_SCREEN_OFF:
+ handleNotifyScreenOff();
+ break;
+ case NOTIFY_SCREEN_ON:
+ handleNotifyScreenOn((IKeyguardShowCallback) msg.obj);
+ break;
+ case KEYGUARD_DONE:
+ handleKeyguardDone(msg.arg1 != 0, msg.arg2 != 0);
+ break;
+ case KEYGUARD_DONE_DRAWING:
+ handleKeyguardDoneDrawing();
+ break;
+ case KEYGUARD_DONE_AUTHENTICATING:
+ keyguardDone(true, true);
+ break;
+ case SET_OCCLUDED:
+ handleSetOccluded(msg.arg1 != 0);
+ break;
+ case KEYGUARD_TIMEOUT:
+ synchronized (KeyguardViewMediator.this) {
+ doKeyguardLocked((Bundle) msg.obj);
+ }
+ break;
+ case DISMISS:
+ handleDismiss();
+ break;
+ }
+ }
+ };
+
+ /**
+ * @see #keyguardDone
+ * @see #KEYGUARD_DONE
+ */
+ private void handleKeyguardDone(boolean authenticated, boolean wakeup) {
+ if (DEBUG) Log.d(TAG, "handleKeyguardDone");
+
+ if (authenticated) {
+ mUpdateMonitor.clearFailedUnlockAttempts();
+ }
+
+ if (mExitSecureCallback != null) {
+ try {
+ mExitSecureCallback.onKeyguardExitResult(authenticated);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call onKeyguardExitResult(" + authenticated + ")", e);
+ }
+
+ mExitSecureCallback = null;
+
+ if (authenticated) {
+ // after succesfully exiting securely, no need to reshow
+ // the keyguard when they've released the lock
+ mExternallyEnabled = true;
+ mNeedToReshowWhenReenabled = false;
+ }
+ }
+
+ handleHide();
+ sendUserPresentBroadcast();
+ }
+
+ private void sendUserPresentBroadcast() {
+ final UserHandle currentUser = new UserHandle(mLockPatternUtils.getCurrentUser());
+ mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, currentUser);
+ }
+
+ /**
+ * @see #keyguardDone
+ * @see #KEYGUARD_DONE_DRAWING
+ */
+ private void handleKeyguardDoneDrawing() {
+ synchronized(this) {
+ if (DEBUG) Log.d(TAG, "handleKeyguardDoneDrawing");
+ if (mWaitingUntilKeyguardVisible) {
+ if (DEBUG) Log.d(TAG, "handleKeyguardDoneDrawing: notifying mWaitingUntilKeyguardVisible");
+ mWaitingUntilKeyguardVisible = false;
+ notifyAll();
+
+ // there will usually be two of these sent, one as a timeout, and one
+ // as a result of the callback, so remove any remaining messages from
+ // the queue
+ mHandler.removeMessages(KEYGUARD_DONE_DRAWING);
+ }
+ }
+ }
+
+ private void playSounds(boolean locked) {
+ // User feedback for keyguard.
+
+ if (mSuppressNextLockSound) {
+ mSuppressNextLockSound = false;
+ return;
+ }
+
+ final ContentResolver cr = mContext.getContentResolver();
+ if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1) {
+ final int whichSound = locked
+ ? mLockSoundId
+ : mUnlockSoundId;
+ mLockSounds.stop(mLockSoundStreamId);
+ // Init mAudioManager
+ if (mAudioManager == null) {
+ mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ if (mAudioManager == null) return;
+ mMasterStreamType = mAudioManager.getMasterStreamType();
+ }
+ // If the stream is muted, don't play the sound
+ if (mAudioManager.isStreamMute(mMasterStreamType)) return;
+
+ mLockSoundStreamId = mLockSounds.play(whichSound,
+ mLockSoundVolume, mLockSoundVolume, 1/*priortiy*/, 0/*loop*/, 1.0f/*rate*/);
+ }
+ }
+
+ private void updateActivityLockScreenState() {
+ try {
+ ActivityManagerNative.getDefault().setLockScreenShown(mShowing && !mOccluded);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * Handle message sent by {@link #showLocked}.
+ * @see #SHOW
+ */
+ private void handleShow(Bundle options) {
+ synchronized (KeyguardViewMediator.this) {
+ if (!mSystemReady) {
+ if (DEBUG) Log.d(TAG, "ignoring handleShow because system is not ready.");
+ return;
+ } else {
+ if (DEBUG) Log.d(TAG, "handleShow");
+ }
+
+ mStatusBarKeyguardViewManager.show(options);
+ mShowing = true;
+ mKeyguardDonePending = false;
+ updateActivityLockScreenState();
+ adjustStatusBarLocked();
+ userActivity();
+ try {
+ ActivityManagerNative.getDefault().closeSystemDialogs("lock");
+ } catch (RemoteException e) {
+ }
+
+ // Do this at the end to not slow down display of the keyguard.
+ playSounds(true);
+
+ mShowKeyguardWakeLock.release();
+ }
+ mKeyguardDisplayManager.show();
+ }
+
+ /**
+ * Handle message sent by {@link #hideLocked()}
+ * @see #HIDE
+ */
+ private void handleHide() {
+ synchronized (KeyguardViewMediator.this) {
+ if (DEBUG) Log.d(TAG, "handleHide");
+
+ // only play "unlock" noises if not on a call (since the incall UI
+ // disables the keyguard)
+ if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) {
+ playSounds(false);
+ }
+
+ mStatusBarKeyguardViewManager.hide();
+ mShowing = false;
+ mKeyguardDonePending = false;
+ updateActivityLockScreenState();
+ adjustStatusBarLocked();
+ }
+ }
+
+ private void adjustStatusBarLocked() {
+ if (mStatusBarManager == null) {
+ mStatusBarManager = (StatusBarManager)
+ mContext.getSystemService(Context.STATUS_BAR_SERVICE);
+ }
+ if (mStatusBarManager == null) {
+ Log.w(TAG, "Could not get status bar manager");
+ } else {
+ // Disable aspects of the system/status/navigation bars that must not be re-enabled by
+ // windows that appear on top, ever
+ int flags = StatusBarManager.DISABLE_NONE;
+ if (mShowing) {
+ // Permanently disable components not available when keyguard is enabled
+ // (like recents). Temporary enable/disable (e.g. the "back" button) are
+ // done in KeyguardHostView.
+ flags |= StatusBarManager.DISABLE_RECENT;
+ if ((isSecure() && !mAllowNotificationsWhenSecure)
+ || !ENABLE_INSECURE_STATUS_BAR_EXPAND) {
+ // showing secure lockscreen; disable expanding.
+ flags |= StatusBarManager.DISABLE_EXPAND;
+ }
+ if (isSecure()) {
+ // showing secure lockscreen; disable ticker and switch private notifications
+ // to show their public versions, if available.
+ flags |= StatusBarManager.DISABLE_PRIVATE_NOTIFICATIONS;
+ }
+ if (!isAssistantAvailable()) {
+ flags |= StatusBarManager.DISABLE_SEARCH;
+ }
+ }
+
+ if (DEBUG) {
+ Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mOccluded=" + mOccluded
+ + " isSecure=" + isSecure() + " --> flags=0x" + Integer.toHexString(flags));
+ }
+
+ if (!(mContext instanceof Activity)) {
+ mStatusBarManager.disable(flags);
+ }
+ }
+ }
+
+ /**
+ * Handle message sent by {@link #resetStateLocked}
+ * @see #RESET
+ */
+ private void handleReset() {
+ synchronized (KeyguardViewMediator.this) {
+ if (DEBUG) Log.d(TAG, "handleReset");
+ mStatusBarKeyguardViewManager.reset();
+ }
+ }
+
+ /**
+ * Handle message sent by {@link #verifyUnlock}
+ * @see #VERIFY_UNLOCK
+ */
+ private void handleVerifyUnlock() {
+ synchronized (KeyguardViewMediator.this) {
+ if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
+ mStatusBarKeyguardViewManager.verifyUnlock();
+ mShowing = true;
+ updateActivityLockScreenState();
+ }
+ }
+
+ /**
+ * Handle message sent by {@link #notifyScreenOffLocked()}
+ * @see #NOTIFY_SCREEN_OFF
+ */
+ private void handleNotifyScreenOff() {
+ synchronized (KeyguardViewMediator.this) {
+ if (DEBUG) Log.d(TAG, "handleNotifyScreenOff");
+ mStatusBarKeyguardViewManager.onScreenTurnedOff();
+ }
+ }
+
+ /**
+ * Handle message sent by {@link #notifyScreenOnLocked}
+ * @see #NOTIFY_SCREEN_ON
+ */
+ private void handleNotifyScreenOn(IKeyguardShowCallback callback) {
+ synchronized (KeyguardViewMediator.this) {
+ if (DEBUG) Log.d(TAG, "handleNotifyScreenOn");
+ mStatusBarKeyguardViewManager.onScreenTurnedOn(callback);
+ }
+ }
+
+ public boolean isDismissable() {
+ return mKeyguardDonePending || !isSecure();
+ }
+
+ private boolean isAssistantAvailable() {
+ return mSearchManager != null
+ && mSearchManager.getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
+ }
+
+ public void onBootCompleted() {
+ mUpdateMonitor.dispatchBootCompleted();
+ }
+
+ public void registerStatusBar(PhoneStatusBar phoneStatusBar, ViewGroup container,
+ StatusBarWindowManager statusBarWindowManager) {
+ mStatusBarKeyguardViewManager.registerStatusBar(phoneStatusBar, container,
+ statusBarWindowManager);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 54e8815..73f1aa4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -22,11 +22,9 @@ import android.app.Notification;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -79,8 +77,6 @@ import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.SearchPanelView;
import com.android.systemui.SystemUI;
-import com.android.systemui.keyguard.KeyguardService;
-import com.android.systemui.keyguard.KeyguardStatusBarBinder;
import com.android.systemui.statusbar.phone.KeyguardTouchDelegate;
import java.util.ArrayList;
@@ -176,12 +172,6 @@ public abstract class BaseStatusBar extends SystemUI implements
protected int mZenMode;
- protected KeyguardStatusBarBinder mKeyguardService;
-
- public IStatusBarService getStatusBarService() {
- return mBarService;
- }
-
public boolean isDeviceProvisioned() {
return mDeviceProvisioned;
}
@@ -320,7 +310,6 @@ public abstract class BaseStatusBar extends SystemUI implements
createAndAddWindows();
- startKeyguardService();
disable(switches[0]);
setSystemUiVisibility(switches[1], 0xffffffff);
topAppWindowChanged(switches[2] != 0);
@@ -371,25 +360,6 @@ public abstract class BaseStatusBar extends SystemUI implements
updateRelatedUserCache();
}
- private void startKeyguardService() {
- Intent intent = new Intent(mContext, KeyguardService.class);
- intent.setAction(KeyguardService.ACTION_STATUS_BAR_BIND);
- if (!mContext.bindService(intent, new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- mKeyguardService = (KeyguardStatusBarBinder) service;
- mKeyguardService.register(mCommandQueue);
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- mKeyguardService = null;
- }
- }, Context.BIND_AUTO_CREATE)) {
- throw new RuntimeException("Couldn't bind status bar keyguard.");
- }
- }
-
public void userSwitched(int newUserId) {
// should be overridden
}
@@ -1363,7 +1333,7 @@ public abstract class BaseStatusBar extends SystemUI implements
boolean interrupt = (isFullscreen || (isHighPriority && (isNoisy || hasTicker)))
&& isAllowed
&& mPowerManager.isScreenOn()
- && !keyguard.isShowingAndNotHidden()
+ && !keyguard.isShowingAndNotOccluded()
&& !keyguard.isInputRestricted();
try {
interrupt = interrupt && !mDreamManager.isDreaming();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index cf6f60c..bbbe8fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -57,7 +57,6 @@ public class CommandQueue extends IStatusBar.Stub {
private static final int MSG_PRELOAD_RECENT_APPS = 14 << MSG_SHIFT;
private static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 15 << MSG_SHIFT;
private static final int MSG_SET_WINDOW_STATE = 16 << MSG_SHIFT;
- private static final int MSG_SET_KEYGUARD_SHOWN = 17 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -100,8 +99,7 @@ public class CommandQueue extends IStatusBar.Stub {
public void hideSearchPanel();
public void cancelPreloadRecentApps();
public void setWindowState(int window, int state);
- public void setKeyguardShown(boolean showKeyguard, IKeyguardShowCallback callback,
- boolean updateWindowFlags);
+
}
public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -236,14 +234,6 @@ public class CommandQueue extends IStatusBar.Stub {
}
}
- public void setKeyguardShown(boolean showKeyguard, IKeyguardShowCallback callback,
- boolean updateWindowFlags) {
- synchronized (mList) {
- mHandler.removeMessages(MSG_SET_KEYGUARD_SHOWN);
- mHandler.obtainMessage(MSG_SET_KEYGUARD_SHOWN,
- showKeyguard ? 1 : 0, updateWindowFlags ? 1 : 0, callback).sendToTarget();
- }
- }
private final class H extends Handler {
public void handleMessage(Message msg) {
@@ -325,10 +315,7 @@ public class CommandQueue extends IStatusBar.Stub {
case MSG_SET_WINDOW_STATE:
mCallbacks.setWindowState(msg.arg1, msg.arg2);
break;
- case MSG_SET_KEYGUARD_SHOWN:
- mCallbacks.setKeyguardShown(msg.arg1 != 0, (IKeyguardShowCallback) msg.obj,
- msg.arg2 != 0);
- break;
+
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java
index 1ea920d..68eaf51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java
@@ -140,16 +140,16 @@ public class KeyguardTouchDelegate {
return false;
}
- public boolean isShowingAndNotHidden() {
+ public boolean isShowingAndNotOccluded() {
final IKeyguardService service = mService;
if (service != null) {
try {
- return service.isShowingAndNotHidden();
+ return service.isShowingAndNotOccluded();
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
} else {
- Slog.w(TAG, "isShowingAndNotHidden(): NO SERVICE!");
+ Slog.w(TAG, "isShowingAndNotOccluded(): NO SERVICE!");
}
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 44f5e3a..bdcf83c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -35,9 +35,11 @@ import android.app.Notification;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -93,6 +95,8 @@ import com.android.systemui.DemoMode;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
import com.android.systemui.SwipeHelper;
+import com.android.systemui.keyguard.KeyguardService;
+import com.android.systemui.keyguard.KeyguardStatusBarBinder;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.GestureRecorder;
@@ -183,6 +187,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
StatusBarWindowView mStatusBarWindow;
PhoneStatusBarView mStatusBarView;
private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
+ private StatusBarWindowManager mStatusBarWindowManager;
int mPixelFormat;
Object mQueueLock = new Object();
@@ -274,6 +279,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
DisplayMetrics mDisplayMetrics = new DisplayMetrics();
+ protected KeyguardStatusBarBinder mKeyguardService;
// XXX: gesture research
private final GestureRecorder mGestureRec = DEBUG_GESTURES
? new GestureRecorder("/sdcard/statusbar_gestures.dat")
@@ -356,12 +362,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
}
}};
- private boolean mKeyguardShowing;
-
- private ViewGroup mKeyguard;
-
- private Button mDismissKeyguard;
-
@Override
public void setZenMode(int mode) {
super.setZenMode(mode);
@@ -393,6 +393,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
Settings.Global.getUriFor(SETTING_HEADS_UP_TICKER), true,
mHeadsUpObserver);
}
+ startKeyguard();
}
// ================================================================================
@@ -443,7 +444,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
}
});
- mKeyguard = (ViewGroup) mStatusBarWindow.findViewById(R.id.keyguard);
if (!ActivityManager.isHighEndGfx()) {
mStatusBarWindow.setBackground(null);
mNotificationPanel.setBackground(new FastColorDrawable(context.getResources().getColor(
@@ -712,6 +712,29 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
return mStatusBarView;
}
+ private void startKeyguard() {
+
+ // Create the connection to KeyguardService.
+ Intent intent = new Intent(mContext, KeyguardService.class);
+ intent.setAction(KeyguardService.ACTION_STATUS_BAR_BIND);
+ if (!mContext.bindService(intent, new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mKeyguardService = (KeyguardStatusBarBinder) service;
+ mKeyguardService.registerStatusBar(PhoneStatusBar.this, mStatusBarWindow,
+ mStatusBarWindowManager);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ if (DEBUG) Log.v(TAG, "Keyguard disconnected.");
+ mKeyguardService = null;
+ }
+ }, Context.BIND_AUTO_CREATE)) {
+ throw new RuntimeException("Couldn't bind status bar keyguard.");
+ }
+ }
+
@Override
protected void onShowSearchPanel() {
if (mNavigationBarView != null) {
@@ -789,10 +812,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
}
}
- protected int getStatusBarGravity() {
- return Gravity.TOP | Gravity.FILL_HORIZONTAL;
- }
-
public int getStatusBarHeight() {
if (mNaturalBarHeight < 0) {
final Resources res = mContext.getResources();
@@ -1508,30 +1527,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
// Expand the window to encompass the full screen in anticipation of the drag.
// This is only possible to do atomically because the status bar is at the top of the screen!
- expandWindow();
+ mStatusBarWindowManager.setStatusBarExpanded(true);
visibilityChanged(true);
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true);
}
- private void expandWindow() {
- WindowManager.LayoutParams lp = (WindowManager.LayoutParams) mStatusBarWindow.getLayoutParams();
- lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- lp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
- mWindowManager.updateViewLayout(mStatusBarWindow, lp);
- }
-
- private void releaseFocus() {
- if (mStatusBarWindow == null) return;
- WindowManager.LayoutParams lp =
- (WindowManager.LayoutParams) mStatusBarWindow.getLayoutParams();
- lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- lp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- mWindowManager.updateViewLayout(mStatusBarWindow, lp);
- }
-
public void animateCollapsePanels() {
animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
}
@@ -1544,7 +1546,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
}
// release focus immediately to kick off focus change transition
- releaseFocus();
+ mStatusBarWindowManager.setStatusBarFocusable(false);
if ((flags & CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL) == 0) {
mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
@@ -1556,7 +1558,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
mHandler.sendEmptyMessage(MSG_CLOSE_SEARCH_PANEL);
}
- if (mStatusBarWindow != null && !mKeyguardShowing) {
+ if (mStatusBarWindow != null) {
mStatusBarWindow.cancelExpandHelper();
mStatusBarView.collapseAllPanels(true);
}
@@ -1768,7 +1770,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
if (SPEW) Log.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible
+ " mExpandedVisible=" + mExpandedVisible);
- if (!mExpandedVisible || mStatusBarWindow == null || mKeyguardShowing) {
+ if (!mExpandedVisible || mStatusBarWindow == null) {
return;
}
@@ -1802,7 +1804,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
visibilityChanged(false);
// Shrink the window to the size of the status bar only
- contractWindow();
+ mStatusBarWindowManager.setStatusBarExpanded(false);
if ((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) {
setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
@@ -1819,15 +1821,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
}
- private void contractWindow() {
- WindowManager.LayoutParams lp =
- (WindowManager.LayoutParams) mStatusBarWindow.getLayoutParams();
- lp.height = getStatusBarHeight();
- lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- lp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- mWindowManager.updateViewLayout(mStatusBarWindow, lp);
- }
-
/**
* Enables or disables layers on the children of the notifications pile.
*
@@ -1936,7 +1929,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
&& mStatusBarWindowState != state) {
mStatusBarWindowState = state;
if (DEBUG_WINDOW_STATE) Log.d(TAG, "Status bar " + windowStateToString(state));
- if (!showing && !mKeyguardShowing) {
+ if (!showing) {
mStatusBarView.collapseAllPanels(false);
}
}
@@ -2361,29 +2354,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
}
private void addStatusBarWindow() {
- // Put up the view
- final int height = getStatusBarHeight();
-
- // Now that the status bar window encompasses the sliding panel and its
- // translucent backdrop, the entire thing is made TRANSLUCENT and is
- // hardware-accelerated.
- final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- height,
- WindowManager.LayoutParams.TYPE_STATUS_BAR,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
- | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
- PixelFormat.TRANSLUCENT);
-
- lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
- lp.gravity = getStatusBarGravity();
- lp.setTitle("StatusBar");
- lp.packageName = mContext.getPackageName();
-
makeStatusBarView();
- mWindowManager.addView(mStatusBarWindow, lp);
+ mStatusBarWindowManager = new StatusBarWindowManager(mContext);
+ mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}
void setNotificationIconVisibility(boolean visible, int anim) {
@@ -2692,67 +2665,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
}
}
- @Override
- public void setKeyguardShown(boolean showKeyguard, final IKeyguardShowCallback callback,
- boolean updateWindowFlags) {
- mKeyguardShowing = showKeyguard;
- if (updateWindowFlags) {
- WindowManager.LayoutParams lp =
- (WindowManager.LayoutParams) mStatusBarWindow.getLayoutParams();
- if (showKeyguard) {
- lp.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
- lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
- } else {
- lp.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
- lp.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
- }
- mWindowManager.updateViewLayout(mStatusBarWindow, lp);
- }
- if (!showKeyguard) {
- mKeyguard.setVisibility(View.GONE);
- mKeyguard.removeAllViews();
- contractWindow();
- } else {
- expandWindow();
- mKeyguard.setVisibility(View.VISIBLE);
- KeyguardSimpleHostView view = (KeyguardSimpleHostView) LayoutInflater.from(mContext)
- .inflate(R.layout.keyguard_simple_host_view, mKeyguard, false);
- mKeyguard.addView(view);
- view.setOnDismissAction(new KeyguardHostView.OnDismissAction() {
- @Override
- public boolean onDismiss() {
- contractWindow();
- if (mKeyguardService != null) {
- mKeyguardService.dismissKeyguard();
- }
- return false;
- }
- });
- view.show();
- }
- if (callback != null) {
- mStatusBarView.getViewTreeObserver().addOnPreDrawListener(
- new ViewTreeObserver.OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- mStatusBarView.getViewTreeObserver().removeOnPreDrawListener(this);
- mStatusBarView.post(new Runnable() {
- @Override
- public void run() {
- try {
- callback.onShown(mStatusBarWindow.getWindowToken());
- } catch (RemoteException e) {
- Log.e(TAG, "Could not call show callback", e);
- }
- }
- });
- return true;
- }
- });
- }
-
- }
-
/**
* Reload some of our resources when the configuration changes.
*
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
new file mode 100644
index 0000000..74549ae
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2014 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.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Slog;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+
+import com.android.internal.policy.IKeyguardShowCallback;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardSimpleHostView;
+import com.android.keyguard.R;
+import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+
+/**
+ * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
+ * via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
+ * which is in turn, reported to this class by the current
+ * {@link com.android.keyguard.KeyguardViewBase}.
+ */
+public class StatusBarKeyguardViewManager {
+ private static String TAG = "StatusBarKeyguardViewManager";
+
+ private final Context mContext;
+
+ private LockPatternUtils mLockPatternUtils;
+ private ViewMediatorCallback mViewMediatorCallback;
+ private PhoneStatusBar mPhoneStatusBar;
+
+ private KeyguardSimpleHostView mKeyguardView;
+ private ViewGroup mRoot;
+ private ViewGroup mContainer;
+ private StatusBarWindowManager mStatusBarWindowManager;
+
+ private boolean mScreenOn = false;
+ private boolean mShowOnRegister;
+
+ public StatusBarKeyguardViewManager(Context context, ViewMediatorCallback callback,
+ LockPatternUtils lockPatternUtils) {
+ mContext = context;
+ mViewMediatorCallback = callback;
+ mLockPatternUtils = lockPatternUtils;
+
+ }
+
+ public void registerStatusBar(PhoneStatusBar phoneStatusBar,
+ ViewGroup container, StatusBarWindowManager statusBarWindowManager) {
+ mPhoneStatusBar = phoneStatusBar;
+ mContainer = container;
+ mStatusBarWindowManager = statusBarWindowManager;
+ if (mShowOnRegister) {
+ mShowOnRegister = false;
+ show(null);
+ if (mScreenOn) {
+ onScreenTurnedOn(null);
+ }
+ }
+ }
+
+ /**
+ * Show the keyguard. Will handle creating and attaching to the view manager
+ * lazily.
+ */
+ public void show(Bundle options) {
+ if (mStatusBarWindowManager != null) {
+ ensureView();
+ mStatusBarWindowManager.setKeyguardShowing(true);
+ mKeyguardView.requestFocus();
+ } else {
+ mShowOnRegister = true;
+ }
+ }
+
+ private void ensureView() {
+ if (mRoot == null) {
+ inflateView();
+ }
+ }
+
+ private void inflateView() {
+ removeView();
+ mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
+ mKeyguardView = (KeyguardSimpleHostView) mRoot.findViewById(R.id.keyguard_host_view);
+ mKeyguardView.setLockPatternUtils(mLockPatternUtils);
+ mKeyguardView.setViewMediatorCallback(mViewMediatorCallback);
+ mContainer.addView(mRoot, mContainer.getChildCount());
+ mRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);
+ }
+
+ private void removeView() {
+ if (mRoot != null && mRoot.getParent() == mContainer) {
+ mContainer.removeView(mRoot);
+ mRoot = null;
+ }
+ }
+
+ /**
+ * Reset the state of the view.
+ */
+ public void reset() {
+ inflateView();
+ }
+
+ public void onScreenTurnedOff() {
+ mScreenOn = false;
+ if (mKeyguardView != null) {
+ mKeyguardView.onScreenTurnedOff();
+ }
+ }
+
+ public void onScreenTurnedOn(final IKeyguardShowCallback callback) {
+ mScreenOn = true;
+ if (mKeyguardView != null) {
+ mKeyguardView.onScreenTurnedOn();
+ if (callback != null) {
+ callbackAfterDraw(callback);
+ }
+ } else {
+ try {
+ if (callback != null) {
+ callback.onShown(null);
+ }
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Exception calling onShown():", e);
+ }
+ }
+ }
+
+ private void callbackAfterDraw(final IKeyguardShowCallback callback) {
+ mKeyguardView.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ callback.onShown(mKeyguardView.getWindowToken());
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Exception calling onShown():", e);
+ }
+ }
+ });
+ }
+
+ public void verifyUnlock() {
+ show(null);
+ mKeyguardView.verifyUnlock();
+ }
+
+ public void setNeedsInput(boolean needsInput) {
+ if (mStatusBarWindowManager != null) {
+ mStatusBarWindowManager.setKeyguardNeedsInput(needsInput);
+ }
+ }
+
+ public void updateUserActivityTimeout() {
+
+ // Use the user activity timeout requested by the keyguard view, if any.
+ if (mKeyguardView != null) {
+ long timeout = mKeyguardView.getUserActivityTimeout();
+ if (timeout >= 0) {
+ mStatusBarWindowManager.setKeyguardUserActivityTimeout(timeout);
+ return;
+ }
+ }
+
+ // Otherwise, use the default timeout.
+ mStatusBarWindowManager.setKeyguardUserActivityTimeout(
+ KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS);
+ }
+
+ public void setOccluded(boolean occluded) {
+ if (mStatusBarWindowManager != null) {
+ mStatusBarWindowManager.setKeyguardOccluded(occluded);
+ }
+ }
+
+ /**
+ * Hides the keyguard view
+ */
+ public void hide() {
+ if (mPhoneStatusBar != null) {
+ mStatusBarWindowManager.setKeyguardShowing(false);
+ if (mKeyguardView != null) {
+ mKeyguardView.cleanUp();
+ mViewMediatorCallback.keyguardGone();
+ }
+ removeView();
+ }
+ mShowOnRegister = false;
+ }
+
+ /**
+ * Dismisses the keyguard by going to the next screen or making it gone.
+ */
+ public void dismiss() {
+ if (mScreenOn) {
+ mKeyguardView.dismiss();
+ }
+ }
+
+ /**
+ * @return Whether the keyguard is showing
+ */
+ public boolean isShowing() {
+ return mRoot != null && mRoot.getVisibility() == View.VISIBLE;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
new file mode 100644
index 0000000..e418ac5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2014 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.systemui.statusbar.phone;
+
+import android.app.ActionBar;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.SystemProperties;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+
+import com.android.keyguard.R;
+
+/**
+ * Encapsulates all logic for the status bar window state management.
+ */
+public class StatusBarWindowManager {
+
+ private final Context mContext;
+ private final WindowManager mWindowManager;
+ private View mStatusBarView;
+ private WindowManager.LayoutParams mLp;
+ private int mBarHeight;
+ private final boolean mKeyguardScreenRotation;
+
+ private final State mCurrentState = new State();
+
+ public StatusBarWindowManager(Context context) {
+ mContext = context;
+ mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
+ }
+
+ private boolean shouldEnableKeyguardScreenRotation() {
+ Resources res = mContext.getResources();
+ return SystemProperties.getBoolean("lockscreen.rot_override", false)
+ || res.getBoolean(R.bool.config_enableLockScreenRotation);
+ }
+
+ /**
+ * Adds the status bar view to the window manager.
+ *
+ * @param statusBarView The view to add.
+ * @param barHeight The height of the status bar in collapsed state.
+ */
+ public void add(View statusBarView, int barHeight) {
+
+ // Now that the status bar window encompasses the sliding panel and its
+ // translucent backdrop, the entire thing is made TRANSLUCENT and is
+ // hardware-accelerated.
+ mLp = new WindowManager.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ barHeight,
+ WindowManager.LayoutParams.TYPE_STATUS_BAR,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+ | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+ | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
+ | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
+ PixelFormat.TRANSLUCENT);
+
+ mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+ mLp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
+ mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+ mLp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
+ mLp.setTitle("StatusBar");
+ mLp.packageName = mContext.getPackageName();
+ mStatusBarView = statusBarView;
+ mBarHeight = barHeight;
+ mWindowManager.addView(mStatusBarView, mLp);
+ }
+
+ private void applyKeyguardFlags(State state) {
+ if (state.keyguardShowing) {
+ mLp.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+ mLp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+ } else {
+ mLp.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+ mLp.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+ }
+ }
+
+ private void adjustScreenOrientation(State state) {
+ if (!state.isKeyguardShowingAndNotOccluded() || mKeyguardScreenRotation) {
+ mLp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
+ } else {
+ mLp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+ }
+ }
+
+ private void applyFocusableFlag(State state) {
+ if (state.isKeyguardShowingAndNotOccluded() && state.keyguardNeedsInput) {
+ mLp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+ } else if (state.isKeyguardShowingAndNotOccluded() || state.statusBarFocusable) {
+ mLp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+ } else {
+ mLp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+ }
+ }
+
+ private void applyHeight(State state) {
+ boolean expanded = state.isKeyguardShowingAndNotOccluded() || state.statusBarExpanded;
+ if (expanded) {
+ mLp.height = ViewGroup.LayoutParams.MATCH_PARENT;
+ } else {
+ mLp.height = mBarHeight;
+ }
+ }
+
+ private void applyUserActivityTimeout(State state) {
+ if (state.isKeyguardShowingAndNotOccluded()) {
+ mLp.userActivityTimeout = state.keyguardUserActivityTimeout;
+ } else {
+ mLp.userActivityTimeout = -1;
+ }
+ }
+
+ private void apply(State state) {
+ applyKeyguardFlags(state);
+ applyFocusableFlag(state);
+ adjustScreenOrientation(state);
+ applyHeight(state);
+ applyUserActivityTimeout(state);
+ mWindowManager.updateViewLayout(mStatusBarView, mLp);
+ }
+
+ public void setKeyguardShowing(boolean showing) {
+ mCurrentState.keyguardShowing = showing;
+ apply(mCurrentState);
+ }
+
+ public void setKeyguardOccluded(boolean occluded) {
+ mCurrentState.keyguardOccluded = occluded;
+ apply(mCurrentState);
+ }
+
+ public void setKeyguardNeedsInput(boolean needsInput) {
+ mCurrentState.keyguardNeedsInput = needsInput;
+ apply(mCurrentState);
+ }
+
+ public void setStatusBarExpanded(boolean expanded) {
+ mCurrentState.statusBarExpanded = expanded;
+ mCurrentState.statusBarFocusable = expanded;
+ apply(mCurrentState);
+ }
+
+ public void setStatusBarFocusable(boolean focusable) {
+ mCurrentState.statusBarFocusable = focusable;
+ apply(mCurrentState);
+ }
+
+ public void setKeyguardUserActivityTimeout(long timeout) {
+ mCurrentState.keyguardUserActivityTimeout = timeout;
+ apply(mCurrentState);
+ }
+
+ private static class State {
+ boolean keyguardShowing;
+ boolean keyguardOccluded;
+ boolean keyguardNeedsInput;
+ boolean statusBarExpanded;
+ boolean statusBarFocusable;
+ long keyguardUserActivityTimeout;
+
+ private boolean isKeyguardShowingAndNotOccluded() {
+ return keyguardShowing && !keyguardOccluded;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 2dc3373..a57a7b5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -94,15 +94,6 @@ public class TvStatusBar extends BaseStatusBar {
}
@Override
- public void setKeyguardShown(boolean showKeyguard, IKeyguardShowCallback callback,
- boolean updateKeyguardFlags) {
- }
-
- @Override
- protected void createAndAddWindows() {
- }
-
- @Override
protected WindowManager.LayoutParams getSearchLayoutParams(
LayoutParams layoutParams) {
return null;
@@ -151,6 +142,10 @@ public class TvStatusBar extends BaseStatusBar {
}
@Override
+ protected void createAndAddWindows() {
+ }
+
+ @Override
protected void refreshLayout(int layoutDirection) {
}