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

Commit a6719454 authored by Bruno Martins's avatar Bruno Martins Committed by Michael Bestas
Browse files

Support for device specific key handlers



This is a squash commit of the following changes,
only modified for the new SDK.

  Author: Alexander Hofbauer <alex@derhofbauer.at>
  Date:   Thu Apr 12 01:24:24 2012 +0200

      Dispatch keys to a device specific key handler

      Injects a device key handler into the input path to handle additional
      keys (as found on some docks with a hardware keyboard).

      Configurable via overlay settings config_deviceKeyHandlerLib and
      config_deviceKeyHandlerClass.

      Change-Id: I6678c89c7530fdb1d4d516ba4f1d2c9e30ce79a4

  Author: Jorge Ruesga <jorge@ruesga.com>
  Date:   Thu Jan 24 02:34:49 2013 +0100

      DeviceKeyHandle: The device should consume only known keys

      When the device receive the key, only should consume it if the device
      know about the key. Otherwise, the key must be handle by the active app.
      Also make mDeviceKeyHandler private (is not useful outside this class)

      Change-Id: I4b9ea57b802e8c8c88c8b93a63d510f5952b0700
      Signed-off-by: default avatarJorge Ruesga <jorge@ruesga.com>

  Author: Danesh Mondegarian <daneshm90@gmail.com>
  Date:   Sun Oct 20 00:34:48 2013 -0700

      DeviceKeyHandler : Allow handling keyevents while screen off

      Some devices require the keyevents to be processed while the screen
      is off, this patchset addresses that by moving the filter up in the call
      hierarchy.

      Change-Id: If71beecc81aa5e453dcd08aba72b7bea5c210590

  Author: Steve Kondik <steve@cyngn.com>
  Date:   Sun Sep 11 00:49:41 2016 -0700

      policy: Use PathClassLoader for loading the keyhandler

       * Fix crash on start due to getCacheDir throwing an exception.
       * We can't do this anymore due to the new storage/crypto in N.

      Change-Id: I28426a5df824460ebc74aa19068192adb00d4f7c

  Author: Zhao Wei Liew <zhaoweiliew@gmail.com>
  Date:   Sun Nov 20 08:20:15 2016 +0800

      PhoneWindowManager: Support multiple key handlers

      Convert the string overlay to a string-array overlay
      to allow devices to specify an array of key handlers.

      Note that the keyhandlers towards the start of the
      array take precedence when loading.

      Change-Id: Iaaab737f1501a97d7016d8d519ccf127ca059218

  Author: Paul Keith <javelinanddart@gmail.com>
  Date:   Thu Nov 23 21:47:51 2017 +0100

      fw/b: Return a KeyEvent instead of a boolean in KeyHandler

      * Allows handlers to modify the event before sending it off
        to another KeyHandler class, to handle things like rotation

      Change-Id: I481107e050f6323c5897260a5d241e64b4e031ac

Change-Id: Ie65a89cd7efd645622d99d47699df847bc3ad96b
parent 3d3a3147
Loading
Loading
Loading
Loading
+31 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2012 The CyanogenMod 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.internal.os;

import android.view.KeyEvent;

public interface DeviceKeyHandler {

    /**
     * Invoked when an unknown key was detected by the system, letting the device handle
     * this special keys prior to pass the key to the active app.
     *
     * @param event The key event to be handled
     * @return null if event is consumed, KeyEvent to be handled otherwise
     */
    public KeyEvent handleKeyEvent(KeyEvent event);
}
+56 −0
Original line number Original line Diff line number Diff line
@@ -232,6 +232,7 @@ import android.view.inputmethod.InputMethodManagerInternal;
import com.android.internal.R;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.DeviceKeyHandler;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
import com.android.internal.policy.IShortcutService;
import com.android.internal.policy.PhoneWindow;
import com.android.internal.policy.PhoneWindow;
@@ -252,8 +253,12 @@ import java.io.File;
import java.io.FileReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
import java.util.List;


