summaryrefslogtreecommitdiffstats
path: root/policy/src
diff options
context:
space:
mode:
Diffstat (limited to 'policy/src')
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java24
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindowManager.java82
-rw-r--r--policy/src/com/android/internal/policy/impl/WakeGestureListener.java100
-rw-r--r--policy/src/com/android/internal/policy/impl/WindowOrientationListener.java69
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;
}