diff options
| author | Moyster <oysterized@gmail.com> | 2016-09-22 01:16:11 +0200 |
|---|---|---|
| committer | Moyster <oysterized@gmail.com> | 2016-09-26 17:50:50 +0200 |
| commit | 1f2520003fc0f8645c7a70db134cf2df38959537 (patch) | |
| tree | 836d7f0be5e63d9d8b7d5318954ca36a69ed8b55 /keyhandler/src | |
| parent | e541da89ba6b73e0450adf031961539a7f572980 (diff) | |
| download | android_device_meizu_m2note-1f2520003fc0f8645c7a70db134cf2df38959537.tar.gz | |
bring up for gestures and keyhandler, based on @Faust93 work
cleanup
fix path for m2note
Diffstat (limited to 'keyhandler/src')
| -rw-r--r-- | keyhandler/src/com/cyanogenmod/settings/device/KeyHandler.java | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/keyhandler/src/com/cyanogenmod/settings/device/KeyHandler.java b/keyhandler/src/com/cyanogenmod/settings/device/KeyHandler.java new file mode 100644 index 0000000..8843b7a --- /dev/null +++ b/keyhandler/src/com/cyanogenmod/settings/device/KeyHandler.java @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2015 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.cyanogenmod.settings.device; + +import android.app.ActivityManagerNative; +import android.app.KeyguardManager; +import android.content.ActivityNotFoundException; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.hardware.TorchManager; +import android.media.session.MediaSessionLegacyHelper; +import android.net.Uri; +import android.os.Handler; +import android.os.Message; +import android.os.PowerManager; +import android.os.PowerManager.WakeLock; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemClock; +import android.os.UserHandle; +import android.os.Vibrator; +import android.provider.MediaStore; +import android.provider.Settings; +import android.provider.Settings.Global; +import android.util.Log; +import android.view.KeyEvent; +import android.view.WindowManagerGlobal; + +import com.android.internal.os.DeviceKeyHandler; +import com.android.internal.util.ArrayUtils; + +import android.app.Instrumentation; +import android.content.SharedPreferences; +import android.content.ContextWrapper; + +public class KeyHandler implements DeviceKeyHandler { + + private static final String TAG = KeyHandler.class.getSimpleName(); + private static final int GESTURE_REQUEST = 1; + + private static final String KEY_GESTURE_HAPTIC_FEEDBACK = + "touchscreen_gesture_haptic_feedback"; + private static final String KEY_FPC_TAP = + "fpc_gesture_tap"; + private static final String KEY_FPC_LEFT = + "fpc_gesture_left"; + private static final String KEY_FPC_RIGHT = + "fpc_gesture_right"; + + private static final String TOUCHSCREEN_GESTURE_HAPTIC_FEEDBACK = + "touchscreen_gesture_haptic_feedback"; + + private static final String ACTION_DISMISS_KEYGUARD = + "com.android.keyguard.action.DISMISS_KEYGUARD_SECURELY"; + + // Supported scancodes + private static final int KEY_DOUBLE_TAP = 623; + private static final int GESTURE_C_SCANCODE = 612; + private static final int GESTURE_Z_SCANCODE = 622; + private static final int GESTURE_DOWN_SCANCODE = 610; + private static final int GESTURE_LTR_SCANCODE = 608; + private static final int GESTURE_GTR_SCANCODE = 609; + private static final int MODE_MUTE = 614; //M + private static final int MODE_DO_NOT_DISTURB = 616; //S + private static final int MODE_NORMAL = 621; //W + + private static final int GESTURE_FPC_TAP_SCANCODE = 189; + private static final int GESTURE_FPC_LEFT_SCANCODE = 191; + private static final int GESTURE_FPC_RIGHT_SCANCODE = 190; + + private static final int GESTURE_WAKELOCK_DURATION = 3000; + + private static final int[] sSupportedGestures = new int[] { + KEY_DOUBLE_TAP, + GESTURE_C_SCANCODE, + GESTURE_Z_SCANCODE, + GESTURE_DOWN_SCANCODE, + GESTURE_LTR_SCANCODE, + GESTURE_GTR_SCANCODE, + MODE_MUTE, + MODE_DO_NOT_DISTURB, + MODE_NORMAL, + GESTURE_FPC_TAP_SCANCODE, + GESTURE_FPC_LEFT_SCANCODE, + GESTURE_FPC_RIGHT_SCANCODE + }; + + private final Context mContext; + + private final PowerManager mPowerManager; + private KeyguardManager mKeyguardManager; + private EventHandler mEventHandler; + private SensorManager mSensorManager; + private TorchManager mTorchManager; + private Sensor mProximitySensor; + private Vibrator mVibrator; + private WakeLock mProximityWakeLock; + private WakeLock mGestureWakeLock; + private int mProximityTimeOut; + private boolean mProximityWakeSupported; + private Instrumentation m_Instrumentation; + private Context cmaContext = null; + + private boolean mNotificationSliderVibrate; + + public KeyHandler(Context context) { + mContext = context; + mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + mEventHandler = new EventHandler(); + m_Instrumentation = new Instrumentation(); + mGestureWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, + "GestureWakeLock"); + + try { + cmaContext = mContext.createPackageContext("com.cyanogenmod.settings.device", Context.CONTEXT_RESTRICTED); + } catch (Exception e) { + e.printStackTrace(); + } + + final Resources resources = mContext.getResources(); + mProximityTimeOut = resources.getInteger( + com.android.internal.R.integer.config_proximityCheckTimeout); + mProximityWakeSupported = resources.getBoolean( + com.android.internal.R.bool.config_proximityCheckOnWake); + + if (mProximityWakeSupported) { + mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); + mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); + mProximityWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, + "ProximityWakeLock"); + } + + mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); + if (mVibrator == null || !mVibrator.hasVibrator()) { + mVibrator = null; + } + } + + private void ensureKeyguardManager() { + if (mKeyguardManager == null) { + mKeyguardManager = + (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); + } + } + + private void ensureTorchManager() { + if (mTorchManager == null) { + mTorchManager = (TorchManager) mContext.getSystemService(Context.TORCH_SERVICE); + } + } + + private class EventHandler extends Handler { + @Override + public void handleMessage(Message msg) { + KeyEvent event = (KeyEvent) msg.obj; + int scanCode = event.getScanCode(); + switch (scanCode) { + case GESTURE_C_SCANCODE: + ensureKeyguardManager(); + final String action; + mGestureWakeLock.acquire(GESTURE_WAKELOCK_DURATION); + if (mKeyguardManager.isKeyguardSecure() && mKeyguardManager.isKeyguardLocked()) { + action = MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE; + } else { + mContext.sendBroadcastAsUser(new Intent(ACTION_DISMISS_KEYGUARD), + UserHandle.CURRENT); + action = MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA; + } + mPowerManager.wakeUp(SystemClock.uptimeMillis()); + Intent intent = new Intent(action, null); + startActivitySafely(intent); + doHapticFeedback(); + break; + case GESTURE_FPC_LEFT_SCANCODE: + if(getCMApref(KEY_FPC_LEFT, false)) { + m_Instrumentation.sendKeyDownUpSync( KeyEvent.KEYCODE_MENU ); + doHapticFeedback(); + } + break; + case GESTURE_FPC_RIGHT_SCANCODE: + if(getCMApref(KEY_FPC_RIGHT, false)) { + m_Instrumentation.sendKeyDownUpSync( KeyEvent.KEYCODE_APP_SWITCH ); + doHapticFeedback(); + } + break; + case GESTURE_Z_SCANCODE: + dispatchMediaKeyWithWakeLockToMediaSession(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE); + doHapticFeedback(); + break; + case GESTURE_DOWN_SCANCODE: + ensureTorchManager(); + mGestureWakeLock.acquire(GESTURE_WAKELOCK_DURATION); + mTorchManager.toggleTorch(); + doHapticFeedback(); + break; + case GESTURE_LTR_SCANCODE: + dispatchMediaKeyWithWakeLockToMediaSession(KeyEvent.KEYCODE_MEDIA_PREVIOUS); + doHapticFeedback(); + break; + case GESTURE_GTR_SCANCODE: + dispatchMediaKeyWithWakeLockToMediaSession(KeyEvent.KEYCODE_MEDIA_NEXT); + doHapticFeedback(); + break; + case MODE_MUTE: + case MODE_DO_NOT_DISTURB: + case MODE_NORMAL: + int zenMode = Global.ZEN_MODE_OFF; + if (scanCode == MODE_MUTE) { + zenMode = Global.ZEN_MODE_NO_INTERRUPTIONS; + } else if (scanCode == MODE_DO_NOT_DISTURB) { + zenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; + } + Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, + zenMode); + if (mNotificationSliderVibrate) { + doHapticFeedback(); + } + mNotificationSliderVibrate = true; + break; + } + } + } + + public boolean handleKeyEvent(KeyEvent event) { + if (event.getAction() != KeyEvent.ACTION_UP) { + return false; + } + boolean isKeySupported = ArrayUtils.contains(sSupportedGestures, event.getScanCode()); + if (isKeySupported && !mEventHandler.hasMessages(GESTURE_REQUEST)) { + if (event.getScanCode() == KEY_DOUBLE_TAP && !mPowerManager.isScreenOn()) { + mPowerManager.wakeUpWithProximityCheck(SystemClock.uptimeMillis()); + doHapticFeedback(); + return true; + } + Message msg = getMessageForKeyEvent(event); + boolean defaultProximity = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_proximityCheckOnWakeEnabledByDefault); + boolean proximityWakeCheckEnabled = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.PROXIMITY_ON_WAKE, defaultProximity ? 1 : 0) == 1; + if (mProximityWakeSupported && proximityWakeCheckEnabled && mProximitySensor != null) { + mEventHandler.sendMessageDelayed(msg, mProximityTimeOut); + processEvent(event); + } else { + mEventHandler.sendMessage(msg); + } + } + return isKeySupported; + } + + private Message getMessageForKeyEvent(KeyEvent keyEvent) { + Message msg = mEventHandler.obtainMessage(GESTURE_REQUEST); + msg.obj = keyEvent; + return msg; + } + + private void processEvent(final KeyEvent keyEvent) { + mProximityWakeLock.acquire(); + mSensorManager.registerListener(new SensorEventListener() { + @Override + public void onSensorChanged(SensorEvent event) { + mProximityWakeLock.release(); + mSensorManager.unregisterListener(this); + if (!mEventHandler.hasMessages(GESTURE_REQUEST)) { + // The sensor took to long, ignoring. + return; + } + mEventHandler.removeMessages(GESTURE_REQUEST); + if (event.values[0] == mProximitySensor.getMaximumRange()) { + Message msg = getMessageForKeyEvent(keyEvent); + mEventHandler.sendMessage(msg); + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) {} + + }, mProximitySensor, SensorManager.SENSOR_DELAY_FASTEST); + } + + private void dispatchMediaKeyWithWakeLockToMediaSession(int keycode) { + MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext); + if (helper != null) { + KeyEvent event = new KeyEvent(SystemClock.uptimeMillis(), + SystemClock.uptimeMillis(), KeyEvent.ACTION_DOWN, keycode, 0); + helper.sendMediaButtonEvent(event, true); + event = KeyEvent.changeAction(event, KeyEvent.ACTION_UP); + helper.sendMediaButtonEvent(event, true); + } else { + Log.w(TAG, "Unable to send media key event"); + } + } + + private void startActivitySafely(Intent intent) { + intent.addFlags( + Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_SINGLE_TOP + | Intent.FLAG_ACTIVITY_CLEAR_TOP); + try { + UserHandle user = new UserHandle(UserHandle.USER_CURRENT); + mContext.startActivityAsUser(intent, null, user); + } catch (ActivityNotFoundException e) { + // Ignore + } + } + + // TODO implement it more graceful way + private boolean getCMApref(String prefKey, boolean defVal) { + SharedPreferences cmaPrefs = null; + cmaPrefs = cmaContext.getSharedPreferences("com.cyanogenmod.settings.device_preferences", Context.MODE_MULTI_PROCESS); + return cmaPrefs.getBoolean(prefKey, defVal); + } + + private void doHapticFeedback() { + if (mVibrator == null) { + return; + } + boolean enabled = getCMApref(TOUCHSCREEN_GESTURE_HAPTIC_FEEDBACK, false); + if (enabled) { + mVibrator.vibrate(50); + } + } +} |
