From a41381660c960844658b6d16f4b6539d7edf56c8 Mon Sep 17 00:00:00 2001 From: Jonathan Solnit Date: Wed, 10 May 2017 21:06:04 -0700 Subject: [PATCH] Add camera lift trigger to GestureLauncherService Add registration for the camera lift trigger sensor and handling for its events to GestureLauncherService Test: Confirmed camera launches on lift gesture if setting is enabled (and other pieces are in place) Change-Id: Ibfad2040409d86af2d019e2ce97ab546bef9ba78 --- core/java/android/app/StatusBarManager.java | 1 + core/res/res/values/config.xml | 6 + core/res/res/values/symbols.xml | 2 + .../phone/KeyguardBottomAreaView.java | 1 + .../phone/NotificationPanelView.java | 2 + proto/src/metrics_constants.proto | 5 + .../server/GestureLauncherService.java | 130 ++++++++++++++++-- .../server/GestureLauncherServiceTest.java | 4 +- 8 files changed, 135 insertions(+), 16 deletions(-) diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index e57a9b5231e3e..ab301bdedcac3 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -92,6 +92,7 @@ public class StatusBarManager { public static final int CAMERA_LAUNCH_SOURCE_WIGGLE = 0; public static final int CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = 1; + public static final int CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER = 2; private Context mContext; private IStatusBarService mService; diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 5abc47d78c386..b94faf750f908 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2933,4 +2933,10 @@ 67 + + + -1 + + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index c688414fb8924..cf10c90479786 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2518,6 +2518,8 @@ + + diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index 41a60e24e7005..037e901d05691 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -100,6 +100,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL public static final String CAMERA_LAUNCH_SOURCE_AFFORDANCE = "lockscreen_affordance"; public static final String CAMERA_LAUNCH_SOURCE_WIGGLE = "wiggle_gesture"; public static final String CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = "power_double_tap"; + public static final String CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER = "lift_to_launch_ml"; public static final String EXTRA_CAMERA_LAUNCH_SOURCE = "com.android.systemui.camera_launch_source"; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index c52c11af4de50..fc274831de675 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -2363,6 +2363,8 @@ public class NotificationPanelView extends PanelView implements mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP; } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE) { mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_WIGGLE; + } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER) { + mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER; } else { // Default. diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index b755dd6d17d7e..818f47862b53b 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -3974,6 +3974,11 @@ message MetricsEvent { // OPEN: Settings > Battery > High Usage DIALOG_HANDLE_ANOMALY = 988; + // ACTION: Camera lift gesture + // CATEGORY: GLOBAL_SYSTEM_UI + // OS: O + ACTION_CAMERA_LIFT_TRIGGER = 989; + // Add new aosp constants above this line. // END OF AOSP CONSTANTS } diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java index 2e2ddbad2bdb7..6c44cc83a27d2 100644 --- a/services/core/java/com/android/server/GestureLauncherService.java +++ b/services/core/java/com/android/server/GestureLauncherService.java @@ -71,14 +71,18 @@ public class GestureLauncherService extends SystemService { /** The listener that receives the gesture event. */ private final GestureEventListener mGestureListener = new GestureEventListener(); + private final CameraLiftTriggerEventListener mCameraLiftTriggerListener = + new CameraLiftTriggerEventListener(); private Sensor mCameraLaunchSensor; + private Sensor mCameraLiftTriggerSensor; private Context mContext; private final MetricsLogger mMetricsLogger; /** The wake lock held when a gesture is detected. */ private WakeLock mWakeLock; - private boolean mRegistered; + private boolean mCameraLaunchRegistered; + private boolean mCameraLiftRegistered; private int mUserId; // Below are fields used for event logging only. @@ -161,6 +165,9 @@ public class GestureLauncherService extends SystemService { mContext.getContentResolver().registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED), false, mSettingObserver, mUserId); + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.CAMERA_LIFT_TRIGGER_ENABLED), + false, mSettingObserver, mUserId); } private void updateCameraRegistered() { @@ -170,6 +177,12 @@ public class GestureLauncherService extends SystemService { } else { unregisterCameraLaunchGesture(); } + + if (isCameraLiftTriggerSettingEnabled(mContext, mUserId)) { + registerCameraLiftTrigger(resources); + } else { + unregisterCameraLiftTrigger(); + } } @VisibleForTesting @@ -181,8 +194,8 @@ public class GestureLauncherService extends SystemService { } private void unregisterCameraLaunchGesture() { - if (mRegistered) { - mRegistered = false; + if (mCameraLaunchRegistered) { + mCameraLaunchRegistered = false; mCameraGestureOnTimeMs = 0L; mCameraGestureLastEventTime = 0L; mCameraGestureSensor1LastOnTimeMs = 0; @@ -199,7 +212,7 @@ public class GestureLauncherService extends SystemService { * Registers for the camera launch gesture. */ private void registerCameraLaunchGesture(Resources resources) { - if (mRegistered) { + if (mCameraLaunchRegistered) { return; } mCameraGestureOnTimeMs = SystemClock.elapsedRealtime(); @@ -209,7 +222,7 @@ public class GestureLauncherService extends SystemService { int cameraLaunchGestureId = resources.getInteger( com.android.internal.R.integer.config_cameraLaunchGestureSensorType); if (cameraLaunchGestureId != -1) { - mRegistered = false; + mCameraLaunchRegistered = false; String sensorName = resources.getString( com.android.internal.R.string.config_cameraLaunchGestureSensorStringType); mCameraLaunchSensor = sensorManager.getDefaultSensor( @@ -221,7 +234,7 @@ public class GestureLauncherService extends SystemService { // makes the code more robust. if (mCameraLaunchSensor != null) { if (sensorName.equals(mCameraLaunchSensor.getStringType())) { - mRegistered = sensorManager.registerListener(mGestureListener, + mCameraLaunchRegistered = sensorManager.registerListener(mGestureListener, mCameraLaunchSensor, 0); } else { String message = String.format("Wrong configuration. Sensor type and sensor " @@ -230,12 +243,61 @@ public class GestureLauncherService extends SystemService { throw new RuntimeException(message); } } - if (DBG) Slog.d(TAG, "Camera launch sensor registered: " + mRegistered); + if (DBG) Slog.d(TAG, "Camera launch sensor registered: " + mCameraLaunchRegistered); } else { if (DBG) Slog.d(TAG, "Camera launch sensor is not specified."); } } + private void unregisterCameraLiftTrigger() { + if (mCameraLiftRegistered) { + mCameraLiftRegistered = false; + + SensorManager sensorManager = (SensorManager) mContext.getSystemService( + Context.SENSOR_SERVICE); + sensorManager.unregisterListener(mCameraLiftTriggerListener); + } + } + + /** + * Registers for the camera lift trigger. + */ + private void registerCameraLiftTrigger(Resources resources) { + if (mCameraLiftRegistered) { + return; + } + SensorManager sensorManager = (SensorManager) mContext.getSystemService( + Context.SENSOR_SERVICE); + int cameraLiftTriggerId = resources.getInteger( + com.android.internal.R.integer.config_cameraLiftTriggerSensorType); + if (cameraLiftTriggerId != -1) { + mCameraLiftRegistered = false; + String sensorName = resources.getString( + com.android.internal.R.string.config_cameraLiftTriggerSensorStringType); + mCameraLiftTriggerSensor = sensorManager.getDefaultSensor( + cameraLiftTriggerId, + false /*wakeUp*/); + + // Compare the camera lift trigger string type to that in the resource file to make + // sure we are registering the correct sensor. This is redundant check, it + // makes the code more robust. + if (mCameraLiftTriggerSensor != null) { + if (sensorName.equals(mCameraLiftTriggerSensor.getStringType())) { + mCameraLiftRegistered = sensorManager.registerListener(mCameraLiftTriggerListener, + mCameraLiftTriggerSensor, 0); + } else { + String message = String.format("Wrong configuration. Sensor type and sensor " + + "string type don't match: %s in resources, %s in the sensor.", + sensorName, mCameraLiftTriggerSensor.getStringType()); + throw new RuntimeException(message); + } + } + if (DBG) Slog.d(TAG, "Camera lift trigger sensor registered: " + mCameraLiftRegistered); + } else { + if (DBG) Slog.d(TAG, "Camera lift trigger sensor is not specified."); + } + } + public static boolean isCameraLaunchSettingEnabled(Context context, int userId) { return isCameraLaunchEnabled(context.getResources()) && (Settings.Secure.getIntForUser(context.getContentResolver(), @@ -248,6 +310,12 @@ public class GestureLauncherService extends SystemService { Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 0, userId) == 0); } + public static boolean isCameraLiftTriggerSettingEnabled(Context context, int userId) { + return isCameraLiftTriggerEnabled(context.getResources()) + && (Settings.Secure.getIntForUser(context.getContentResolver(), + Settings.Secure.CAMERA_LIFT_TRIGGER_ENABLED, 0, userId) != 0); + } + /** * Whether to enable the camera launch gesture. */ @@ -263,11 +331,18 @@ public class GestureLauncherService extends SystemService { com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled); } + public static boolean isCameraLiftTriggerEnabled(Resources resources) { + boolean configSet = resources.getInteger( + com.android.internal.R.integer.config_cameraLiftTriggerSensorType) != -1; + return configSet; + } + /** * Whether GestureLauncherService should be enabled according to system properties. */ public static boolean isGestureLauncherEnabled(Resources resources) { - return isCameraLaunchEnabled(resources) || isCameraDoubleTapPowerEnabled(resources); + return isCameraLaunchEnabled(resources) || isCameraDoubleTapPowerEnabled(resources) || + isCameraLiftTriggerEnabled(resources); } public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive, @@ -296,7 +371,7 @@ public class GestureLauncherService extends SystemService { if (launched) { Slog.i(TAG, "Power button double tap gesture detected, launching camera. Interval=" + powerTapInterval + "ms"); - launched = handleCameraLaunchGesture(false /* useWakelock */, + launched = handleCameraGesture(false /* useWakelock */, StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); if (launched) { mMetricsLogger.action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, @@ -313,17 +388,17 @@ public class GestureLauncherService extends SystemService { * @return true if camera was launched, false otherwise. */ @VisibleForTesting - boolean handleCameraLaunchGesture(boolean useWakelock, int source) { + boolean handleCameraGesture(boolean useWakelock, int source) { boolean userSetupComplete = Settings.Secure.getIntForUser(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0; if (!userSetupComplete) { if (DBG) Slog.d(TAG, String.format( - "userSetupComplete = %s, ignoring camera launch gesture.", + "userSetupComplete = %s, ignoring camera gesture.", userSetupComplete)); return false; } if (DBG) Slog.d(TAG, String.format( - "userSetupComplete = %s, performing camera launch gesture.", + "userSetupComplete = %s, performing camera gesture.", userSetupComplete)); if (useWakelock) { @@ -361,7 +436,7 @@ public class GestureLauncherService extends SystemService { private final class GestureEventListener implements SensorEventListener { @Override public void onSensorChanged(SensorEvent event) { - if (!mRegistered) { + if (!mCameraLaunchRegistered) { if (DBG) Slog.d(TAG, "Ignoring gesture event because it's unregistered."); return; } @@ -371,7 +446,7 @@ public class GestureLauncherService extends SystemService { Slog.d(TAG, String.format("Received a camera launch event: " + "values=[%.4f, %.4f, %.4f].", values[0], values[1], values[2])); } - if (handleCameraLaunchGesture(true /* useWakelock */, + if (handleCameraGesture(true /* useWakelock */, StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE)) { mMetricsLogger.action(MetricsEvent.ACTION_WIGGLE_CAMERA_GESTURE); trackCameraLaunchEvent(event); @@ -430,4 +505,31 @@ public class GestureLauncherService extends SystemService { mCameraLaunchLastEventExtra = extra; } } + + private final class CameraLiftTriggerEventListener implements SensorEventListener { + @Override + public void onSensorChanged(SensorEvent event) { + if (!mCameraLiftRegistered) { + if (DBG) Slog.d(TAG, "Ignoring camera lift event because it's unregistered."); + return; + } + if (event.sensor == mCameraLiftTriggerSensor) { + if (DBG) { + float[] values = event.values; + Slog.d(TAG, String.format("Received a camera lift trigger event: " + + "values=[%.4f].", values[0])); + } + if (handleCameraGesture(true /* useWakelock */, + StatusBarManager.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER)) { + MetricsLogger.action(mContext, MetricsEvent.ACTION_CAMERA_LIFT_TRIGGER); + } + return; + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + // Ignored. + } + } } diff --git a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java index f281bd7e42614..33e4165718a55 100644 --- a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java @@ -154,7 +154,7 @@ public class GestureLauncherServiceTest { withUserSetupCompleteValue(true); boolean useWakeLock = false; - assertTrue(mGestureLauncherService.handleCameraLaunchGesture(useWakeLock, FAKE_SOURCE)); + assertTrue(mGestureLauncherService.handleCameraGesture(useWakeLock, FAKE_SOURCE)); verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected(FAKE_SOURCE); } @@ -163,7 +163,7 @@ public class GestureLauncherServiceTest { withUserSetupCompleteValue(false); boolean useWakeLock = false; - assertFalse(mGestureLauncherService.handleCameraLaunchGesture(useWakeLock, FAKE_SOURCE)); + assertFalse(mGestureLauncherService.handleCameraGesture(useWakeLock, FAKE_SOURCE)); } @Test