Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f26a9a20 authored by Zhentao Sun's avatar Zhentao Sun Committed by Android Git Automerger
Browse files

am c6cd1f9a: Added service that listens for gestures.

* commit 'c6cd1f9a':
  Added service that listens for gestures.
parents 2237c32f c6cd1f9a
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -2269,4 +2269,9 @@
    <string-array name="config_cell_retries_per_error_code">
    </string-array>

    <!-- The OEM specified sensor type for the gesture to launch the camear app. -->
    <integer name="config_cameraLaunchGestureSensorType">-1</integer>
    <!-- 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>
</resources>
+3 −0
Original line number Diff line number Diff line
@@ -2315,4 +2315,7 @@
  <java-symbol type="array" name="config_cell_retries_per_error_code" />
  <java-symbol type="drawable" name="ic_more_items" />

  <!-- Gesture -->
  <java-symbol type="integer" name="config_cameraLaunchGestureSensorType" />
  <java-symbol type="string" name="config_cameraLaunchGestureSensorStringType" />
</resources>
+185 −0
Original line number Diff line number Diff line
/*
 * 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.
 * <p>For now, only camera launch gesture is supported, and in the future, more gestures can be
 * added.</p>
 * @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.
        }
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -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 {