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

Commit db1b4e6e authored by Roman Birg's avatar Roman Birg
Browse files

framework: move device key handler logic, fix gesture camera launch



In order to make device camera gestures behave the same way as launching
the camera by double tapping the power button, route DeviceKeyHandler
logic through the GestureLauncherService.

A callback is used in order to avoid publishing the
GestureLauncherService into the System service registry, because the
KeyHandler code cannot directly access services local to the system
process.

OPO-427

Change-Id: I2a8860b278f65ccf31bfee151513d8a23ab746c5
Signed-off-by: default avatarRoman Birg <roman@cyngn.com>
parent e486d56b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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_SCREEN_GESTURE = 2;

    private Context mContext;
    private IStatusBarService mService;
+9 −1
Original line number Diff line number Diff line
@@ -20,7 +20,15 @@ public interface DeviceKeyHandler {
     * this special keys prior to pass the key to the active app.
     *
     * @param event The key event to be handled
     * @param callback callback into the gesture launcher to route common actions
     * @return If the event is consume
     */
    public boolean handleKeyEvent(KeyEvent event);
    public boolean handleKeyEvent(KeyEvent event, DeviceHandlerCallback callback);

    interface DeviceHandlerCallback {
        /**
         * Let the gesture launcher service know that the device wants the camera launched
         */
        void onScreenCameraGesture();
    }
}
+55 −2
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.app.ActivityManager;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
@@ -38,8 +39,13 @@ import android.util.Slog;
import android.view.KeyEvent;

import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.DeviceKeyHandler;
import com.android.server.statusbar.StatusBarManagerInternal;

import dalvik.system.DexClassLoader;

import java.lang.reflect.Constructor;

/**
 * The service that listens for gestures detected in sensor firmware and starts the intent
 * accordingly.
@@ -47,7 +53,8 @@ import com.android.server.statusbar.StatusBarManagerInternal;
 * added.</p>
 * @hide
 */
public class GestureLauncherService extends SystemService {
public class GestureLauncherService extends SystemService
        implements DeviceKeyHandler.DeviceHandlerCallback {
    private static final boolean DBG = false;
    private static final String TAG = "GestureLauncherService";

@@ -105,6 +112,8 @@ public class GestureLauncherService extends SystemService {
    private boolean mCameraDoubleTapPowerEnabled;
    private long mLastPowerDown;

    private DeviceKeyHandler mDeviceKeyHandler;

    public GestureLauncherService(Context context) {
        super(context);
        mContext = context;
@@ -132,6 +141,30 @@ public class GestureLauncherService extends SystemService {
            mUserId = ActivityManager.getCurrentUser();
            mContext.registerReceiver(mUserReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED));
            registerContentObservers();

            String deviceKeyHandlerLib = mContext.getResources().getString(
                    com.android.internal.R.string.config_deviceKeyHandlerLib);

            String deviceKeyHandlerClass = mContext.getResources().getString(
                    com.android.internal.R.string.config_deviceKeyHandlerClass);

            if (!deviceKeyHandlerLib.isEmpty() && !deviceKeyHandlerClass.isEmpty()) {
                DexClassLoader loader =  new DexClassLoader(deviceKeyHandlerLib,
                        new ContextWrapper(mContext).getCacheDir().getAbsolutePath(),
                        null,
                        ClassLoader.getSystemClassLoader());
                try {
                    Class<?> klass = loader.loadClass(deviceKeyHandlerClass);
                    Constructor<?> constructor = klass.getConstructor(Context.class);
                    mDeviceKeyHandler = (DeviceKeyHandler) constructor.newInstance(
                            mContext);
                    if(DBG) Slog.d(TAG, "Device key handler loaded");
                } catch (Exception e) {
                    Slog.w(TAG, "Could not instantiate device key handler "
                            + deviceKeyHandlerClass + " from class "
                            + deviceKeyHandlerLib, e);
                }
            }
        }
    }

@@ -243,11 +276,19 @@ public class GestureLauncherService extends SystemService {
                com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled);
    }

