diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e9ffc5226fb35..bec401ee96025 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4460,6 +4460,12 @@ public final class Settings {
public static final int INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT =
INCALL_POWER_BUTTON_BEHAVIOR_SCREEN_OFF;
+ /**
+ * Whether the device should wake when the wake gesture sensor detects motion.
+ * @hide
+ */
+ public static final String WAKE_GESTURE_ENABLED = "wake_gesture_enabled";
+
/**
* The current night mode that has been selected by the user. Owned
* and controlled by UiModeManagerService. Constants are as per
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index bf97fc0abd29f..0e025a911bab1 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -192,4 +192,7 @@
%1$s %2$s
+
+ true
+
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 286921ecff336..c4a54b7ff782e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -70,7 +70,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
// database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
// is properly propagated through your change. Not doing so will result in a loss of user
// settings.
- private static final int DATABASE_VERSION = 103;
+ private static final int DATABASE_VERSION = 104;
private Context mContext;
private int mUserHandle;
@@ -1660,6 +1660,23 @@ public class DatabaseHelper extends SQLiteOpenHelper {
}
upgradeVersion = 103;
}
+
+ if (upgradeVersion == 103) {
+ db.beginTransaction();
+ SQLiteStatement stmt = null;
+ try {
+ stmt = db.compileStatement("INSERT OR REPLACE INTO secure(name,value)"
+ + " VALUES(?,?);");
+ loadBooleanSetting(stmt, Settings.Secure.WAKE_GESTURE_ENABLED,
+ R.bool.def_wake_gesture_enabled);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ if (stmt != null) stmt.close();
+ }
+ upgradeVersion = 104;
+ }
+
// *** Remember to update DATABASE_VERSION above!
if (upgradeVersion != currentVersion) {
@@ -2222,6 +2239,9 @@ public class DatabaseHelper extends SQLiteOpenHelper {
loadBooleanSetting(stmt, Settings.Secure.INSTALL_NON_MARKET_APPS,
R.bool.def_install_non_market_apps);
+ loadBooleanSetting(stmt, Settings.Secure.WAKE_GESTURE_ENABLED,
+ R.bool.def_wake_gesture_enabled);
+
} finally {
if (stmt != null) stmt.close();
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 1a7c0a8900eba..fb041fa2e3126 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -289,6 +289,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;
@@ -525,6 +528,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);
@@ -555,6 +561,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);
@@ -856,6 +877,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mWindowManager = windowManager;
mWindowManagerFuncs = windowManagerFuncs;
mHandler = new PolicyHandler();
+ mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
mOrientationListener = new MyOrientationListener(mContext, mHandler);
try {
mOrientationListener.setCurrentRotation(windowManager.getRotation());
@@ -1142,6 +1164,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,
@@ -1189,6 +1220,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);
@@ -4406,6 +4451,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mKeyguardDelegate.onScreenTurnedOff(why);
}
synchronized (mLock) {
+ updateWakeGestureListenerLp();
updateOrientationListenerLp();
updateLockScreenTimeout();
}
@@ -4422,6 +4468,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
synchronized (mLock) {
mScreenOnEarly = true;
+ updateWakeGestureListenerLp();
updateOrientationListenerLp();
updateLockScreenTimeout();
}
@@ -5022,6 +5069,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) {
@@ -5482,6 +5533,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);
@@ -5628,6 +5682,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
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 0000000000000..9396c2ca62607
--- /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();
+ }
+ };
+}