diff options
-rw-r--r-- | core/java/android/provider/Settings.java | 9 | ||||
-rw-r--r-- | core/java/com/android/internal/logging/MetricsLogger.java | 2 | ||||
-rwxr-xr-x | core/res/res/values/config.xml | 4 | ||||
-rwxr-xr-x | core/res/res/values/symbols.xml | 1 | ||||
-rw-r--r-- | services/core/java/com/android/server/GestureLauncherService.java | 140 | ||||
-rw-r--r-- | services/core/java/com/android/server/policy/PhoneWindowManager.java | 11 |
6 files changed, 127 insertions, 40 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 78be3cd..2053dbe 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 d7658d1..f711c80 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2290,4 +2290,8 @@ <!-- The OEM specified sensor string type for the gesture to launch camera app, this value 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> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 4c8e55e..0e85f43 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2323,6 +2323,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="drawable" name="platlogo_m" /> </resources> 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 34737c1..d7e3c54 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -117,6 +117,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; @@ -125,7 +126,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; @@ -931,10 +931,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. |