From c61ec68566646128facfa3874fcc46775a546e81 Mon Sep 17 00:00:00 2001 From: Danesh M Date: Wed, 25 Jun 2014 21:31:49 -0700 Subject: [PATCH 1/4] PowerManager: Add proximity check on wake This consists of the following patches: ProximityWake : Add support for checking proximity when waking device Change-Id: Ia5ff446d88435773acccc7467e66009000dc20cb Be sure to shutdown the proximity sensor after display wake This fixes: http://review.cyanogenmod.org/#/c/66657/ Change-Id: I1768f13cb48c3e056d0e137642690fc3d650c4ab PowerManager : Make proximity check opt-in Change-Id: I7cf64a82530da2e655018e43683ba7a5584d54f8 Framework : Fix proximity wakeup reference Change-Id: Ia40ca6fbf6e37fbb3996f2384f725c30b88c2131 [1/2] Frameworks: let InCallUI handle proximity sensor for incoming calls Fixes "while 'prevent accidental wake-up' is on, proximity sensor doesn't control screen state on incoming call. Must manually turn on screen to see who's calling." Change-Id: I738b3bbd328992c8a8010a0c8d9aa1e444cfa9f9 power: Fix locking for wakeup proximity check * Often I'm noticing high power consumption due to the proximity sensor never turning off. Add synchronization around this code to ensure ordering. Change-Id: I8ccf3152166cd896e0ce2551c01b8ac8f501d782 add config for proximity check on screen on default value Change-Id: I7e6ae08e23ee147a37986aa6aa9b3176b301a09e Services : Ensure proximity check is taken into consideration Only do the proximity check if explicitly being asked to do so. This is a patch that was never ported from cm-11.0 : 2293e60c7de011782e59486605c04b9f67a1e24f issue-id: CYNGNOS-1223 Change-Id: Id1be619e638de6a45252d8390eab6e38bd5de5a7 services: button brightness should check proximity Change-Id: I10a72fa6d8b520e86cfef3d7ded489fd7fa936d2 powermanager: Initialize SensorManager in systemReady() * Service startup ordering is different on M and the sensor service is not ready during construction of the PowerManager. This was causing a hang on boot. Move it to systemReady instead. Change-Id: I9e0293484e1aaaf9f82f9c75680bec558607c54d fw: Move proximitycheck to CMSettings. Change-Id: Ie80166c990363d3846925b189a1f7001a7fd56f8 PowerManagerService: Log when proximity blocks wake There is currently no indication when the proximity sensor is allowed to prevent the system from waking up. This can make it hard to debug weird failed wakes. Add a log to facilitate debugging wakup problems. Change-Id: I7df34e13b1268a4e7211fb06ccd88f2053c0af0a (cherry picked from commit 21ddba548589fa38907a45789f893c7a08040875) base: Fix proximity check on power key To test, enable "Settings >> Display >> Prevent accidental wakeup", hold your hand over the proximity sensor and turn your phone on. Prior to this change, it will wake up the phone and after the change it will not. Change-Id: Ied300108cebb31dedf228e85510abebb3e8a4152 base: Fix proximity check on non power key To test, enable "Settings >> Display >> Prevent accidental wake-up" and "Settings >> Buttons >> Home button Wake up device", hold your hand over the proximity sensor and turn your phone on by home key. Prior to this change, it will wake up the phone and after the change it will not. Change-Id: Ifd14ff2ad9cd2cbc64209b9cf19e3c0ee0b6f40f only use proximity checks on wakeup keys The power button should always wake the screen regardless of the proximity; only check proximity when the wake up key code is WAKEUP. Ticket: CYNGNOS-2579 Change-Id: I686ad22d513a3d939be3a0a5c3b752339b2383d3 Signed-off-by: Roman Birg Disable proximity check on power key properly Change-Id: If1ca0fa02805ce2fbe5a9ac1ab56a5e62beca4e1 The change-id below is so that Gerrit won't be confused. Change-Id: Ia5ff446d88435773acccc7467e66009000dc20cb --- core/java/android/os/IPowerManager.aidl | 2 + core/java/android/os/PowerManager.java | 16 ++ core/java/android/provider/Settings.java | 5 + core/res/res/values/custom_config.xml | 6 + core/res/res/values/custom_symbols.xml | 8 + .../server/policy/PhoneWindowManager.java | 17 +- .../server/power/PowerManagerService.java | 150 +++++++++++++++++- 7 files changed, 196 insertions(+), 8 deletions(-) diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index 13e4e38df5f6..7cd90450a63b 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -68,4 +68,6 @@ interface IPowerManager // controls whether PowerManager should doze after the screen turns off or not void setDozeAfterScreenOff(boolean on); + + void wakeUpWithProximityCheck(long time, String reason, String opPackageName); } diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 6ad0ff33d47a..dcb5f2280fbd 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -981,6 +981,22 @@ public void wakeUp(long time, String reason) { } } + /** + * Forces the device to wake up from sleep only if + * nothing is blocking the proximity sensor + * + * @see #wakeUp + * + * @hide + */ + public void wakeUpWithProximityCheck(long time, String reason) { + try { + mService.wakeUpWithProximityCheck(time, reason, mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Forces the device to start napping. *

diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 70a028ac6e22..9d75dd2c98dc 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3904,6 +3904,11 @@ public boolean validate(@Nullable String value) { public static final String DOCK_SOUNDS_ENABLED = Global.DOCK_SOUNDS_ENABLED; private static final Validator DOCK_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; + /** + * Check the proximity sensor during wakeup + * @hide + */ + public static final String PROXIMITY_ON_WAKE = "proximity_on_wake"; /** * Whether to play sounds when the keyguard is shown and dismissed. diff --git a/core/res/res/values/custom_config.xml b/core/res/res/values/custom_config.xml index a6dd60c2310c..6cfaff362ae4 100644 --- a/core/res/res/values/custom_config.xml +++ b/core/res/res/values/custom_config.xml @@ -127,4 +127,10 @@ true + + false + 250 + false diff --git a/core/res/res/values/custom_symbols.xml b/core/res/res/values/custom_symbols.xml index f4bee99864a7..6bbbf9725c3a 100644 --- a/core/res/res/values/custom_symbols.xml +++ b/core/res/res/values/custom_symbols.xml @@ -109,4 +109,12 @@ + + + + + + + + diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index fadf88e81ccf..fe66bdcb159b 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -7178,7 +7178,8 @@ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { if (isValidGlobalKey(keyCode) && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) { if (isWakeKey) { - wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); + wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, + "android.policy:KEY", true); } return result; } @@ -7543,7 +7544,8 @@ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { } if (isWakeKey) { - wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); + wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY", + event.getKeyCode() == KeyEvent.KEYCODE_WAKEUP); // Check prox only on wake key } return result; @@ -8020,6 +8022,11 @@ private void wakeUpFromPowerKey(long eventTime) { } private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) { + return wakeUp(wakeTime, wakeInTheaterMode, reason, false); + } + + private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason, + final boolean withProximityCheck) { final boolean theaterModeEnabled = isTheaterModeEnabled(); if (!wakeInTheaterMode && theaterModeEnabled) { return false; @@ -8030,7 +8037,11 @@ private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) Settings.Global.THEATER_MODE_ON, 0); } - mPowerManager.wakeUp(wakeTime, reason); + if (withProximityCheck) { + mPowerManager.wakeUpWithProximityCheck(wakeTime, reason); + } else { + mPowerManager.wakeUp(wakeTime, reason); + } return true; } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 296c735e244f..aa1638055d78 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -33,6 +33,9 @@ import android.content.pm.PackageManager; import android.content.res.Resources; import android.database.ContentObserver; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.SystemSensorManager; import android.hardware.display.DisplayManagerInternal; @@ -69,6 +72,8 @@ import android.service.dreams.DreamManagerInternal; import android.service.vr.IVrManager; import android.service.vr.IVrStateCallbacks; +import android.telephony.TelephonyManager; +import android.util.EventLog; import android.util.KeyValueListParser; import android.util.PrintWriterPrinter; import android.util.Log; @@ -130,6 +135,8 @@ public final class PowerManagerService extends SystemService // Message: Polling to look for long held wake locks. private static final int MSG_CHECK_FOR_LONG_WAKELOCKS = 4; + private static final int MSG_WAKE_UP = 5; + // Dirty bit: mWakeLocks changed private static final int DIRTY_WAKE_LOCKS = 1 << 0; // Dirty bit: mWakefulness changed @@ -225,6 +232,8 @@ public final class PowerManagerService extends SystemService // Persistent property for last reboot reason private static final String LAST_REBOOT_PROPERTY = "persist.sys.boot.reason"; + + private static final float PROXIMITY_NEAR_THRESHOLD = 5.0f; private final Context mContext; private final ServiceThread mHandlerThread; @@ -671,6 +680,17 @@ void dumpProto(ProtoOutputStream proto) { private static native void nativeSendPowerHint(int hintId, int data); private static native void nativeSetFeature(int featureId, int data); + // Whether proximity check on wake is enabled by default + private boolean mProximityWakeEnabledByDefaultConfig; + + private boolean mProximityWakeSupported; + private boolean mProximityWakeEnabled; + private int mProximityTimeOut; + private SensorManager mSensorManager; + private Sensor mProximitySensor; + private SensorEventListener mProximityListener; + private android.os.PowerManager.WakeLock mProximityWakeLock; + public PowerManagerService(Context context) { super(context); mContext = context; @@ -810,6 +830,10 @@ public void systemReady(IAppOpsService appOps) { // Shouldn't happen since in-process. } + // Initialize proximity sensor + mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); + mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); + // Go. readConfigurationLocked(); updateSettingsLocked(); @@ -869,6 +893,9 @@ public void systemReady(IAppOpsService appOps) { resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.NAVIGATION_BAR_ENABLED), false, mSettingsObserver, UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.PROXIMITY_ON_WAKE), + false, mSettingsObserver, UserHandle.USER_ALL); IVrManager vrManager = (IVrManager) getBinderService(Context.VR_SERVICE); if (vrManager != null) { try { @@ -937,6 +964,16 @@ private void readConfigurationLocked() { com.android.internal.R.fraction.config_maximumScreenDimRatio, 1, 1); mSupportsDoubleTapWakeConfig = resources.getBoolean( com.android.internal.R.bool.config_supportDoubleTapWake); + mProximityWakeSupported = resources.getBoolean( + com.android.internal.R.bool.config_proximityCheckOnWake); + mProximityWakeEnabledByDefaultConfig = resources.getBoolean( + com.android.internal.R.bool.config_proximityCheckOnWakeEnabledByDefault); + mProximityTimeOut = resources.getInteger( + com.android.internal.R.integer.config_proximityCheckTimeout); + if (mProximityWakeSupported) { + mProximityWakeLock = ((PowerManager) mContext.getSystemService(Context.POWER_SERVICE)) + .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ProximityWakeLock"); + } } private void updateSettingsLocked() { @@ -1002,6 +1039,10 @@ private void updateSettingsLocked() { Settings.System.NAVIGATION_BAR_ENABLED, 0, UserHandle.USER_CURRENT) != 0; mButtonBrightnessEnabled &= !navBarEnabled; + mProximityWakeEnabled = Settings.System.getInt(resolver, + Settings.System.PROXIMITY_ON_WAKE, + mProximityWakeEnabledByDefaultConfig ? 1 : 0) == 1; + mDirty |= DIRTY_SETTINGS; } @@ -3963,6 +4004,10 @@ public void handleMessage(Message msg) { case MSG_CHECK_FOR_LONG_WAKELOCKS: checkForLongWakeLocks(); break; + case MSG_WAKE_UP: + cleanupProximity(); + ((Runnable) msg.obj).run(); + break; } } } @@ -4382,6 +4427,19 @@ public void userActivity(long eventTime, int event, int flags) { @Override // Binder call public void wakeUp(long eventTime, String reason, String opPackageName) { + wakeUp(eventTime, reason, opPackageName, false); + } + + @Override // Binder call + public void wakeUpWithProximityCheck(long eventTime, String reason, String opPackageName) { + wakeUp(eventTime, reason, opPackageName, true); + } + + /** + * @hide + */ + private void wakeUp(long eventTime, String reason, String opPackageName, + final boolean checkProximity) { if (eventTime > SystemClock.uptimeMillis()) { throw new IllegalArgumentException("event time must not be in the future"); } @@ -4390,11 +4448,21 @@ public void wakeUp(long eventTime, String reason, String opPackageName) { android.Manifest.permission.DEVICE_POWER, null); final int uid = Binder.getCallingUid(); - final long ident = Binder.clearCallingIdentity(); - try { - wakeUpInternal(eventTime, reason, uid, opPackageName, uid); - } finally { - Binder.restoreCallingIdentity(ident); + final Runnable r = new Runnable() { + @Override + public void run() { + final long ident = Binder.clearCallingIdentity(); + try { + wakeUpInternal(eventTime, reason, uid, opPackageName, uid); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + }; + if (checkProximity) { + runWithProximityCheck(r); + } else { + r.run(); } } @@ -4849,4 +4917,76 @@ public void powerHint(int hintId, int data) { powerHintInternal(hintId, data); } } + + private void cleanupProximity() { + synchronized (mProximityWakeLock) { + cleanupProximityLocked(); + } + } + + private void cleanupProximityLocked() { + if (mProximityWakeLock.isHeld()) { + mProximityWakeLock.release(); + } + if (mProximityListener != null) { + mSensorManager.unregisterListener(mProximityListener); + mProximityListener = null; + } + } + + private void runWithProximityCheck(final Runnable r) { + if (mHandler.hasMessages(MSG_WAKE_UP)) { + // A message is already queued + return; + } + + final TelephonyManager tm = + (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); + final boolean hasIncomingCall = tm.getCallState() == TelephonyManager.CALL_STATE_RINGING; + + if (mProximityWakeSupported && mProximityWakeEnabled + && mProximitySensor != null && !hasIncomingCall) { + final Message msg = mHandler.obtainMessage(MSG_WAKE_UP); + msg.obj = r; + mHandler.sendMessageDelayed(msg, mProximityTimeOut); + runPostProximityCheck(r); + } else { + r.run(); + } + } + + private void runPostProximityCheck(final Runnable r) { + if (mSensorManager == null) { + r.run(); + return; + } + synchronized (mProximityWakeLock) { + mProximityWakeLock.acquire(); + mProximityListener = new SensorEventListener() { + @Override + public void onSensorChanged(SensorEvent event) { + cleanupProximityLocked(); + if (!mHandler.hasMessages(MSG_WAKE_UP)) { + Slog.w(TAG, "Proximity sensor took too long, wake event already triggered!"); + return; + } + mHandler.removeMessages(MSG_WAKE_UP); + final float distance = event.values[0]; + if (distance >= PROXIMITY_NEAR_THRESHOLD || + distance >= mProximitySensor.getMaximumRange()) { + r.run(); + } else { + Slog.w(TAG, "Not waking up. Proximity sensor is blocked."); + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + // Do nothing + } + }; + mSensorManager.registerListener(mProximityListener, + mProximitySensor, SensorManager.SENSOR_DELAY_FASTEST); + } + } } From 4a4e91e32c2ccd16be7736e38b659aea5c80972d Mon Sep 17 00:00:00 2001 From: Alexander Hofbauer Date: Thu, 12 Apr 2012 01:24:24 +0200 Subject: [PATCH 2/4] 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 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 --- .../android/internal/os/DeviceKeyHandler.java | 26 +++++++++ core/res/res/values/custom_config.xml | 7 +++ core/res/res/values/custom_symbols.xml | 5 ++ .../server/policy/PhoneWindowManager.java | 57 +++++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 core/java/com/android/internal/os/DeviceKeyHandler.java 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..e7d103dd6bee --- /dev/null +++ b/core/java/com/android/internal/os/DeviceKeyHandler.java @@ -0,0 +1,26 @@ +/* + * 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); +} diff --git a/core/res/res/values/custom_config.xml b/core/res/res/values/custom_config.xml index 6cfaff362ae4..50ad87f0fd3f 100644 --- a/core/res/res/values/custom_config.xml +++ b/core/res/res/values/custom_config.xml @@ -133,4 +133,11 @@ false 250 false + + + + + + + diff --git a/core/res/res/values/custom_symbols.xml b/core/res/res/values/custom_symbols.xml index 6bbbf9725c3a..46e2195c6e4d 100644 --- a/core/res/res/values/custom_symbols.xml +++ b/core/res/res/values/custom_symbols.xml @@ -117,4 +117,9 @@ + + + + + diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index fe66bdcb159b..1704bc317448 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -172,6 +172,7 @@ import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; +import android.content.ContextWrapper; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; @@ -283,6 +284,9 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.policy.IKeyguardDismissCallback; +import com.android.internal.os.DeviceKeyHandler; +import com.android.internal.policy.PhoneWindow; +import com.android.internal.policy.IKeyguardService; import com.android.internal.policy.IShortcutService; import com.android.internal.policy.KeyguardDismissCallback; import com.android.internal.policy.PhoneWindow; @@ -305,11 +309,14 @@ import com.android.server.wm.WindowManagerInternal; import com.android.server.wm.WindowManagerInternal.AppTransitionListener; +import dalvik.system.DexClassLoader; + import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.util.List; +import java.lang.reflect.Constructor; /** * WindowManagerPolicy implementation for the Android phone UI. This @@ -505,6 +512,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** Amount of time (in milliseconds) a toast window can be shown. */ public static final int TOAST_WINDOW_TIMEOUT = 3500; // 3.5 seconds + private DeviceKeyHandler mDeviceKeyHandler; + /** * Lock protecting internal state. Must not call out into window * manager with lock held. (This lock will be acquired in places @@ -2789,6 +2798,30 @@ public void onShowingChanged() { mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); mProximityWakeLock = mContext.getSystemService(PowerManager.class) .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ProximityWakeLock"); + + 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); + } + } } /** @@ -5028,6 +5061,18 @@ public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int p 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); + } + } + if (down) { long shortcutCode = keyCode; if (event.isCtrlPressed()) { @@ -5155,6 +5200,18 @@ public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policy final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0; + // Specific device key handling + if (mDeviceKeyHandler != null) { + try { + // The device only should consume known keys. + if (mDeviceKeyHandler.handleKeyEvent(event)) { + return null; + } + } catch (Exception e) { + Slog.w(TAG, "Could not dispatch event to device key handler", e); + } + } + // Check for fallback actions specified by the key character map. final FallbackAction fallbackAction; if (initialDown) { From 207d40ebfed2c1da4aee2a75c397ead0c450616f Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Sun, 11 Sep 2016 00:49:41 -0700 Subject: [PATCH 3/4] 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 --- .../com/android/server/policy/PhoneWindowManager.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 1704bc317448..2f5f55ca813e 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -309,8 +309,6 @@ import com.android.server.wm.WindowManagerInternal; import com.android.server.wm.WindowManagerInternal.AppTransitionListener; -import dalvik.system.DexClassLoader; - import java.io.File; import java.io.FileReader; import java.io.IOException; @@ -318,6 +316,8 @@ import java.util.List; import java.lang.reflect.Constructor; +import dalvik.system.PathClassLoader; + /** * WindowManagerPolicy implementation for the Android phone UI. This * introduces a new method suffix, Lp, for an internal lock of the @@ -2806,10 +2806,8 @@ public void onShowingChanged() { 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()); + PathClassLoader loader = new PathClassLoader(deviceKeyHandlerLib, + getClass().getClassLoader()); try { Class klass = loader.loadClass(deviceKeyHandlerClass); Constructor constructor = klass.getConstructor(Context.class); From 4a5a275389c38778837345b953a433d31e368ead Mon Sep 17 00:00:00 2001 From: Keith Mok Date: Mon, 16 Nov 2015 13:48:36 -0800 Subject: [PATCH 4/4] DeviceKeyHandler: Fix suspend gesture not working A function for handling DeviceKey is mis-placed in PhoneWindowManager.java when merging from cm-12.1 Change-Id: I5a5421c88216b70defaac69b732d99d506e1a2a6 --- .../server/policy/PhoneWindowManager.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 2f5f55ca813e..abe653d8e0a6 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -5198,18 +5198,6 @@ public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policy final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0; - // Specific device key handling - if (mDeviceKeyHandler != null) { - try { - // The device only should consume known keys. - if (mDeviceKeyHandler.handleKeyEvent(event)) { - return null; - } - } catch (Exception e) { - Slog.w(TAG, "Could not dispatch event to device key handler", e); - } - } - // Check for fallback actions specified by the key character map. final FallbackAction fallbackAction; if (initialDown) { @@ -7251,6 +7239,18 @@ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { // Trigger haptic feedback only for "real" events. && source != InputDevice.SOURCE_CUSTOM; + // 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_BACK: {