diff options
Diffstat (limited to 'policy')
5 files changed, 261 insertions, 51 deletions
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java index 76d3df0..f45556f 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java @@ -293,6 +293,10 @@ class KeyguardStatusViewManager implements OnClickListener { mUpdateMonitor.registerInfoCallback(mInfoCallback); mUpdateMonitor.registerSimStateCallback(mSimStateCallback); resetStatusInfo(); + //Issue the faceunlock failure message in a centralized place + if (mUpdateMonitor.getMaxFaceUnlockAttemptsReached()) { + setInstructionText(getContext().getString(R.string.faceunlock_multiple_failures)); + } } void resetStatusInfo() { diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java index b4b82aa..1d6f39a 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java @@ -81,6 +81,8 @@ public class KeyguardUpdateMonitor { private CharSequence mTelephonySpn; private int mFailedAttempts = 0; + private int mFailedFaceUnlockAttempts = 0; + private static final int FAILED_FACE_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 15; private boolean mClockVisible; @@ -630,6 +632,7 @@ public class KeyguardUpdateMonitor { public void clearFailedAttempts() { mFailedAttempts = 0; + mFailedFaceUnlockAttempts = 0; } public void reportFailedAttempt() { @@ -643,4 +646,12 @@ public class KeyguardUpdateMonitor { public int getPhoneState() { return mPhoneState; } + + public void reportFailedFaceUnlockAttempt() { + mFailedFaceUnlockAttempts++; + } + + public boolean getMaxFaceUnlockAttemptsReached() { + return mFailedFaceUnlockAttempts >= FAILED_FACE_UNLOCK_ATTEMPTS_BEFORE_BACKUP; + } } diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java index ff8d5ac..4bba71b 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java @@ -118,6 +118,7 @@ public class KeyguardViewManager implements KeyguardWindowController { int flags = WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER | WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING + | WindowManager.LayoutParams.FLAG_SLIPPERY /*| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR*/ ; if (!mNeedsInput) { diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java index 6eff4b6..0d0461b 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -52,6 +52,7 @@ import android.os.Handler; import android.os.Message; import android.os.IBinder; import android.os.Parcelable; +import android.os.PowerManager; import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; @@ -101,8 +102,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler private View mLockScreen; private View mUnlockScreen; - private volatile boolean mScreenOn = false; - private volatile boolean mWindowFocused = false; + private boolean mScreenOn; + private boolean mWindowFocused = false; private boolean mEnableFallback = false; // assume no fallback UI until we know better private boolean mShowLockBeforeUnlock = false; @@ -132,10 +133,6 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler // So the user has a consistent amount of time when brought to the backup method from FaceLock private final int BACKUP_LOCK_TIMEOUT = 5000; - // Needed to keep track of failed FaceUnlock attempts - private int mFailedFaceUnlockAttempts = 0; - private static final int FAILED_FACE_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 15; - /** * The current {@link KeyguardScreen} will use this to communicate back to us. */ @@ -147,6 +144,11 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler //Also true if we've activated a phone call, either emergency dialing or incoming //This resets when the phone is turned off with no current call private boolean mHasOverlay; + //True if a dialog is currently displaying on top of this window + //Unlike other overlays, this does not close with a power button cycle + private boolean mHasDialog = false; + //True if this device is currently plugged in + private boolean mPluggedIn; /** @@ -309,6 +311,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler mLockPatternUtils = lockPatternUtils; mWindowController = controller; mHasOverlay = false; + mPluggedIn = mUpdateMonitor.isDevicePluggedIn(); + mScreenOn = ((PowerManager)context.getSystemService(Context.POWER_SERVICE)).isScreenOn(); mUpdateMonitor.registerInfoCallback(this); @@ -370,7 +374,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT); } - // FaceLock must be stopped if it is running + // FaceLock must be stopped if it is running when emergency call is pressed stopAndUnbindFromFaceLock(); pokeWakelock(EMERGENCY_CALL_TIMEOUT); @@ -459,7 +463,6 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler } public void reportSuccessfulUnlockAttempt() { - mFailedFaceUnlockAttempts = 0; mLockPatternUtils.reportSuccessfulPasswordAttempt(); } }; @@ -557,7 +560,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler if (DEBUG) Log.d(TAG, "screen off"); mScreenOn = false; mForgotPattern = false; - mHasOverlay = mUpdateMonitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE; + mHasOverlay = mUpdateMonitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE || + mHasDialog; // Emulate activity life-cycle for both lock and unlock screen. if (mLockScreen != null) { @@ -577,22 +581,26 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler * FaceLock, but only if we're not dealing with a call */ private void activateFaceLockIfAble() { - final boolean tooManyFaceUnlockTries = - (mFailedFaceUnlockAttempts >= FAILED_FACE_UNLOCK_ATTEMPTS_BEFORE_BACKUP); + final boolean tooManyFaceUnlockTries = mUpdateMonitor.getMaxFaceUnlockAttemptsReached(); final int failedBackupAttempts = mUpdateMonitor.getFailedAttempts(); final boolean backupIsTimedOut = (failedBackupAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT); if (tooManyFaceUnlockTries) Log.i(TAG, "tooManyFaceUnlockTries: " + tooManyFaceUnlockTries); if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE + && usingFaceLock() && !mHasOverlay && !tooManyFaceUnlockTries && !backupIsTimedOut) { bindToFaceLock(); + // Show FaceLock area, but only for a little bit so lockpattern will become visible if // FaceLock fails to start or crashes - if (usingFaceLock()) { - showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_SERVICE_TIMEOUT); - } + showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_SERVICE_TIMEOUT); + + // When switching between portrait and landscape view while FaceLock is running, the + // screen will eventually go dark unless we poke the wakelock when FaceLock is + // restarted + mKeyguardScreenCallback.pokeWakelock(); } else { hideFaceLockArea(); } @@ -647,8 +655,9 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler mHasOverlay = true; stopAndUnbindFromFaceLock(); hideFaceLockArea(); - } else if (runFaceLock) { - activateFaceLockIfAble(); + } else { + mHasDialog = false; + if (runFaceLock) activateFaceLockIfAble(); } } @@ -718,10 +727,19 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler post(mRecreateRunnable); } - //Ignore these events; they are implemented only because they come from the same interface + /** When somebody plugs in or unplugs the device, we don't want to display faceunlock */ @Override - public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) - {} + public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) { + mHasOverlay |= mPluggedIn != pluggedIn; + mPluggedIn = pluggedIn; + //If it's already running, don't close it down: the unplug didn't start it + if (!mFaceLockServiceRunning) { + stopAndUnbindFromFaceLock(); + hideFaceLockArea(); + } + } + + //Ignore these events; they are implemented only because they come from the same interface @Override public void onTimeChanged() {} @Override @@ -1049,6 +1067,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler } private void showDialog(String title, String message) { + mHasDialog = true; final AlertDialog dialog = new AlertDialog.Builder(mContext) .setTitle(title) .setMessage(message) @@ -1292,8 +1311,11 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler } if (mFaceLockAreaView != null) { + int[] faceLockPosition; + faceLockPosition = new int[2]; + mFaceLockAreaView.getLocationInWindow(faceLockPosition); startFaceLock(mFaceLockAreaView.getWindowToken(), - mFaceLockAreaView.getLeft(), mFaceLockAreaView.getTop(), + faceLockPosition[0], faceLockPosition[1], mFaceLockAreaView.getWidth(), mFaceLockAreaView.getHeight()); } } @@ -1311,14 +1333,14 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler }; // Tells the FaceLock service to start displaying its UI and perform recognition - public void startFaceLock(IBinder windowToken, int x, int y, int h, int w) + public void startFaceLock(IBinder windowToken, int x, int y, int w, int h) { if (usingFaceLock()) { synchronized (mFaceLockServiceRunningLock) { if (!mFaceLockServiceRunning) { if (DEBUG) Log.d(TAG, "Starting FaceLock"); try { - mFaceLockService.startUi(windowToken, x, y, h, w); + mFaceLockService.startUi(windowToken, x, y, w, h); } catch (RemoteException e) { Log.e(TAG, "Caught exception starting FaceLock: " + e.toString()); return; @@ -1360,7 +1382,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler public void unlock() { if (DEBUG) Log.d(TAG, "FaceLock unlock()"); showFaceLockArea(); // Keep fallback covered - stopFaceLock(); + stopAndUnbindFromFaceLock(); mKeyguardScreenCallback.keyguardDone(true); mKeyguardScreenCallback.reportSuccessfulUnlockAttempt(); @@ -1372,7 +1394,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler public void cancel() { if (DEBUG) Log.d(TAG, "FaceLock cancel()"); hideFaceLockArea(); // Expose fallback - stopFaceLock(); + stopAndUnbindFromFaceLock(); mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT); } @@ -1381,9 +1403,9 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler @Override public void reportFailedAttempt() { if (DEBUG) Log.d(TAG, "FaceLock reportFailedAttempt()"); - mFailedFaceUnlockAttempts++; + mUpdateMonitor.reportFailedFaceUnlockAttempt(); hideFaceLockArea(); // Expose fallback - stopFaceLock(); + stopAndUnbindFromFaceLock(); mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT); } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 0b223c1..468f0d5 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -45,6 +45,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.IRemoteCallback; import android.os.LocalPowerManager; +import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.PowerManager; @@ -61,7 +62,6 @@ import com.android.internal.app.ShutdownThread; import com.android.internal.policy.PolicyManager; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.telephony.ITelephony; -import com.android.internal.view.BaseInputHandler; import com.android.internal.widget.PointerLocationView; import android.util.DisplayMetrics; @@ -75,8 +75,8 @@ import android.view.IApplicationToken; import android.view.IWindowManager; import android.view.InputChannel; import android.view.InputDevice; -import android.view.InputQueue; -import android.view.InputHandler; +import android.view.InputEvent; +import android.view.InputEventReceiver; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.MotionEvent; @@ -164,6 +164,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true; static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false; + // Should screen savers use their own timeout, or the SCREEN_OFF_TIMEOUT? + static final boolean SEPARATE_TIMEOUT_FOR_SCREEN_SAVER = false; + static final int LONG_PRESS_POWER_NOTHING = 0; static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1; static final int LONG_PRESS_POWER_SHUT_OFF = 2; @@ -316,7 +319,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean mSystemReady; boolean mSystemBooted; boolean mHdmiPlugged; - int mUiMode = Configuration.UI_MODE_TYPE_NORMAL; + int mUiMode; int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED; int mLidOpenRotation; int mCarDockRotation; @@ -348,25 +351,32 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowState mFocusedWindow; IApplicationToken mFocusedApp; - private final InputHandler mPointerLocationInputHandler = new BaseInputHandler() { + final class PointerLocationInputEventReceiver extends InputEventReceiver { + public PointerLocationInputEventReceiver(InputChannel inputChannel, Looper looper) { + super(inputChannel, looper); + } + @Override - public void handleMotion(MotionEvent event, InputQueue.FinishedCallback finishedCallback) { + public void onInputEvent(InputEvent event) { boolean handled = false; try { - if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { + if (event instanceof MotionEvent + && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { + final MotionEvent motionEvent = (MotionEvent)event; synchronized (mLock) { if (mPointerLocationView != null) { - mPointerLocationView.addPointerEvent(event); + mPointerLocationView.addPointerEvent(motionEvent); handled = true; } } } } finally { - finishedCallback.finished(handled); + finishInputEvent(event, handled); } } - }; - + } + PointerLocationInputEventReceiver mPointerLocationInputEventReceiver; + // The current size of the screen; really; (ir)regardless of whether the status // bar can be hidden or not int mUnrestrictedScreenLeft, mUnrestrictedScreenTop; @@ -426,6 +436,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mLockScreenTimeout; boolean mLockScreenTimerActive; + // visual screen saver support + int mScreenSaverTimeout = 0; + boolean mScreenSaverEnabledByUser = false; + boolean mScreenSaverMayRun = true; // false if a wakelock is held + boolean mPluggedIn; + // Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.) int mEndcallBehavior; @@ -488,6 +504,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { Settings.Secure.DEFAULT_INPUT_METHOD), false, this); resolver.registerContentObserver(Settings.System.getUriFor( "fancy_rotation_anim"), false, this); + resolver.registerContentObserver(Settings.Secure.getUriFor( + Settings.Secure.SCREENSAVER_ENABLED), false, this); + if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) { + resolver.registerContentObserver(Settings.Secure.getUriFor( + "screensaver_timeout"), false, this); + } // otherwise SCREEN_OFF_TIMEOUT will do nicely updateSettings(); } @@ -771,6 +793,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { settingsObserver.observe(); mShortcutManager = new ShortcutManager(context, mHandler); mShortcutManager.observe(); + mUiMode = context.getResources().getInteger( + com.android.internal.R.integer.config_defaultUiModeType); mHomeIntent = new Intent(Intent.ACTION_MAIN, null); mHomeIntent.addCategory(Intent.CATEGORY_HOME); mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK @@ -816,6 +840,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { Intent.EXTRA_DOCK_STATE_UNDOCKED); } + // watch the plug to know whether to trigger the screen saver + filter = new IntentFilter(); + filter.addAction(Intent.ACTION_BATTERY_CHANGED); + intent = context.registerReceiver(mPowerReceiver, filter); + if (intent != null) { + mPluggedIn = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0)); + } + mVibrator = new Vibrator(); mLongPressVibePattern = getLongIntArray(mContext.getResources(), com.android.internal.R.array.config_longPressVibePattern); @@ -964,6 +996,23 @@ public class PhoneWindowManager implements WindowManagerPolicy { mHasSoftInput = hasSoftInput; updateRotation = true; } + + mScreenSaverEnabledByUser = 0 != Settings.Secure.getInt(resolver, + Settings.Secure.SCREENSAVER_ENABLED, 1); + + if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) { + mScreenSaverTimeout = Settings.Secure.getInt(resolver, + "screensaver_timeout", 0); + } else { + mScreenSaverTimeout = Settings.System.getInt(resolver, + Settings.System.SCREEN_OFF_TIMEOUT, 0); + if (mScreenSaverTimeout > 0) { + // We actually want to activate the screensaver just before the + // power manager's screen timeout + mScreenSaverTimeout -= 5000; + } + } + updateScreenSaverTimeoutLocked(); } if (updateRotation) { updateRotation(true); @@ -987,9 +1036,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mPointerLocationInputChannel == null) { try { mPointerLocationInputChannel = - mWindowManager.monitorInput("PointerLocationView"); - InputQueue.registerInputChannel(mPointerLocationInputChannel, - mPointerLocationInputHandler, mHandler.getLooper().getQueue()); + mWindowManager.monitorInput("PointerLocationView"); + mPointerLocationInputEventReceiver = + new PointerLocationInputEventReceiver( + mPointerLocationInputChannel, mHandler.getLooper()); } catch (RemoteException ex) { Slog.e(TAG, "Could not set up input monitoring channel for PointerLocation.", ex); @@ -997,8 +1047,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } if (removeView != null) { + if (mPointerLocationInputEventReceiver != null) { + mPointerLocationInputEventReceiver.dispose(); + mPointerLocationInputEventReceiver = null; + } if (mPointerLocationInputChannel != null) { - InputQueue.unregisterInputChannel(mPointerLocationInputChannel); mPointerLocationInputChannel.dispose(); mPointerLocationInputChannel = null; } @@ -1829,13 +1882,19 @@ public class PhoneWindowManager implements WindowManagerPolicy { * to determine when the nav bar should be shown and prevent applications from * receiving those touches. */ - final InputHandler mHideNavInputHandler = new BaseInputHandler() { + final class HideNavInputEventReceiver extends InputEventReceiver { + public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) { + super(inputChannel, looper); + } + @Override - public void handleMotion(MotionEvent event, InputQueue.FinishedCallback finishedCallback) { + public void onInputEvent(InputEvent event) { boolean handled = false; try { - if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { - if (event.getAction() == MotionEvent.ACTION_DOWN) { + if (event instanceof MotionEvent + && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { + final MotionEvent motionEvent = (MotionEvent)event; + if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { // When the user taps down, we re-show the nav bar. boolean changed = false; synchronized (mLock) { @@ -1872,9 +1931,17 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } } finally { - finishedCallback.finished(handled); + finishInputEvent(event, handled); } } + } + final InputEventReceiver.Factory mHideNavInputEventReceiverFactory = + new InputEventReceiver.Factory() { + @Override + public InputEventReceiver createInputEventReceiver( + InputChannel inputChannel, Looper looper) { + return new HideNavInputEventReceiver(inputChannel, looper); + } }; @Override @@ -1938,7 +2005,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } else if (mHideNavFakeWindow == null) { mHideNavFakeWindow = mWindowManagerFuncs.addFakeWindow( - mHandler.getLooper(), mHideNavInputHandler, + mHandler.getLooper(), mHideNavInputEventReceiverFactory, "hidden nav", WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER, 0, false, false, true); } @@ -2721,6 +2788,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); } + if (keyCode == KeyEvent.KEYCODE_POWER) { + policyFlags |= WindowManagerPolicy.FLAG_WAKE; + } + final boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE + | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0; + // Basic policy based on screen state and keyguard. // FIXME: This policy isn't quite correct. We shouldn't care whether the screen // is on or off, really. We should care about whether the device is in an @@ -2730,16 +2803,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { // the device some other way (which is why we have an exemption here for injected // events). int result; - if (isScreenOn || isInjected) { + if (isScreenOn || (isInjected && !isWakeKey)) { // When the screen is on or if the key is injected pass the key to the application. result = ACTION_PASS_TO_USER; } else { // When the screen is off and the key is not injected, determine whether // to wake the device but don't pass the key to the application. result = 0; - - final boolean isWakeKey = (policyFlags - & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0; if (down && isWakeKey) { if (keyguardActive) { // If the keyguard is showing, let it decide what to do with the wake key. @@ -3021,6 +3091,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { } }; + BroadcastReceiver mPowerReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) { + mPluggedIn = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0)); + if (localLOGV) Log.v(TAG, "BATTERY_CHANGED: " + intent + " plugged=" + mPluggedIn); + } + } + }; + /** {@inheritDoc} */ public void screenTurnedOff(int why) { EventLog.writeEvent(70000, 0); @@ -3032,6 +3111,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { synchronized (mLock) { updateOrientationListenerLp(); updateLockScreenTimeout(); + updateScreenSaverTimeoutLocked(); } } @@ -3078,6 +3158,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mScreenOnEarly = true; updateOrientationListenerLp(); updateLockScreenTimeout(); + updateScreenSaverTimeoutLocked(); } } @@ -3476,6 +3557,85 @@ public class PhoneWindowManager implements WindowManagerPolicy { mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); } } + + synchronized (mLock) { + // Only posts messages; holds no additional locks. + updateScreenSaverTimeoutLocked(); + } + } + + Runnable mScreenSaverActivator = new Runnable() { + public void run() { + if (!(mScreenSaverMayRun && mScreenOnEarly)) { + Log.w(TAG, "mScreenSaverActivator ran, but the screensaver should not be showing. Who's driving this thing?"); + return; + } + if (!mPluggedIn) { + if (localLOGV) Log.v(TAG, "mScreenSaverActivator: not running screen saver when not plugged in"); + return; + } + // Quick fix for automation tests. + // The correct fix is to move this triggering logic to PowerManager, where more complete + // information about wakelocks (including StayOnWhilePluggedIn) is available. + if (Settings.System.getInt(mContext.getContentResolver(), + Settings.System.STAY_ON_WHILE_PLUGGED_IN, + BatteryManager.BATTERY_PLUGGED_AC) != 0) { + Log.v(TAG, "mScreenSaverActivator: not running screen saver when STAY_ON_WHILE_PLUGGED_IN"); + return; + } + + if (localLOGV) Log.v(TAG, "mScreenSaverActivator entering dreamland"); + + try { + String component = Settings.Secure.getString( + mContext.getContentResolver(), Settings.Secure.SCREENSAVER_COMPONENT); + if (component == null) { + component = mContext.getResources().getString(R.string.config_defaultDreamComponent); + } + if (component != null) { + // dismiss the notification shade, recents, etc. + mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS) + .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)); + + ComponentName cn = ComponentName.unflattenFromString(component); + Intent intent = new Intent(Intent.ACTION_MAIN) + .setComponent(cn) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS + | Intent.FLAG_ACTIVITY_NO_USER_ACTION + | Intent.FLAG_FROM_BACKGROUND + | Intent.FLAG_ACTIVITY_NO_HISTORY + ); + mContext.startActivity(intent); + } else { + Log.e(TAG, "Couldn't start screen saver: none selected"); + } + } catch (android.content.ActivityNotFoundException exc) { + // no screensaver? give up + Log.e(TAG, "Couldn't start screen saver: none installed"); + } + } + }; + + // Must call while holding mLock + private void updateScreenSaverTimeoutLocked() { + if (mScreenSaverActivator == null) return; + + mHandler.removeCallbacks(mScreenSaverActivator); + if (mScreenSaverEnabledByUser && mScreenSaverMayRun && mScreenOnEarly && mScreenSaverTimeout > 0) { + if (localLOGV) + Log.v(TAG, "scheduling screensaver for " + mScreenSaverTimeout + "ms from now"); + mHandler.postDelayed(mScreenSaverActivator, mScreenSaverTimeout); + } else { + if (localLOGV) { + if (!mScreenSaverEnabledByUser || mScreenSaverTimeout == 0) + Log.v(TAG, "screen saver disabled by user"); + else if (!mScreenOnEarly) + Log.v(TAG, "screen saver disabled while screen off"); + else + Log.v(TAG, "screen saver disabled by wakelock"); + } + } } Runnable mScreenLockTimeout = new Runnable() { @@ -3681,6 +3841,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { } public void screenOnStartedLw() { + // The window manager has just grabbed a wake lock. This is our cue to disable the screen + // saver. + synchronized (mLock) { + mScreenSaverMayRun = false; + } } public void screenOnStoppedLw() { @@ -3689,6 +3854,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { long curTime = SystemClock.uptimeMillis(); mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT); } + + synchronized (mLock) { + // even if the keyguard is up, now that all the wakelocks have been released, we + // should re-enable the screen saver + mScreenSaverMayRun = true; + updateScreenSaverTimeoutLocked(); + } } } |
