From c6cd1f9a83b2807ef7434b6775a07e1e9208d4e0 Mon Sep 17 00:00:00 2001 From: Zhentao Sun Date: Tue, 21 Jul 2015 17:43:53 -0700 Subject: [PATCH] Added service that listens for gestures. Added the GestureLauncherService that listens for camera launch gesture and starts the camera app. OEMs need to specify the sensor type of the camera launch gesture in their overlays. In the future, we can add more gesture support in this service. Change-Id: I0769e7ca71e08bd9159aacf29bdcefd316efd2f0 --- core/res/res/values/config.xml | 5 + core/res/res/values/symbols.xml | 3 + .../server/GestureLauncherService.java | 185 ++++++++++++++++++ .../java/com/android/server/SystemServer.java | 5 + 4 files changed, 198 insertions(+) create mode 100644 services/core/java/com/android/server/GestureLauncherService.java diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 06b6389f3bea2..531f109488357 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2269,4 +2269,9 @@ + + -1 + + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index fe82b8cb0d201..5087b2c8bc8c6 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2315,4 +2315,7 @@ + + + diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java new file mode 100644 index 0000000000000..d7b0765044661 --- /dev/null +++ b/services/core/java/com/android/server/GestureLauncherService.java @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2015 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.server; + +import android.app.KeyguardManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.res.Resources; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.os.PowerManager; +import android.os.Vibrator; +import android.os.PowerManager.WakeLock; +import android.os.SystemProperties; +import android.provider.MediaStore; +import android.util.Slog; + +/** + * The service that listens for gestures detected in sensor firmware and starts the intent + * accordingly. + *

For now, only camera launch gesture is supported, and in the future, more gestures can be + * added.

+ * @hide + */ +class GestureLauncherService extends SystemService { + private static final boolean DBG = false; + private static final String TAG = "GestureLauncherService"; + + /** The listener that receives the gesture event. */ + private final GestureEventListener mGestureListener = new GestureEventListener(); + + private Sensor mCameraLaunchSensor; + private Vibrator mVibrator; + private KeyguardManager mKeyGuard; + private Context mContext; + + /** The wake lock held when a gesture is detected. */ + private WakeLock mWakeLock; + + public GestureLauncherService(Context context) { + super(context); + mContext = context; + } + + public void onStart() { + // Nothing to publish. + } + + public void onBootPhase(int phase) { + if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { + Resources resources = mContext.getResources(); + if (!isGestureLauncherEnabled(resources)) { + if (DBG) Slog.d(TAG, "Gesture launcher is disabled in system properties."); + return; + } + + mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); + mKeyGuard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); + PowerManager powerManager = (PowerManager) mContext.getSystemService( + Context.POWER_SERVICE); + mWakeLock = powerManager.newWakeLock( + PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, + "GestureLauncherService"); + if (isCameraLaunchEnabled(resources)) { + registerCameraLaunchGesture(resources); + } + } + } + + /** + * Registers for the camera launch gesture. + */ + private void registerCameraLaunchGesture(Resources resources) { + SensorManager sensorManager = (SensorManager) mContext.getSystemService( + Context.SENSOR_SERVICE); + int cameraLaunchGestureId = resources.getInteger( + com.android.internal.R.integer.config_cameraLaunchGestureSensorType); + if (cameraLaunchGestureId != -1) { + boolean registered = false; + String sensorName = resources.getString( + com.android.internal.R.string.config_cameraLaunchGestureSensorStringType); + mCameraLaunchSensor = sensorManager.getDefaultSensor( + cameraLaunchGestureId, + true /*wakeUp*/); + + // Compare the camera gesture 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 (mCameraLaunchSensor != null) { + if (sensorName.equals(mCameraLaunchSensor.getStringType())) { + registered = sensorManager.registerListener(mGestureListener, + mCameraLaunchSensor, 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, mCameraLaunchSensor.getStringType()); + throw new RuntimeException(message); + } + } + if (DBG) Slog.d(TAG, "Camera launch sensor registered: " + registered); + } else { + if (DBG) Slog.d(TAG, "Camera launch sensor is not specified."); + } + } + + /** + * Whether to enable the camera launch gesture. + */ + public static boolean isCameraLaunchEnabled(Resources resources) { + boolean configSet = resources.getInteger( + com.android.internal.R.integer.config_cameraLaunchGestureSensorType) != -1; + return configSet && + !SystemProperties.getBoolean("gesture.disable_camera_launch", false); + } + + /** + * 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); + } + + private final class GestureEventListener implements SensorEventListener { + @Override + public void onSensorChanged(SensorEvent event) { + if (event.sensor == mCameraLaunchSensor) { + handleCameraLaunchGesture(); + return; + } + } + + private void handleCameraLaunchGesture() { + if (DBG) Slog.d(TAG, "Received a camera launch event."); + boolean locked = mKeyGuard != null && mKeyGuard.inKeyguardRestrictedInputMode(); + String action = locked + ? MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE + : MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA; + Intent intent = new Intent(action); + PackageManager pm = mContext.getPackageManager(); + ResolveInfo componentInfo = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); + if (componentInfo == null) { + if (DBG) Slog.d(TAG, "Couldn't find an app to process the camera intent."); + return; + } + + if (mVibrator != null && mVibrator.hasVibrator()) { + mVibrator.vibrate(1000L); + } + + // Turn on the screen before the camera launches. + mWakeLock.acquire(500L); + intent.setComponent(new ComponentName(componentInfo.activityInfo.packageName, + componentInfo.activityInfo.name)); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + mWakeLock.release(); + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + // Ignored. + } + } +} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 014527b0a24e6..f1fac9ea9e854 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -857,6 +857,11 @@ public final class SystemServer { if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_VOICE_RECOGNIZERS)) { mSystemServiceManager.startService(VOICE_RECOGNITION_MANAGER_SERVICE_CLASS); } + + if (GestureLauncherService.isGestureLauncherEnabled(context.getResources())) { + Slog.i(TAG, "Gesture Launcher Service"); + mSystemServiceManager.startService(GestureLauncherService.class); + } } try {