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

Commit 3d24dedf authored by Alexander Hofbauer's avatar Alexander Hofbauer Committed by Steve Kondik
Browse files

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

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>

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
parent 3ba09bd4
Loading
Loading
Loading
Loading
+26 −0
Original line number 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 If the event is consume
     */
    public boolean handleKeyEvent(KeyEvent event);
}
+6 −0
Original line number Diff line number Diff line
@@ -1822,6 +1822,12 @@

    <bool name="config_networkSamplingWakesDevice">true</bool>

    <!-- Path to the library that contains a device specific key handler -->
    <string name="config_deviceKeyHandlerLib" translatable="false"></string>

    <!-- Name of that key handler class -->
    <string name="config_deviceKeyHandlerClass" translatable="false"></string>

    <string-array translatable="false" name="config_cdma_home_system" />

    <!--From SmsMessage-->
+4 −0
Original line number Diff line number Diff line
@@ -1991,6 +1991,10 @@
  <java-symbol type="layout" name="year_label_text_view" />
  <java-symbol type="layout" name="date_picker_holo" />

  <!-- Config.xml entries -->
  <java-symbol type="string" name="config_deviceKeyHandlerLib" />
  <java-symbol type="string" name="config_deviceKeyHandlerClass" />

  <java-symbol type="id" name="time_header" />
  <java-symbol type="id" name="hours" />
  <java-symbol type="id" name="minutes" />
+57 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
@@ -104,6 +105,7 @@ import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;

import com.android.internal.R;
import com.android.internal.os.DeviceKeyHandler;
import com.android.internal.policy.IKeyguardService;
import com.android.internal.policy.IKeyguardServiceConstants;
import com.android.internal.policy.PolicyManager;
@@ -115,11 +117,15 @@ import com.android.internal.util.gesture.EdgeServiceConstants;
import com.android.internal.widget.PointerLocationView;
import com.android.server.LocalServices;

import dalvik.system.DexClassLoader;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.List;
import java.lang.reflect.Constructor;

import static android.view.WindowManager.LayoutParams.*;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
@@ -249,6 +255,8 @@ 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
@@ -1306,6 +1314,30 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        if (!mPowerManager.isInteractive()) {
            goingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
        }

        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() {
@@ -2870,6 +2902,19 @@ public class PhoneWindowManager implements WindowManagerPolicy {

        if (mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
            return -1;

        }

        // Specific device key handling
        if (mDeviceKeyHandler != null) {
            try {
                // The device only should consume known keys.
                if (mDeviceKeyHandler.handleKeyEvent(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
@@ -4710,6 +4755,18 @@ 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)) {
                    return 0;
                }
            } catch (Exception e) {
                Slog.w(TAG, "Could not dispatch event to device key handler", e);
            }
        }

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