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
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index e57a9b5..ab301bd 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -92,6 +92,7 @@
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 5abc47d..b94faf7 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2933,4 +2933,10 @@
<!-- Volume level of in-call notification tone playback,
relative to the overall voice call stream volume [0..100] -->
<integer name="config_inCallNotificationVolumeRelative">67</integer>
+
+ <!-- The OEM specified sensor type for the lift trigger to launch the camera app. -->
+ <integer name="config_cameraLiftTriggerSensorType">-1</integer>
+ <!-- The OEM specified sensor string type for the gesture to launch camera app, this value
+ must match the value of config_cameraLiftTriggerSensorType in OEM's HAL -->
+ <string translatable="false" name="config_cameraLiftTriggerSensorStringType"></string>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c688414..cf10c90 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2518,6 +2518,8 @@
<java-symbol type="integer" name="config_cameraLaunchGestureSensorType" />
<java-symbol type="string" name="config_cameraLaunchGestureSensorStringType" />
<java-symbol type="bool" name="config_cameraDoubleTapPowerGestureEnabled" />
+ <java-symbol type="integer" name="config_cameraLiftTriggerSensorType" />
+ <java-symbol type="string" name="config_cameraLiftTriggerSensorStringType" />
<java-symbol type="drawable" name="platlogo_m" />
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 41a60e2..037e901 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 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 c52c11a..fc27483 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 @@
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 b755dd6..818f478 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3974,6 +3974,11 @@
// 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 2e2ddba..6c44cc8 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -71,14 +71,18 @@
/** 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 @@
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 @@
} else {
unregisterCameraLaunchGesture();
}
+
+ if (isCameraLiftTriggerSettingEnabled(mContext, mUserId)) {
+ registerCameraLiftTrigger(resources);
+ } else {
+ unregisterCameraLiftTrigger();
+ }
}
@VisibleForTesting
@@ -181,8 +194,8 @@
}
private void unregisterCameraLaunchGesture() {
- if (mRegistered) {
- mRegistered = false;
+ if (mCameraLaunchRegistered) {
+ mCameraLaunchRegistered = false;
mCameraGestureOnTimeMs = 0L;
mCameraGestureLastEventTime = 0L;
mCameraGestureSensor1LastOnTimeMs = 0;
@@ -199,7 +212,7 @@
* Registers for the camera launch gesture.
*/
private void registerCameraLaunchGesture(Resources resources) {
- if (mRegistered) {
+ if (mCameraLaunchRegistered) {
return;
}
mCameraGestureOnTimeMs = SystemClock.elapsedRealtime();
@@ -209,7 +222,7 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
* @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 @@
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 @@
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 @@
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 f281bd7..33e4165 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 @@
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 @@
withUserSetupCompleteValue(false);
boolean useWakeLock = false;
- assertFalse(mGestureLauncherService.handleCameraLaunchGesture(useWakeLock, FAKE_SOURCE));
+ assertFalse(mGestureLauncherService.handleCameraGesture(useWakeLock, FAKE_SOURCE));
}
@Test