import dalvik.system.PathClassLoader;

/**
/**
 * WindowManagerPolicy implementation for the Android phone UI.  This
 * WindowManagerPolicy implementation for the Android phone UI.  This
 * introduces a new method suffix, Lp, for an internal lock of the
 * introduces a new method suffix, Lp, for an internal lock of the
@@ -806,6 +811,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {


    private final MutableBoolean mTmpBoolean = new MutableBoolean(false);
    private final MutableBoolean mTmpBoolean = new MutableBoolean(false);


    private final List<DeviceKeyHandler> mDeviceKeyHandlers = new ArrayList<>();

    private static final int MSG_ENABLE_POINTER_LOCATION = 1;
    private static final int MSG_ENABLE_POINTER_LOCATION = 1;
    private static final int MSG_DISABLE_POINTER_LOCATION = 2;
    private static final int MSG_DISABLE_POINTER_LOCATION = 2;
    private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
    private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
@@ -2151,6 +2158,28 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                        mWindowManagerFuncs.notifyKeyguardTrustedChanged();
                        mWindowManagerFuncs.notifyKeyguardTrustedChanged();
                    }
                    }
                });
                });

        final Resources res = mContext.getResources();
        final String[] deviceKeyHandlerLibs = res.getStringArray(
                org.lineageos.platform.internal.R.array.config_deviceKeyHandlerLibs);
        final String[] deviceKeyHandlerClasses = res.getStringArray(
                org.lineageos.platform.internal.R.array.config_deviceKeyHandlerClasses);

        for (int i = 0;
                i < deviceKeyHandlerLibs.length && i < deviceKeyHandlerClasses.length; i++) {
            try {
                PathClassLoader loader = new PathClassLoader(
                        deviceKeyHandlerLibs[i], getClass().getClassLoader());
                Class<?> klass = loader.loadClass(deviceKeyHandlerClasses[i]);
                Constructor<?> constructor = klass.getConstructor(Context.class);
                mDeviceKeyHandlers.add((DeviceKeyHandler) constructor.newInstance(mContext));
            } catch (Exception e) {
                Slog.w(TAG, "Could not instantiate device key handler "
                        + deviceKeyHandlerLibs[i] + " from class "
                        + deviceKeyHandlerClasses[i], e);
            }
        }
        if (DEBUG) Slog.d(TAG, "" + mDeviceKeyHandlers.size() + " device key handlers loaded");
    }
    }


    /**
    /**
@@ -3791,6 +3820,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
            return -1;
            return -1;
        }
        }


        // Specific device key handling
        if (dispatchKeyToKeyHandlers(event)) {
            return -1;
        }

        if (down) {
        if (down) {
            long shortcutCode = keyCode;
            long shortcutCode = keyCode;
            if (event.isCtrlPressed()) {
            if (event.isCtrlPressed()) {
@@ -3897,6 +3931,23 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        }
        }
    }
    }


    private boolean dispatchKeyToKeyHandlers(KeyEvent event) {
        for (DeviceKeyHandler handler : mDeviceKeyHandlers) {
            try {
                if (DEBUG_INPUT) {
                    Log.d(TAG, "Dispatching key event " + event + " to handler " + handler);
                }
                event = handler.handleKeyEvent(event);
                if (event == null) {
                    return true;
                }
            } catch (Exception e) {
                Slog.w(TAG, "Could not dispatch event to device key handler", e);
            }
        }
        return false;
    }

    /** {@inheritDoc} */
    /** {@inheritDoc} */
    @Override
    @Override
    public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
    public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
@@ -6002,6 +6053,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
                && event.getRepeatCount() == 0;
                && event.getRepeatCount() == 0;


        // Specific device key handling
        if (dispatchKeyToKeyHandlers(event)) {
            return 0;
        }

        // Handle special keys.
        // Handle special keys.
        switch (keyCode) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_BACK: {
            case KeyEvent.KEYCODE_BACK: {