diff options
Diffstat (limited to 'policy/src')
4 files changed, 274 insertions, 1 deletions
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index ef096e0..5e1aa3b 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -119,6 +119,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private final static String TAG = "PhoneWindow"; private final static boolean SWEEP_OPEN_MENU = false; + + private final static int DEFAULT_BACKGROUND_FADE_DURATION_MS = 300; + /** * Simple callback used by the context menu and its submenus. The options * menu submenus do not use this (their behavior is more complex). @@ -247,6 +250,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private Transition mSharedElementExitTransition; private Boolean mAllowExitTransitionOverlap; private Boolean mAllowEnterTransitionOverlap; + private long mBackgroundFadeDurationMillis = -1; static class WindowManagerHolder { static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface( @@ -3422,6 +3426,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { com.android.internal.R.styleable. Window_windowAllowExitTransitionOverlap, true); } + if (mBackgroundFadeDurationMillis < 0) { + mBackgroundFadeDurationMillis = getWindowStyle().getInteger( + com.android.internal.R.styleable. + Window_windowTransitionBackgroundFadeDuration, + DEFAULT_BACKGROUND_FADE_DURATION_MS); + } } } } @@ -3828,6 +3838,20 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { return (mAllowExitTransitionOverlap == null) ? true : mAllowExitTransitionOverlap; } + @Override + public long getTransitionBackgroundFadeDuration() { + return (mBackgroundFadeDurationMillis < 0) ? DEFAULT_BACKGROUND_FADE_DURATION_MS + : mBackgroundFadeDurationMillis; + } + + @Override + public void setTransitionBackgroundFadeDuration(long fadeDurationMillis) { + if (fadeDurationMillis < 0) { + throw new IllegalArgumentException("negative durations are not allowed"); + } + mBackgroundFadeDurationMillis = fadeDurationMillis; + } + private static final class DrawableFeatureState { DrawableFeatureState(int _featureId) { featureId = _featureId; diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 684fd9f..03d29c0 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -314,6 +314,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mDemoHdmiRotation; boolean mDemoHdmiRotationLock; + boolean mWakeGestureEnabledSetting; + MyWakeGestureListener mWakeGestureListener; + // Default display does not rotate, apps that require non-default orientation will have to // have the orientation emulated. private boolean mForceDefaultOrientation = false; @@ -443,6 +446,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean mSearchKeyShortcutPending; boolean mConsumeSearchKeyUp; boolean mAssistKeyLongPressed; + boolean mPendingMetaAction; // support for activating the lock screen while the screen is on boolean mAllowLockscreenWhenOn; @@ -573,6 +577,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.Secure.getUriFor( + Settings.Secure.WAKE_GESTURE_ENABLED), false, this, + UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.ACCELEROMETER_ROTATION), false, this, UserHandle.USER_ALL); @@ -603,6 +610,21 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + class MyWakeGestureListener extends WakeGestureListener { + MyWakeGestureListener(Context context, Handler handler) { + super(context, handler); + } + + @Override + public void onWakeUp() { + synchronized (mLock) { + if (shouldEnableWakeGestureLp()) { + mPowerManager.wakeUp(SystemClock.uptimeMillis()); + } + } + } + } + class MyOrientationListener extends WindowOrientationListener { MyOrientationListener(Context context, Handler handler) { super(context, handler); @@ -906,6 +928,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); mHandler = new PolicyHandler(); + mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler); mOrientationListener = new MyOrientationListener(mContext, mHandler); try { mOrientationListener.setCurrentRotation(windowManager.getRotation()); @@ -1192,6 +1215,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT, UserHandle.USER_CURRENT); + // Configure wake gesture. + boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver, + Settings.Secure.WAKE_GESTURE_ENABLED, 0, + UserHandle.USER_CURRENT) != 0; + if (mWakeGestureEnabledSetting != wakeGestureEnabledSetting) { + mWakeGestureEnabledSetting = wakeGestureEnabledSetting; + updateWakeGestureListenerLp(); + } + // Configure rotation lock. int userRotation = Settings.System.getIntForUser(resolver, Settings.System.USER_ROTATION, Surface.ROTATION_0, @@ -1239,6 +1271,20 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + private void updateWakeGestureListenerLp() { + if (shouldEnableWakeGestureLp()) { + mWakeGestureListener.requestWakeUpTrigger(); + } else { + mWakeGestureListener.cancelWakeUpTrigger(); + } + } + + private boolean shouldEnableWakeGestureLp() { + return mWakeGestureEnabledSetting && !mScreenOnEarly + && (!mLidControlsSleep || mLidState != LID_CLOSED) + && mWakeGestureListener.isSupported(); + } + private void enablePointerLocation() { if (mPointerLocationView == null) { mPointerLocationView = new PointerLocationView(mContext); @@ -2043,6 +2089,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + // Cancel any pending meta actions if we see any other keys being pressed between the down + // of the meta key and its corresponding up. + if (mPendingMetaAction && keyCode != KeyEvent.KEYCODE_META_LEFT) { + mPendingMetaAction = false; + } + // First we always handle the home key here, so applications // can never break it, although if keyguard is on, we do let // it handle it, because that gives us the correct 5 second @@ -2237,6 +2289,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT_OR_SELF); } return -1; + } else if (keyCode == KeyEvent.KEYCODE_META_LEFT) { + if (down) { + mPendingMetaAction = true; + } else if (mPendingMetaAction) { + mPendingMetaAction = false; + launchAssistAction(); + } + return -1; } // Shortcuts are invoked through Search+key, so intercept those here @@ -2346,6 +2406,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { return -1; } + // Reserve all the META modifier combos for system behavior + if ((metaState & KeyEvent.META_META_LEFT_ON) != 0) { + return -1; + } + // Let the application handle the key. return 0; } @@ -4461,6 +4526,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mKeyguardDelegate.onScreenTurnedOff(why); } synchronized (mLock) { + updateWakeGestureListenerLp(); updateOrientationListenerLp(); updateLockScreenTimeout(); } @@ -4482,6 +4548,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { synchronized (mLock) { mScreenOnEarly = true; + updateWakeGestureListenerLp(); updateOrientationListenerLp(); updateLockScreenTimeout(); } @@ -5056,6 +5123,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { PowerManager.GO_TO_SLEEP_REASON_USER, PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); } + + synchronized (mLock) { + updateWakeGestureListenerLp(); + } } void updateRotation(boolean alwaysSendConfiguration) { @@ -5516,6 +5587,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(prefix); pw.print("mLastFocusNeedsMenu="); pw.println(mLastFocusNeedsMenu); } + pw.print(prefix); pw.print("mWakeGestureEnabledSetting="); + pw.println(mWakeGestureEnabledSetting); + pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation); pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); pw.print(" mDockMode="); pw.print(mDockMode); @@ -5657,9 +5731,17 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation); pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock); pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation); + mGlobalKeyManager.dump(prefix, pw); mStatusBarController.dump(pw, prefix); mNavigationBarController.dump(pw, prefix); PolicyControl.dump(prefix, pw); + + if (mWakeGestureListener != null) { + mWakeGestureListener.dump(pw, prefix); + } + if (mOrientationListener != null) { + mOrientationListener.dump(pw, prefix); + } } } diff --git a/policy/src/com/android/internal/policy/impl/WakeGestureListener.java b/policy/src/com/android/internal/policy/impl/WakeGestureListener.java new file mode 100644 index 0000000..9396c2c --- /dev/null +++ b/policy/src/com/android/internal/policy/impl/WakeGestureListener.java @@ -0,0 +1,100 @@ +/* + * 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.internal.policy.impl; + +import android.os.Handler; +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorManager; +import android.hardware.TriggerEvent; +import android.hardware.TriggerEventListener; + +import java.io.PrintWriter; + +/** + * Watches for wake gesture sensor events then invokes the listener. + */ +public abstract class WakeGestureListener { + private static final String TAG = "WakeGestureListener"; + + private final SensorManager mSensorManager; + private final Handler mHandler; + + private final Object mLock = new Object(); + + private boolean mTriggerRequested; + private Sensor mSensor; + + public WakeGestureListener(Context context, Handler handler) { + mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE); + mHandler = handler; + + mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_WAKE_GESTURE); + } + + public abstract void onWakeUp(); + + public boolean isSupported() { + synchronized (mLock) { + return mSensor != null; + } + } + + public void requestWakeUpTrigger() { + synchronized (mLock) { + if (mSensor != null && !mTriggerRequested) { + mTriggerRequested = true; + mSensorManager.requestTriggerSensor(mListener, mSensor); + } + } + } + + public void cancelWakeUpTrigger() { + synchronized (mLock) { + if (mSensor != null && mTriggerRequested) { + mTriggerRequested = false; + mSensorManager.cancelTriggerSensor(mListener, mSensor); + } + } + } + + public void dump(PrintWriter pw, String prefix) { + synchronized (mLock) { + pw.println(prefix + TAG); + prefix += " "; + pw.println(prefix + "mTriggerRequested=" + mTriggerRequested); + pw.println(prefix + "mSensor=" + mSensor); + } + } + + private final TriggerEventListener mListener = new TriggerEventListener() { + @Override + public void onTrigger(TriggerEvent event) { + synchronized (mLock) { + mTriggerRequested = false; + mHandler.post(mWakeUpRunnable); + } + } + }; + + private final Runnable mWakeUpRunnable = new Runnable() { + @Override + public void run() { + onWakeUp(); + } + }; +} diff --git a/policy/src/com/android/internal/policy/impl/WindowOrientationListener.java b/policy/src/com/android/internal/policy/impl/WindowOrientationListener.java index 0c77556..2cc33b5 100644 --- a/policy/src/com/android/internal/policy/impl/WindowOrientationListener.java +++ b/policy/src/com/android/internal/policy/impl/WindowOrientationListener.java @@ -26,6 +26,9 @@ import android.os.SystemProperties; import android.util.FloatMath; import android.util.Log; import android.util.Slog; +import android.util.TimeUtils; + +import java.io.PrintWriter; /** * A special helper class used by the WindowManager @@ -181,6 +184,19 @@ public abstract class WindowOrientationListener { */ public abstract void onProposedRotationChanged(int rotation); + public void dump(PrintWriter pw, String prefix) { + synchronized (mLock) { + pw.println(prefix + TAG); + prefix += " "; + pw.println(prefix + "mEnabled=" + mEnabled); + pw.println(prefix + "mCurrentRotation=" + mCurrentRotation); + pw.println(prefix + "mSensor=" + mSensor); + pw.println(prefix + "mRate=" + mRate); + + mSensorEventListener.dumpLocked(pw, prefix); + } + } + /** * This class filters the raw accelerometer data and tries to detect actual changes in * orientation. This is a very ill-defined problem so there are a lot of tweakable parameters, @@ -342,6 +358,14 @@ public abstract class WindowOrientationListener { /* ROTATION_270 */ { -25, 65 } }; + // The tilt angle below which we conclude that the user is holding the device + // overhead reading in bed and lock into that state. + private final int TILT_OVERHEAD_ENTER = -40; + + // The tilt angle above which we conclude that the user would like a rotation + // change to occur and unlock from the overhead state. + private final int TILT_OVERHEAD_EXIT = -15; + // The gap angle in degrees between adjacent orientation angles for hysteresis. // This creates a "dead zone" between the current orientation and a proposed // adjacent orientation. No orientation proposal is made when the orientation @@ -364,12 +388,18 @@ public abstract class WindowOrientationListener { // Timestamp when the device last appeared to be flat for sure (the flat delay elapsed). private long mFlatTimestampNanos; + private boolean mFlat; // Timestamp when the device last appeared to be swinging. private long mSwingTimestampNanos; + private boolean mSwinging; // Timestamp when the device last appeared to be undergoing external acceleration. private long mAccelerationTimestampNanos; + private boolean mAccelerating; + + // Whether we are locked into an overhead usage mode. + private boolean mOverhead; // History of observed tilt angles. private static final int TILT_HISTORY_SIZE = 40; @@ -381,6 +411,19 @@ public abstract class WindowOrientationListener { return mProposedRotation; } + public void dumpLocked(PrintWriter pw, String prefix) { + pw.println(prefix + "mProposedRotation=" + mProposedRotation); + pw.println(prefix + "mPredictedRotation=" + mPredictedRotation); + pw.println(prefix + "mLastFilteredX=" + mLastFilteredX); + pw.println(prefix + "mLastFilteredY=" + mLastFilteredY); + pw.println(prefix + "mLastFilteredZ=" + mLastFilteredZ); + pw.println(prefix + "mTiltHistory={last: " + getLastTiltLocked() + "}"); + pw.println(prefix + "mFlat=" + mFlat); + pw.println(prefix + "mSwinging=" + mSwinging); + pw.println(prefix + "mAccelerating=" + mAccelerating); + pw.println(prefix + "mOverhead=" + mOverhead); + } + @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @@ -478,7 +521,18 @@ public abstract class WindowOrientationListener { // If the tilt angle is too close to horizontal then we cannot determine // the orientation angle of the screen. - if (Math.abs(tiltAngle) > MAX_TILT) { + if (tiltAngle <= TILT_OVERHEAD_ENTER) { + mOverhead = true; + } else if (tiltAngle >= TILT_OVERHEAD_EXIT) { + mOverhead = false; + } + if (mOverhead) { + if (LOG) { + Slog.v(TAG, "Ignoring sensor data, device is overhead: " + + "tiltAngle=" + tiltAngle); + } + clearPredictedRotationLocked(); + } else if (Math.abs(tiltAngle) > MAX_TILT) { if (LOG) { Slog.v(TAG, "Ignoring sensor data, tilt angle too high: " + "tiltAngle=" + tiltAngle); @@ -526,6 +580,9 @@ public abstract class WindowOrientationListener { } } } + mFlat = isFlat; + mSwinging = isSwinging; + mAccelerating = isAccelerating; // Determine new proposed rotation. oldProposedRotation = mProposedRotation; @@ -543,6 +600,7 @@ public abstract class WindowOrientationListener { + ", isAccelerating=" + isAccelerating + ", isFlat=" + isFlat + ", isSwinging=" + isSwinging + + ", isOverhead=" + mOverhead + ", timeUntilSettledMS=" + remainingMS(now, mPredictedRotationTimestampNanos + PROPOSAL_SETTLE_TIME_NANOS) + ", timeUntilAccelerationDelayExpiredMS=" + remainingMS(now, @@ -660,8 +718,12 @@ public abstract class WindowOrientationListener { mLastFilteredTimestampNanos = Long.MIN_VALUE; mProposedRotation = -1; mFlatTimestampNanos = Long.MIN_VALUE; + mFlat = false; mSwingTimestampNanos = Long.MIN_VALUE; + mSwinging = false; mAccelerationTimestampNanos = Long.MIN_VALUE; + mAccelerating = false; + mOverhead = false; clearPredictedRotationLocked(); clearTiltHistoryLocked(); } @@ -726,6 +788,11 @@ public abstract class WindowOrientationListener { return mTiltHistoryTimestampNanos[index] != Long.MIN_VALUE ? index : -1; } + private float getLastTiltLocked() { + int index = nextTiltHistoryIndexLocked(mTiltHistoryIndex); + return index >= 0 ? mTiltHistory[index] : Float.NaN; + } + private float remainingMS(long now, long until) { return now >= until ? 0 : (until - now) * 0.000001f; } |