    public static boolean isKeyHandlerPresent(Resources resources) {
        return !resources.getString(com.android.internal.R.string.config_deviceKeyHandlerLib)
                .isEmpty()
                && !resources.getString(com.android.internal.R.string.config_deviceKeyHandlerClass)
                .isEmpty();
    }

    /**
     * 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)
                || isKeyHandlerPresent(resources);
    }

    public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive) {
@@ -326,6 +367,18 @@ public class GestureLauncherService extends SystemService {
        }
    };

    public boolean deviceKeyHandlerEvent(KeyEvent event) {
        if (mDeviceKeyHandler != null) {
            return mDeviceKeyHandler.handleKeyEvent(event, this);
        }
        return false;
    }

    @Override
    public void onScreenCameraGesture() {
        handleCameraLaunchGesture(true, StatusBarManager.CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE);
    }

    private final class GestureEventListener implements SensorEventListener {
        @Override
        public void onSensorChanged(SensorEvent event) {
+11 −44
Original line number Diff line number Diff line
@@ -307,8 +307,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
    static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;

    private DeviceKeyHandler mDeviceKeyHandler;

    /**
     * Lock protecting internal state.  Must not call out into window
     * manager with lock held.  (This lock will be acquired in places
@@ -1886,30 +1884,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        mWindowManagerInternal.registerAppTransitionListener(
                mStatusBarController.getAppTransitionListener());

        String deviceKeyHandlerLib = mContext.getResources().getString(
                com.android.internal.R.string.config_deviceKeyHandlerLib);

        String deviceKeyHandlerClass = mContext.getResources().getString(
                com.android.internal.R.string.config_deviceKeyHandlerClass);

        if (!deviceKeyHandlerLib.isEmpty() && !deviceKeyHandlerClass.isEmpty()) {
            DexClassLoader loader =  new DexClassLoader(deviceKeyHandlerLib,
                    new ContextWrapper(mContext).getCacheDir().getAbsolutePath(),
                    null,
                    ClassLoader.getSystemClassLoader());
            try {
                Class<?> klass = loader.loadClass(deviceKeyHandlerClass);
                Constructor<?> constructor = klass.getConstructor(Context.class);
                mDeviceKeyHandler = (DeviceKeyHandler) constructor.newInstance(
                        mContext);
                if(DEBUG) Slog.d(TAG, "Device key handler loaded");
            } catch (Exception e) {
                Slog.w(TAG, "Could not instantiate device key handler "
                        + deviceKeyHandlerClass + " from class "
                        + deviceKeyHandlerLib, e);
            }
        }

    }

    private void updateKeyAssignments() {
@@ -3639,16 +3613,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
            return -1;
        }

        // Specific device key handling
        if (mDeviceKeyHandler != null) {
            try {
                // The device only should consume known keys.
                if (mDeviceKeyHandler.handleKeyEvent(event)) {
        GestureLauncherService gestureService = LocalServices.getService(
                GestureLauncherService.class);
        if (gestureService != null) {
            if (gestureService.deviceKeyHandlerEvent(event)) {
                return -1;
            }
            } catch (Exception e) {
                Slog.w(TAG, "Could not dispatch event to device key handler", e);
            }
        }

        // Reserve all the META modifier combos for system behavior
@@ -5670,16 +5640,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
                && event.getRepeatCount() == 0;

        // Specific device key handling
        if (mDeviceKeyHandler != null) {
            try {
                // The device only should consume known keys.
                if (mDeviceKeyHandler.handleKeyEvent(event)) {

        GestureLauncherService gestureService = LocalServices.getService(
                GestureLauncherService.class);
        if (gestureService != null) {
            if (gestureService.deviceKeyHandlerEvent(event)) {
                return 0;
            }
            } catch (Exception e) {
                Slog.w(TAG, "Could not dispatch event to device key handler", e);
            }
        }

        // Handle special keys.