summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/provider/Settings.java9
-rw-r--r--core/java/com/android/internal/logging/MetricsLogger.java2
-rwxr-xr-xcore/res/res/values/config.xml4
-rwxr-xr-xcore/res/res/values/symbols.xml1
-rw-r--r--services/core/java/com/android/server/GestureLauncherService.java140
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java11
6 files changed, 127 insertions, 40 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 89de101..501b771 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5719,6 +5719,15 @@ public final class Settings {
public static final String CAMERA_GESTURE_DISABLED = "camera_gesture_disabled";
/**
+ * Whether the camera launch gesture to double tap the power button when the screen is off
+ * should be disabled.
+ *
+ * @hide
+ */
+ public static final String CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED =
+ "camera_double_tap_power_gesture_disabled";
+
+ /**
* This are the settings to be backed up.
*
* NOTE: Settings are backed up and restored in the order they appear
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index 6da0f63..b6240e4 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -44,6 +44,8 @@ public class MetricsLogger implements MetricsConstants {
public static final int ACTION_FINGERPRINT_AUTH = 252;
public static final int ACTION_FINGERPRINT_DELETE = 253;
public static final int ACTION_FINGERPRINT_RENAME = 254;
+ public static final int ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE = 255;
+ public static final int ACTION_WIGGLE_CAMERA_GESTURE = 256;
public static void visible(Context context, int category) throws IllegalArgumentException {
if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b958c4b..901ef5a 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2306,6 +2306,10 @@
must match the value of config_cameraLaunchGestureSensorType in OEM's HAL -->
<string translatable="false" name="config_cameraLaunchGestureSensorStringType"></string>
+ <!-- Allow the gesture to double tap the power button twice to start the camera while the device
+ is non-interactive. -->
+ <bool name="config_cameraDoubleTapPowerGestureEnabled">true</bool>
+
<!-- Name of the component to handle network policy notifications. If present,
disables NetworkPolicyManagerService's presentation of data-usage notifications. -->
<string translatable="false" name="config_networkPolicyNotificationComponent"></string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 57d7c0e..2648ddd 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2327,6 +2327,7 @@
<!-- Gesture -->
<java-symbol type="integer" name="config_cameraLaunchGestureSensorType" />
<java-symbol type="string" name="config_cameraLaunchGestureSensorStringType" />
+ <java-symbol type="bool" name="config_cameraDoubleTapPowerGestureEnabled" />
<java-symbol type="string" name="config_networkPolicyNotificationComponent" />
<java-symbol type="drawable" name="platlogo_m" />
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index 342a3ef..69f0cef 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -17,7 +17,6 @@
package com.android.server;
import android.app.ActivityManager;
-import android.app.KeyguardManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -33,10 +32,11 @@ import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.os.Vibrator;
import android.provider.Settings;
import android.util.Slog;
+import android.view.KeyEvent;
+import com.android.internal.logging.MetricsLogger;
import com.android.server.statusbar.StatusBarManagerInternal;
/**
@@ -46,10 +46,16 @@ import com.android.server.statusbar.StatusBarManagerInternal;
* added.</p>
* @hide
*/
-class GestureLauncherService extends SystemService {
+public class GestureLauncherService extends SystemService {
private static final boolean DBG = false;
private static final String TAG = "GestureLauncherService";
+ /**
+ * Time in milliseconds in which the power button must be pressed twice so it will be considered
+ * as a camera launch.
+ */
+ private static final long CAMERA_POWER_DOUBLE_TAP_TIME_MS = 300;
+
/** The listener that receives the gesture event. */
private final GestureEventListener mGestureListener = new GestureEventListener();
@@ -91,13 +97,20 @@ class GestureLauncherService extends SystemService {
*/
private int mCameraLaunchLastEventExtra = 0;
+ /**
+ * Whether camera double tap power button gesture is currently enabled;
+ */
+ private boolean mCameraDoubleTapPowerEnabled;
+ private long mLastPowerDownWhileNonInteractive = 0;
+
+
public GestureLauncherService(Context context) {
super(context);
mContext = context;
}
public void onStart() {
- // Nothing to publish.
+ LocalServices.addService(GestureLauncherService.class, this);
}
public void onBootPhase(int phase) {
@@ -113,17 +126,21 @@ class GestureLauncherService extends SystemService {
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"GestureLauncherService");
updateCameraRegistered();
+ updateCameraDoubleTapPowerEnabled();
mUserId = ActivityManager.getCurrentUser();
mContext.registerReceiver(mUserReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED));
- registerContentObserver();
+ registerContentObservers();
}
}
- private void registerContentObserver() {
+ private void registerContentObservers() {
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.CAMERA_GESTURE_DISABLED),
false, mSettingObserver, mUserId);
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED),
+ false, mSettingObserver, mUserId);
}
private void updateCameraRegistered() {
@@ -135,6 +152,13 @@ class GestureLauncherService extends SystemService {
}
}
+ private void updateCameraDoubleTapPowerEnabled() {
+ boolean enabled = isCameraDoubleTapPowerSettingEnabled(mContext, mUserId);
+ synchronized (this) {
+ mCameraDoubleTapPowerEnabled = enabled;
+ }
+ }
+
private void unregisterCameraLaunchGesture() {
if (mRegistered) {
mRegistered = false;
@@ -197,6 +221,12 @@ class GestureLauncherService extends SystemService {
Settings.Secure.CAMERA_GESTURE_DISABLED, 0, userId) == 0);
}
+ public static boolean isCameraDoubleTapPowerSettingEnabled(Context context, int userId) {
+ return isCameraDoubleTapPowerEnabled(context.getResources())
+ && (Settings.Secure.getIntForUser(context.getContentResolver(),
+ Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 0, userId) == 0);
+ }
+
/**
* Whether to enable the camera launch gesture.
*/
@@ -207,13 +237,64 @@ class GestureLauncherService extends SystemService {
!SystemProperties.getBoolean("gesture.disable_camera_launch", false);
}
+ public static boolean isCameraDoubleTapPowerEnabled(Resources resources) {
+ return resources.getBoolean(
+ com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled);
+ }
+
/**
* Whether GestureLauncherService should be enabled according to system properties.
*/
public static boolean isGestureLauncherEnabled(Resources resources) {
- // For now, the only supported gesture is camera launch gesture, so whether to enable this
- // service equals to isCameraLaunchEnabled();
- return isCameraLaunchEnabled(resources);
+ return isCameraLaunchEnabled(resources) || isCameraDoubleTapPowerEnabled(resources);
+ }
+
+ public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive) {
+ boolean launched = false;
+ synchronized (this) {
+ if (!mCameraDoubleTapPowerEnabled) {
+ mLastPowerDownWhileNonInteractive = 0;
+ return false;
+ }
+ if (event.getEventTime() - mLastPowerDownWhileNonInteractive
+ < CAMERA_POWER_DOUBLE_TAP_TIME_MS) {
+ launched = true;
+ }
+ mLastPowerDownWhileNonInteractive = interactive ? 0 : event.getEventTime();
+ }
+ if (launched) {
+ Slog.i(TAG, "Power button double tap gesture detected, launching camera.");
+ launched = handleCameraLaunchGesture(false /* useWakelock */,
+ MetricsLogger.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE);
+ }
+ return launched;
+ }
+
+ /**
+ * @return true if camera was launched, false otherwise.
+ */
+ private boolean handleCameraLaunchGesture(boolean useWakelock, int logCategory) {
+ boolean userSetupComplete = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
+ if (!userSetupComplete) {
+ if (DBG) Slog.d(TAG, String.format(
+ "userSetupComplete = %s, ignoring camera launch gesture.",
+ userSetupComplete));
+ return false;
+ }
+ if (DBG) Slog.d(TAG, String.format(
+ "userSetupComplete = %s, performing camera launch gesture.",
+ userSetupComplete));
+
+ if (useWakelock) {
+ // Make sure we don't sleep too early
+ mWakeLock.acquire(500L);
+ }
+ StatusBarManagerInternal service = LocalServices.getService(
+ StatusBarManagerInternal.class);
+ service.onCameraLaunchGestureDetected();
+ MetricsLogger.action(mContext, logCategory);
+ return true;
}
private final BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
@@ -222,8 +303,9 @@ class GestureLauncherService extends SystemService {
if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
mUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
mContext.getContentResolver().unregisterContentObserver(mSettingObserver);
- registerContentObserver();
+ registerContentObservers();
updateCameraRegistered();
+ updateCameraDoubleTapPowerEnabled();
}
}
};
@@ -232,6 +314,7 @@ class GestureLauncherService extends SystemService {
public void onChange(boolean selfChange, android.net.Uri uri, int userId) {
if (userId == mUserId) {
updateCameraRegistered();
+ updateCameraDoubleTapPowerEnabled();
}
}
};
@@ -244,36 +327,17 @@ class GestureLauncherService extends SystemService {
return;
}
if (event.sensor == mCameraLaunchSensor) {
- handleCameraLaunchGesture(event);
- return;
- }
- }
-
- private void handleCameraLaunchGesture(SensorEvent event) {
- if (DBG) {
- float[] values = event.values;
- Slog.d(TAG, String.format("Received a camera launch event: " +
- "values=[%.4f, %.4f, %.4f].", values[0], values[1], values[2]));
- }
- boolean userSetupComplete = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
- if (!userSetupComplete) {
- if (DBG) Slog.d(TAG, String.format(
- "userSetupComplete = %s, ignoring camera launch gesture.",
- userSetupComplete));
+ if (DBG) {
+ float[] values = event.values;
+ Slog.d(TAG, String.format("Received a camera launch event: " +
+ "values=[%.4f, %.4f, %.4f].", values[0], values[1], values[2]));
+ }
+ if (handleCameraLaunchGesture(true /* useWakelock */,
+ MetricsLogger.ACTION_WIGGLE_CAMERA_GESTURE)) {
+ trackCameraLaunchEvent(event);
+ }
return;
}
- if (DBG) Slog.d(TAG, String.format(
- "userSetupComplete = %s, performing camera launch gesture.",
- userSetupComplete));
-
- // Make sure we don't sleep too early
- mWakeLock.acquire(500L);
- StatusBarManagerInternal service = LocalServices.getService(
- StatusBarManagerInternal.class);
- service.onCameraLaunchGestureDetected();
- trackCameraLaunchEvent(event);
- mWakeLock.release();
}
@Override
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index c7c5afd..fb461ae 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -118,6 +118,7 @@ import com.android.internal.R;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.ScreenShapeHelper;
import com.android.internal.widget.PointerLocationView;
+import com.android.server.GestureLauncherService;
import com.android.server.LocalServices;
import com.android.server.policy.keyguard.KeyguardServiceDelegate;
import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener;
@@ -126,7 +127,6 @@ import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
-import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
@@ -933,10 +933,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ GestureLauncherService gestureService = LocalServices.getService(
+ GestureLauncherService.class);
+ boolean gesturedServiceIntercepted = false;
+ if (gestureService != null) {
+ gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive);
+ }
+
// If the power key has still not yet been handled, then detect short
// press, long press, or multi press and decide what to do.
mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
- || mScreenshotChordVolumeUpKeyTriggered;
+ || mScreenshotChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
if (!mPowerKeyHandled) {
if (interactive) {
// When interactive, we're already awake.