summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/com/android/internal/os/DeviceKeyHandler.java31
-rw-r--r--core/res/res/values/ice_config.xml8
-rw-r--r--core/res/res/values/ice_symbols.xml4
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java57
4 files changed, 100 insertions, 0 deletions
diff --git a/core/java/com/android/internal/os/DeviceKeyHandler.java b/core/java/com/android/internal/os/DeviceKeyHandler.java
new file mode 100644
index 000000000000..8902337f3ebb
--- /dev/null
+++ b/core/java/com/android/internal/os/DeviceKeyHandler.java
@@ -0,0 +1,31 @@
+/*
+ * 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);
+}
diff --git a/core/res/res/values/ice_config.xml b/core/res/res/values/ice_config.xml
index 07802d7a3603..ee314977e8d9 100644
--- a/core/res/res/values/ice_config.xml
+++ b/core/res/res/values/ice_config.xml
@@ -31,4 +31,12 @@
<!-- The list of components which should be forced to be enabled. -->
<string-array name="config_forceEnabledComponents" translatable="false">
</string-array>
+
+ <!-- Paths to the libraries that contain device specific key handlers -->
+ <string-array name="config_deviceKeyHandlerLibs" translatable="false">
+ </string-array>
+
+ <!-- Names of the key handler classes -->
+ <string-array name="config_deviceKeyHandlerClasses" translatable="false">
+ </string-array>
</resources>
diff --git a/core/res/res/values/ice_symbols.xml b/core/res/res/values/ice_symbols.xml
index c981eae9f9ca..8c5a79decaaa 100644
--- a/core/res/res/values/ice_symbols.xml
+++ b/core/res/res/values/ice_symbols.xml
@@ -21,4 +21,8 @@
<java-symbol type="array" name="config_deviceDisabledComponents" />
<java-symbol type="array" name="config_globallyDisabledComponents" />
<java-symbol type="array" name="config_forceEnabledComponents" />
+
+ <!-- Device keyhandlers -->
+ <java-symbol type="array" name="config_deviceKeyHandlerLibs" />
+ <java-symbol type="array" name="config_deviceKeyHandlerClasses" />
</resources>
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b02d08027510..12de08936d27 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -195,6 +195,7 @@ import com.android.internal.app.AssistUtils;
import com.android.internal.inputmethod.SoftInputShowHideReason;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.os.DeviceKeyHandler;
import com.android.internal.os.RoSystemProperties;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
@@ -223,12 +224,17 @@ import com.android.server.wm.WindowManagerInternal;
import com.android.server.wm.WindowManagerInternal.AppTransitionListener;
import com.android.server.wm.WindowManagerService;
+import dalvik.system.PathClassLoader;
+
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
import java.util.HashSet;
+import java.util.List;
/**
* WindowManagerPolicy implementation for the Android phone UI. This
@@ -598,6 +604,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private boolean mLockNowPending = false;
+ private final List<DeviceKeyHandler> mDeviceKeyHandlers = new ArrayList<>();
+
private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
@@ -1859,6 +1867,28 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mWindowManagerFuncs.onKeyguardShowingAndNotOccludedChanged();
}
});
+ final String[] deviceKeyHandlerLibs = res.getStringArray(
+ com.android.internal.R.array.config_deviceKeyHandlerLibs);
+ final String[] deviceKeyHandlerClasses = res.getStringArray(
+ com.android.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_INPUT) {
+ Slog.d(TAG, "" + mDeviceKeyHandlers.size() + " device key handlers loaded");
+ }
initKeyCombinationRules();
initSingleKeyGestureRules();
mSideFpsEventHandler = new SideFpsEventHandler(mContext, mHandler, mPowerManager);
@@ -2870,6 +2900,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return key_consumed;
}
+ // Specific device key handling
+ if (dispatchKeyToKeyHandlers(event)) {
+ return -1;
+ }
+
// Reserve all the META modifier combos for system behavior
if ((metaState & KeyEvent.META_META_ON) != 0) {
return key_consumed;
@@ -2922,6 +2957,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;
+ }
+
// TODO(b/117479243): handle it in InputPolicy
/** {@inheritDoc} */
@Override
@@ -3536,6 +3588,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
&& (!isNavBarVirtKey || mNavBarVirtualKeyHapticFeedbackEnabled)
&& event.getRepeatCount() == 0;
+ // Specific device key handling
+ if (dispatchKeyToKeyHandlers(event)) {
+ return 0;
+ }
+
// Handle special keys.
switch (keyCode) {
case KeyEvent.KEYCODE_BACK: {