diff options
-rw-r--r-- | core/java/com/android/internal/os/DeviceKeyHandler.java | 31 | ||||
-rw-r--r-- | core/res/res/values/ice_config.xml | 8 | ||||
-rw-r--r-- | core/res/res/values/ice_symbols.xml | 4 | ||||
-rw-r--r-- | services/core/java/com/android/server/policy/PhoneWindowManager.java | 57 |
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: { |