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 | |
| 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
24 files changed, 1311 insertions, 35 deletions
diff --git a/cm.dependencies b/cm.dependencies deleted file mode 100644 index 1492bb0..0000000 --- a/cm.dependencies +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "remote": "github" - "repository": "M571-cm/android_vendor_meizu_m2note", - "target_path": "vendor/meizu/m2note", - "branch": "master" - } - { - "remote": "github", - "repository": "M571-cm/android_kernel_meizu_m2note", - "revision": "cm-12.1", - "target_path": "kernel/meizu/m2note" - } -] diff --git a/cmactions/Android.mk b/cmactions/Android.mk new file mode 100644 index 0000000..a098093 --- /dev/null +++ b/cmactions/Android.mk @@ -0,0 +1,16 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_PACKAGE_NAME := CMActions +LOCAL_CERTIFICATE := platform +LOCAL_PRIVILEGED_MODULE := true + +LOCAL_PROGUARD_FLAG_FILES := proguard.flags + +include $(BUILD_PACKAGE) + +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/cmactions/AndroidManifest.xml b/cmactions/AndroidManifest.xml new file mode 100644 index 0000000..7adc1dc --- /dev/null +++ b/cmactions/AndroidManifest.xml @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.cyanogenmod.settings.device" + android:versionCode="1" + android:versionName="1.0" + android:sharedUserId="android.uid.system" + > + + <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> + + <uses-sdk + android:minSdkVersion="22" + android:targetSdkVersion="22" /> + + <application + android:allowBackup="true" + android:label="CMActions" + android:persistent="true" + android:icon="@mipmap/ic_launcher_settings" + android:theme="@android:style/Theme.Material.Settings" > + + <receiver android:name="com.cyanogenmod.settings.device.BootCompletedReceiver"> + <intent-filter> + <action android:name="android.intent.action.BOOT_COMPLETED" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + </receiver> + + <service android:name="ServiceWrapper" android:permission="ServiceWrapper"> + <intent-filter> + <action android:name="ServiceWrapper"/> + </intent-filter> + </service> + + <!-- stub to ensure its loaded - DO NOT REMOVE --> + <activity android:name=".KeyHandler"/> + + <activity + android:excludeFromRecents="true" + android:name="CMActions" + android:label="CMActions" + android:launchMode="singleInstance" + android:screenOrientation="portrait" + android:windowAnimationStyle="@null"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + </intent-filter> + </activity> + + <activity + android:name=".TouchscreenGestureSettings" + android:label="@string/screen_gestures_panel_title"> + <intent-filter> + <action android:name="com.cyanogenmod.action.LAUNCH_TOUCHSCREEN_GESTURE_SETTINGS" /> + </intent-filter> + <meta-data + android:name="com.android.settings.title" + android:resource="@string/screen_gestures_panel_title"/> + <meta-data + android:name="com.android.settings.summary" + android:resource="@string/screen_gestures_panel_summary"/> + </activity> + + </application> + +</manifest> diff --git a/cmactions/proguard.flags b/cmactions/proguard.flags new file mode 100644 index 0000000..def5066 --- /dev/null +++ b/cmactions/proguard.flags @@ -0,0 +1,3 @@ +-keep class org.cyanogenmod.CMActions.* { + *; +} diff --git a/cmactions/res/mipmap-xhdpi/ic_launcher_settings.png b/cmactions/res/mipmap-xhdpi/ic_launcher_settings.png Binary files differnew file mode 100644 index 0000000..fa8c813 --- /dev/null +++ b/cmactions/res/mipmap-xhdpi/ic_launcher_settings.png diff --git a/cmactions/res/mipmap-xxhdpi/ic_launcher_settings.png b/cmactions/res/mipmap-xxhdpi/ic_launcher_settings.png Binary files differnew file mode 100644 index 0000000..3fa69e9 --- /dev/null +++ b/cmactions/res/mipmap-xxhdpi/ic_launcher_settings.png diff --git a/cmactions/res/mipmap-xxxhdpi/ic_launcher_settings.png b/cmactions/res/mipmap-xxxhdpi/ic_launcher_settings.png Binary files differnew file mode 100644 index 0000000..72946b7 --- /dev/null +++ b/cmactions/res/mipmap-xxxhdpi/ic_launcher_settings.png diff --git a/cmactions/res/values-ru/strings.xml b/cmactions/res/values-ru/strings.xml new file mode 100644 index 0000000..9953f84 --- /dev/null +++ b/cmactions/res/values-ru/strings.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2013-2014 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. +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Gesture shortcuts --> + <string name="screen_gestures_panel_title">Управление жестами</string> + <string name="screen_gestures_panel_summary">Use gestures while the screen is off</string> + + <string name="touchscreen_control_gesture_head">Жесты выключенного экрана</string> + <string name="touchscreen_control_gesture_title">Включить управление жестами</string> + <string name="gesture_category_title">Доступные жесты</string> + <string name="touchscreen_dtp_gesture_title">Двойной тап</string> + <string name="touchscreen_dtp_gesture_summary">Пробуждение двойным тапом</string> + <string name="touchscreen_c_gesture_title">Камера</string> + <string name="touchscreen_c_gesture_summary">Нарисуйте \"C\" для активации камеры</string> + <string name="touchscreen_z_gesture_title">Музыка</string> + <string name="touchscreen_z_gesture_summary">Нарисуйте \"Z\" для Play/Pause</string> + <string name="touchscreen_ltr_gesture_title">Музыка</string> + <string name="touchscreen_ltr_gesture_summary">Черта влево - предыдущий трек</string> + <string name="touchscreen_gtr_gesture_title">Музыка</string> + <string name="touchscreen_gtr_gesture_summary">Черта вправо - следующий трек</string> + <string name="touchscreen_s_gesture_title">Уведомления</string> + <string name="touchscreen_s_gesture_summary">Нарисуйте \"S\" для активации режима \"Не беспокоить\"</string> + <string name="touchscreen_w_gesture_title">Уведомления</string> + <string name="touchscreen_w_gesture_summary">Нарисуйте \"W\" для активации нормального режима</string> + <string name="touchscreen_m_gesture_title">Уведомления</string> + <string name="touchscreen_m_gesture_summary">Нарисуйте \"M\" для активации режима \"Без звука\"</string> + <string name="touchscreen_ydown_gesture_title">Фонарик</string> + <string name="touchscreen_ydown_gesture_summary">Нарисуйте вертикальную черту для активации фонарика</string> + + <string name="fpc_gesture_title">Жесты кнопки сенсора</string> + <string name="fpc_gesture_tap_summary">Одиночный тап для возврата</string> + <string name="fpc_gesture_left_summary">Свайп влево для вызова меню</string> + <string name="fpc_gesture_right_summary">Свайп вправо для вызова недавних приложений</string> + + <!-- haptic feedback --> + <string name="touchscreen_extras">Дополнительные настройки</string> + <string name="haptic_feedback">Вибрация</string> + <string name="haptic_feedback_summary">Использовать вбирацию при обработке жеста</string> + +</resources> diff --git a/cmactions/res/values/colors.xml b/cmactions/res/values/colors.xml new file mode 100644 index 0000000..c1f38af --- /dev/null +++ b/cmactions/res/values/colors.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> +<resources> + <!-- Palette colors referenced by top-level themes. --> + <color name="theme_primary">#ff263238</color> + <color name="theme_primary_dark">#ff21272b</color> + <color name="theme_accent">#ff009688</color> +</resources> diff --git a/cmactions/res/values/dimens.xml b/cmactions/res/values/dimens.xml new file mode 100644 index 0000000..133701d --- /dev/null +++ b/cmactions/res/values/dimens.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> +<resources> + <!-- ActionBar contentInsetStart --> + <dimen name="actionbar_subsettings_contentInsetStart">72dp</dimen> +</resources> diff --git a/cmactions/res/values/strings.xml b/cmactions/res/values/strings.xml new file mode 100644 index 0000000..6ae6c87 --- /dev/null +++ b/cmactions/res/values/strings.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2013-2014 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. +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Gesture shortcuts --> + <string name="screen_gestures_panel_title">Gesture shortcuts</string> + <string name="screen_gestures_panel_summary">Use gestures while the screen is off</string> + + <string name="touchscreen_control_gesture_head">Screen Off Gestures</string> + <string name="touchscreen_control_gesture_title">Enable Screen Gestures</string> + <string name="gesture_category_title">Available Gestures</string> + <string name="touchscreen_dtp_gesture_title">Double Tap</string> + <string name="touchscreen_dtp_gesture_summary">Double Tap to Wake-Up device</string> + <string name="touchscreen_c_gesture_title">Camera</string> + <string name="touchscreen_c_gesture_summary">Draw a \"C\" to activate Camera</string> + <string name="touchscreen_z_gesture_title">Music</string> + <string name="touchscreen_z_gesture_summary">Draw an \"Z\" to Play/Pause</string> + <string name="touchscreen_ltr_gesture_title">Music</string> + <string name="touchscreen_ltr_gesture_summary">Swipe left to Prev Track</string> + <string name="touchscreen_gtr_gesture_title">Music</string> + <string name="touchscreen_gtr_gesture_summary">Swipe right to Next Track</string> + <string name="touchscreen_s_gesture_title">Notifications</string> + <string name="touchscreen_s_gesture_summary">Draw a \"S\" to activate \"Do Not Disturb\" Mode</string> + <string name="touchscreen_w_gesture_title">Notifications</string> + <string name="touchscreen_w_gesture_summary">Draw a \"W\" to activate \"Normal\" Mode</string> + <string name="touchscreen_m_gesture_title">Notifications</string> + <string name="touchscreen_m_gesture_summary">Draw a \"M\" to activate \"Mute\" Mode</string> + <string name="touchscreen_ydown_gesture_title">Flashlight</string> + <string name="touchscreen_ydown_gesture_summary">Draw a vertical line down to activate Flashlight</string> + + <string name="fpc_gesture_title">Fingerprint Sensor Gestures</string> + <string name="fpc_gesture_tap_summary">Tap once to Back</string> + <string name="fpc_gesture_left_summary">Swipe left for Menu</string> + <string name="fpc_gesture_right_summary">Swipe right for Recent Apps</string> + + <!-- haptic feedback --> + <string name="touchscreen_extras">Extras</string> + <string name="haptic_feedback">Haptic feedback</string> + <string name="haptic_feedback_summary">Vibrate when a gesture is detected</string> +</resources> diff --git a/cmactions/res/values/styles.xml b/cmactions/res/values/styles.xml new file mode 100644 index 0000000..b013f16 --- /dev/null +++ b/cmactions/res/values/styles.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2014-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. +--> +<resources> + <style name="Theme.Main" parent="@android:style/Theme.Material.Light.DarkActionBar"> + <item name="android:colorPrimary">@color/theme_primary</item> + <item name="android:colorPrimaryDark">@color/theme_primary_dark</item> + <item name="android:colorAccent">@color/theme_accent</item> + <!-- Redefine the ActionBar style for contentInsetStart --> + <item name="android:actionBarStyle">@style/Theme.ActionBar.SubSettings</item> + </style> + + <style name="Theme.ActionBar.SubSettings" parent="@android:style/Widget.Material.Light.ActionBar.Solid"> + <item name="android:contentInsetStart">@dimen/actionbar_subsettings_contentInsetStart</item> + </style> +</resources> diff --git a/cmactions/res/xml/touchscreen_panel.xml b/cmactions/res/xml/touchscreen_panel.xml new file mode 100644 index 0000000..edf8453 --- /dev/null +++ b/cmactions/res/xml/touchscreen_panel.xml @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> + + <PreferenceCategory + android:key="fpc_gestures" + android:title="@string/fpc_gesture_title" > + + <SwitchPreference + android:key="fpc_gesture_left" + android:title="@string/fpc_gesture_left_summary" /> + + <SwitchPreference + android:key="fpc_gesture_right" + android:title="@string/fpc_gesture_right_summary" /> + + </PreferenceCategory> + + <PreferenceCategory + android:title="@string/touchscreen_control_gesture_head" > + + <SwitchPreference + android:key="touchscreen_gesture_control" + android:title="@string/touchscreen_control_gesture_title" /> + + </PreferenceCategory> + + <PreferenceCategory + android:key="category_gestures" + android:title="@string/gesture_category_title" > + + <SwitchPreference + android:key="touchscreen_gesture_dtap" + android:title="@string/touchscreen_dtp_gesture_title" + android:summary="@string/touchscreen_dtp_gesture_summary" /> + + <SwitchPreference + android:key="touchscreen_gesture_c" + android:title="@string/touchscreen_c_gesture_title" + android:summary="@string/touchscreen_c_gesture_summary" /> + + <SwitchPreference + android:key="touchscreen_gesture_z" + android:title="@string/touchscreen_z_gesture_title" + android:summary="@string/touchscreen_z_gesture_summary" /> + + <SwitchPreference + android:key="touchscreen_gesture_ltr" + android:title="@string/touchscreen_ltr_gesture_title" + android:summary="@string/touchscreen_ltr_gesture_summary" /> + + <SwitchPreference + android:key="touchscreen_gesture_gtr" + android:title="@string/touchscreen_gtr_gesture_title" + android:summary="@string/touchscreen_gtr_gesture_summary" /> + + <SwitchPreference + android:key="touchscreen_gesture_s" + android:title="@string/touchscreen_s_gesture_title" + android:summary="@string/touchscreen_s_gesture_summary" /> + + <SwitchPreference + android:key="touchscreen_gesture_w" + android:title="@string/touchscreen_w_gesture_title" + android:summary="@string/touchscreen_w_gesture_summary" /> + + <SwitchPreference + android:key="touchscreen_gesture_m" + android:title="@string/touchscreen_m_gesture_title" + android:summary="@string/touchscreen_m_gesture_summary" /> + + <SwitchPreference + android:key="touchscreen_gesture_ydown" + android:title="@string/touchscreen_ydown_gesture_title" + android:summary="@string/touchscreen_ydown_gesture_summary" /> + + </PreferenceCategory> + + <PreferenceCategory + android:title="@string/touchscreen_extras"> + + <SwitchPreference + android:key="touchscreen_gesture_haptic_feedback" + android:title="@string/haptic_feedback" + android:summary="@string/haptic_feedback_summary" /> + + </PreferenceCategory> + +</PreferenceScreen> diff --git a/cmactions/src/com/cyanogenmod/settings/device/BootCompletedReceiver.java b/cmactions/src/com/cyanogenmod/settings/device/BootCompletedReceiver.java new file mode 100644 index 0000000..eb9e233 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/BootCompletedReceiver.java @@ -0,0 +1,69 @@ +/* + * 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 com.cyanogenmod.settings.device.ServiceWrapper.LocalBinder; + +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.util.Log; + +import com.cyanogenmod.settings.device.utils.FileUtils; + +public class BootCompletedReceiver extends BroadcastReceiver { + static final String TAG = "CMActions"; + private ServiceWrapper mServiceWrapper; + + @Override + public void onReceive(final Context context, Intent intent) { + Log.d(TAG, "Booting"); + enableComponent(context, TouchscreenGestureSettings.class.getName()); + context.startService(new Intent(context, ServiceWrapper.class)); + // Set sane default, for whatever reason gesture_mode loads with garbage at boot + FileUtils.writeAsByte(CMActionsSettings.TOUCHSCREEN_GESTURE_MODE_NODE, 256); + } + + private ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName className, IBinder service) { + LocalBinder binder = (LocalBinder) service; + mServiceWrapper = binder.getService(); + mServiceWrapper.start(); + } + + @Override + public void onServiceDisconnected(ComponentName className) { + mServiceWrapper = null; + } + }; + + private void enableComponent(Context context, String component) { + ComponentName name = new ComponentName(context, component); + PackageManager pm = context.getPackageManager(); + if (pm.getComponentEnabledSetting(name) + == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) { + pm.setComponentEnabledSetting(name, + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP); + } + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/CMActionsService.java b/cmactions/src/com/cyanogenmod/settings/device/CMActionsService.java new file mode 100644 index 0000000..3c09037 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/CMActionsService.java @@ -0,0 +1,44 @@ +/* + * 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.IntentService; +import android.content.Context; +import android.content.Intent; +import android.provider.Settings; +import android.util.Log; + +import java.util.List; +import java.util.LinkedList; + + +public class CMActionsService extends IntentService { + private static final String TAG = "CMActions"; + private final Context mContext; + + public CMActionsService(Context context) { + super("CMActionService"); + mContext = context; + Log.d(TAG, "Starting"); + CMActionsSettings cmActionsSettings = new CMActionsSettings(context ); + } + + @Override + protected void onHandleIntent(Intent intent) { + } +} + diff --git a/cmactions/src/com/cyanogenmod/settings/device/CMActionsSettings.java b/cmactions/src/com/cyanogenmod/settings/device/CMActionsSettings.java new file mode 100644 index 0000000..24bdb77 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/CMActionsSettings.java @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2015 The CyanogenMod Project + * Copyright (C) 2016 faust93 adaptation for Meizu PRO5 FTS Driver + * + * 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.content.ContentResolver; +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.provider.Settings; + +import android.util.Log; + +import com.cyanogenmod.settings.device.utils.FileUtils; + +import java.lang.Integer; + +public class CMActionsSettings { + private static final String TAG = "CMActions"; + + // Preference keys + public static final String TOUCHSCREEN_GESTURE_CONTROL_KEY = "touchscreen_gesture_control"; + public static final String TOUCHSCREEN_DOUBLETAP_KEY = "touchscreen_gesture_dtap"; + public static final String TOUCHSCREEN_C_GESTURE_KEY = "touchscreen_gesture_c"; + public static final String TOUCHSCREEN_Z_GESTURE_KEY = "touchscreen_gesture_z"; + public static final String TOUCHSCREEN_LTR_GESTURE_KEY = "touchscreen_gesture_ltr"; + public static final String TOUCHSCREEN_GTR_GESTURE_KEY = "touchscreen_gesture_gtr"; + public static final String TOUCHSCREEN_S_GESTURE_KEY = "touchscreen_gesture_s"; + public static final String TOUCHSCREEN_W_GESTURE_KEY = "touchscreen_gesture_w"; + public static final String TOUCHSCREEN_M_GESTURE_KEY = "touchscreen_gesture_m"; + public static final String TOUCHSCREEN_YDOWN_GESTURE_KEY = "touchscreen_gesture_ydown"; + + public static final String FPC_GESTURE_TAP_KEY = "fpc_gesture_tap"; + public static final String FPC_GESTURE_LEFT_GESTURE_KEY = "fpc_gesture_left"; + public static final String FPC_GESTURE_RIGHT_KEY = "fpc_gesture_right"; + + public static final String TOUCHSCREEN_GESTURE_HAPTIC_FEEDBACK = + "touchscreen_gesture_haptic_feedback"; + + // Proc nodes + public static final String TOUCHSCREEN_GESTURE_MODE_NODE = "/sys/devices/platform/mx-gs/gesture_control"; + + // Key Masks + public static final int KEY_MASK_DTP_CONTROL = 0x200; + public static final int KEY_MASK_GESTURE_DTP = 0x1000000; + + public static final int KEY_MASK_SWIPE_CONTROL = 0x400; + public static final int KEY_MASK_GESTURE_YDOWN = 0x4000000; + public static final int KEY_MASK_GESTURE_LTR = 0x1000000; + public static final int KEY_MASK_GESTURE_GTR = 0x2000000; + + public static final int KEY_MASK_GESTURE_CONTROL = 0x300; + public static final int KEY_MASK_GESTURE_C = 0x2000000; + public static final int KEY_MASK_GESTURE_E = 0x4000000; + public static final int KEY_MASK_GESTURE_S = 0x14000000; + public static final int KEY_MASK_GESTURE_V = 0x1000000; + public static final int KEY_MASK_GESTURE_W = 0x8000000; + public static final int KEY_MASK_GESTURE_Z = 0x40000000; + public static final int KEY_MASK_GESTURE_O = 0x80000000; + public static final int KEY_MASK_GESTURE_M = 0x10000000; + + public static final int DISABLE_ALL_MASK = 0x100; + public static final int ENABLE_ALL_MASK = 0x1000100; + + private static boolean mIsGestureEnabled; + private static boolean mIsGesture_DTP_Enabled; + private static boolean mIsGesture_C_Enabled; + private static boolean mIsGesture_E_Enabled; + private static boolean mIsGesture_S_Enabled; + private static boolean mIsGesture_V_Enabled; + private static boolean mIsGesture_O_Enabled; + private static boolean mIsGesture_M_Enabled; + private static boolean mIsGesture_W_Enabled; + private static boolean mIsGesture_Z_Enabled; + private static boolean mIsGesture_YDOWN_Enabled; + private static boolean mIsGesture_LTR_Enabled; + private static boolean mIsGesture_GTR_Enabled; + + private final Context mContext; + + private static SharedPreferences.OnSharedPreferenceChangeListener mPrefListener; + + public CMActionsSettings(Context context ) { + + SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context); + loadPreferences(sharedPrefs); + + mPrefListener = new SharedPreferences.OnSharedPreferenceChangeListener() { + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + boolean updated = true; + if (TOUCHSCREEN_GESTURE_CONTROL_KEY.equals(key)) { + mIsGestureEnabled = sharedPreferences.getBoolean(TOUCHSCREEN_GESTURE_CONTROL_KEY, false); + Log.d(TAG, "prefChanged: gesture control " + mIsGestureEnabled); + TouchscreenGestureSettings.gestureCat.setEnabled(areGesturesEnabled()); + } else if (TOUCHSCREEN_DOUBLETAP_KEY.equals(key)) { + mIsGesture_DTP_Enabled = sharedPreferences.getBoolean(TOUCHSCREEN_DOUBLETAP_KEY, false); + } else if (TOUCHSCREEN_C_GESTURE_KEY.equals(key)) { + mIsGesture_C_Enabled = sharedPreferences.getBoolean(TOUCHSCREEN_C_GESTURE_KEY, false); + } else if (TOUCHSCREEN_S_GESTURE_KEY.equals(key)) { + mIsGesture_S_Enabled = sharedPreferences.getBoolean(TOUCHSCREEN_S_GESTURE_KEY, false); + } else if (TOUCHSCREEN_W_GESTURE_KEY.equals(key)) { + mIsGesture_W_Enabled = sharedPreferences.getBoolean(TOUCHSCREEN_W_GESTURE_KEY, false); + } else if (TOUCHSCREEN_M_GESTURE_KEY.equals(key)) { + mIsGesture_M_Enabled = sharedPreferences.getBoolean(TOUCHSCREEN_M_GESTURE_KEY, false); + } else if (TOUCHSCREEN_Z_GESTURE_KEY.equals(key)) { + mIsGesture_Z_Enabled = sharedPreferences.getBoolean(TOUCHSCREEN_Z_GESTURE_KEY, false); + } else if (TOUCHSCREEN_YDOWN_GESTURE_KEY.equals(key)) { + mIsGesture_YDOWN_Enabled = sharedPreferences.getBoolean(TOUCHSCREEN_YDOWN_GESTURE_KEY, false); + } else if (TOUCHSCREEN_LTR_GESTURE_KEY.equals(key)) { + mIsGesture_LTR_Enabled = sharedPreferences.getBoolean(TOUCHSCREEN_LTR_GESTURE_KEY, false); + } else if (TOUCHSCREEN_GTR_GESTURE_KEY.equals(key)) { + mIsGesture_GTR_Enabled = sharedPreferences.getBoolean(TOUCHSCREEN_GTR_GESTURE_KEY, false); + } else if (TOUCHSCREEN_GESTURE_HAPTIC_FEEDBACK.equals(key)) { + //CMSettings.System.putInt(getContentResolver(),CMSettings.System.TOUCHSCREEN_GESTURE_HAPTIC_FEEDBACK, value ? 1 : 0); + final boolean val = sharedPreferences.getBoolean(TOUCHSCREEN_GTR_GESTURE_KEY, false); + } else { + updated = false; + } + if (updated) { + updateGestureMode(); + } + } + }; + + sharedPrefs.registerOnSharedPreferenceChangeListener(mPrefListener); + mContext = context; + } + + public static boolean areGesturesEnabled() { + Log.d(TAG,"Are gestures enabled:" +mIsGestureEnabled); + return mIsGestureEnabled; + } + + public static void loadPreferences(SharedPreferences sharedPreferences) { + mIsGestureEnabled = sharedPreferences.getBoolean(TOUCHSCREEN_GESTURE_CONTROL_KEY, false); + mIsGesture_DTP_Enabled = sharedPreferences.getBoolean(TOUCHSCREEN_DOUBLETAP_KEY, false); + mIsGesture_C_Enabled = sharedPreferences.getBoolean(TOUCHSCREEN_C_GESTURE_KEY, false); + mIsGesture_S_Enabled = sharedPreferences.getBoolean(TOUCHSCREEN_S_GESTURE_KEY, false); + mIsGesture_M_Enabled = sharedPreferences.getBoolean(TOUCHSCREEN_M_GESTURE_KEY, false); + mIsGesture_W_Enabled = sharedPreferences.getBoolean(TOUCHSCREEN_W_GESTURE_KEY, false); + mIsGesture_Z_Enabled = sharedPreferences.getBoolean(TOUCHSCREEN_Z_GESTURE_KEY, false); + mIsGesture_YDOWN_Enabled = sharedPreferences.getBoolean(TOUCHSCREEN_YDOWN_GESTURE_KEY, false); + mIsGesture_LTR_Enabled = sharedPreferences.getBoolean(TOUCHSCREEN_LTR_GESTURE_KEY, false); + mIsGesture_GTR_Enabled = sharedPreferences.getBoolean(TOUCHSCREEN_GTR_GESTURE_KEY, false); + + updateGestureMode(); + } + + + /* Use bitwise logic to set gesture_mode in kernel driver. + Check each if each key is enabled with & operator and KEY_MASK, + if enabled toggle the appropriate bit with ^ XOR operator */ + public static void updateGestureMode() { + int gesture_mode = 0; + + if (mIsGestureEnabled) { + FileUtils.writeAsByte(TOUCHSCREEN_GESTURE_MODE_NODE, ENABLE_ALL_MASK); + /* TAP_CTR masking */ + gesture_mode = (gesture_mode ^ KEY_MASK_DTP_CONTROL); + if (mIsGesture_DTP_Enabled) + gesture_mode = (gesture_mode ^ KEY_MASK_GESTURE_DTP); + Log.d(TAG, "Gesture mode DoubleTap: " + gesture_mode); + FileUtils.writeAsByte(TOUCHSCREEN_GESTURE_MODE_NODE, gesture_mode); + gesture_mode = 0; + /* SWIPE_CTR masking */ + gesture_mode = (gesture_mode ^ KEY_MASK_SWIPE_CONTROL); + if (mIsGesture_YDOWN_Enabled) + gesture_mode = (gesture_mode ^ KEY_MASK_GESTURE_YDOWN); + if (mIsGesture_LTR_Enabled) + gesture_mode = (gesture_mode ^ KEY_MASK_GESTURE_LTR); + if (mIsGesture_GTR_Enabled) + gesture_mode = (gesture_mode ^ KEY_MASK_GESTURE_GTR); + Log.d(TAG, "Gesture mode Swipe: " + gesture_mode); + FileUtils.writeAsByte(TOUCHSCREEN_GESTURE_MODE_NODE, gesture_mode); + gesture_mode = 0; + /* UNICODE_CTR masking */ + gesture_mode = (gesture_mode ^ KEY_MASK_GESTURE_CONTROL); + if (((gesture_mode & KEY_MASK_GESTURE_C) == 1) != mIsGesture_C_Enabled) + gesture_mode = (gesture_mode ^ KEY_MASK_GESTURE_C); + if (((gesture_mode & KEY_MASK_GESTURE_S) == 1) != mIsGesture_S_Enabled) + gesture_mode = (gesture_mode ^ KEY_MASK_GESTURE_S); + if (((gesture_mode & KEY_MASK_GESTURE_W) == 1) != mIsGesture_W_Enabled) + gesture_mode = (gesture_mode ^ KEY_MASK_GESTURE_W); + if (((gesture_mode & KEY_MASK_GESTURE_M) == 1) != mIsGesture_M_Enabled) + gesture_mode = (gesture_mode ^ KEY_MASK_GESTURE_M); + if (((gesture_mode & KEY_MASK_GESTURE_Z) == 1) != mIsGesture_Z_Enabled) + gesture_mode = (gesture_mode ^ KEY_MASK_GESTURE_Z); + } else { + gesture_mode = DISABLE_ALL_MASK; + } + Log.d(TAG, "finished gesture mode: " + gesture_mode); + FileUtils.writeAsByte(TOUCHSCREEN_GESTURE_MODE_NODE, gesture_mode); + } + +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/ServiceWrapper.java b/cmactions/src/com/cyanogenmod/settings/device/ServiceWrapper.java new file mode 100644 index 0000000..0a4b21c --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/ServiceWrapper.java @@ -0,0 +1,65 @@ +/* + * 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.content.Intent; +import android.os.Binder; +import android.os.Bundle; +import android.os.IBinder; +import android.util.Log; + +public class ServiceWrapper extends android.app.Service { + static final String TAG = "CMActions-ServiceWrapper"; + + private final IBinder mBinder = new LocalBinder(); + private CMActionsService mCmActionsService; + + public interface ServiceCallback { + void sendResults(int resultCode, Bundle b); + } + + public class LocalBinder extends Binder { + ServiceWrapper getService() { + // Return this instance of the service so clients can call public + // methods + return ServiceWrapper.this; + } + } + + @Override + public void onCreate() { + Log.i(TAG, "onCreate"); + super.onCreate(); + mCmActionsService = new CMActionsService(this); + } + + @Override + public IBinder onBind(Intent intent) { + Log.i(TAG, "onBind"); + return null; + } + + public void setCallback(ServiceCallback callback) { + } + + public void start() { + Log.i(TAG, "start"); + } + + public void stop() { + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/TouchscreenGestureSettings.java b/cmactions/src/com/cyanogenmod/settings/device/TouchscreenGestureSettings.java new file mode 100644 index 0000000..44bcc44 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/TouchscreenGestureSettings.java @@ -0,0 +1,67 @@ +/* + * 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 com.android.internal.util.cm.ScreenType; + +import android.app.ActionBar; +import android.os.Bundle; +import android.preference.PreferenceActivity; +import android.preference.PreferenceCategory; +import android.view.Menu; +import android.view.MenuItem; + +public class TouchscreenGestureSettings extends PreferenceActivity { + public static final String CATEGORY_GESTURES = "category_gestures"; + public static PreferenceCategory gestureCat; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.touchscreen_panel); + gestureCat = (PreferenceCategory) findPreference(CATEGORY_GESTURES); + if (gestureCat != null) { + gestureCat.setEnabled(CMActionsSettings.areGesturesEnabled()); + } + final ActionBar actionBar = getActionBar(); + actionBar.setDisplayHomeAsUpEnabled(true); + } + + @Override + protected void onResume() { + super.onResume(); + + gestureCat = (PreferenceCategory) findPreference(CATEGORY_GESTURES); + if (gestureCat != null) { + gestureCat.setEnabled(CMActionsSettings.areGesturesEnabled()); + } + + // If running on a phone, remove padding around the listview + if (!ScreenType.isTablet(this)) { + getListView().setPadding(0, 0, 0, 0); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + onBackPressed(); + return true; + } + return false; + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/UpdatedStateNotifier.java b/cmactions/src/com/cyanogenmod/settings/device/UpdatedStateNotifier.java new file mode 100644 index 0000000..268b4bd --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/UpdatedStateNotifier.java @@ -0,0 +1,21 @@ +/* + * 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; + +interface UpdatedStateNotifier { + public void updateState(); +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/utils/FileUtils.java b/cmactions/src/com/cyanogenmod/settings/device/utils/FileUtils.java new file mode 100644 index 0000000..64ed3d6 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/utils/FileUtils.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2013 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.utils; + +import android.util.Log; + +import java.io.BufferedReader; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.nio.ByteBuffer; + +public final class FileUtils { + private static final String TAG = "FileUtils"; + + private FileUtils() { + // this class is not supposed to be instantiated + } + + /** + * Reads the first line of text from the given file + */ + public static String readOneLine(String fileName) { + String line = null; + BufferedReader reader = null; + + try { + reader = new BufferedReader(new FileReader(fileName), 512); + line = reader.readLine(); + } catch (IOException e) { + Log.e(TAG, "Could not read from file " + fileName, e); + } finally { + try { + if (reader != null) { + reader.close(); + } + } catch (IOException e) { + // ignored, not much we can do anyway + } + } + + return line; + } + + /** + * Writes the given value into the given file + * + * @return true on success, false on failure + */ + public static boolean writeLine(String fileName, String value) { + try { + FileOutputStream fos = new FileOutputStream(fileName); + fos.write(value.getBytes()); + fos.flush(); + fos.close(); + } catch (IOException e) { + Log.e(TAG, "Could not write to file " + fileName, e); + return false; + } + + return true; + } + + public static boolean writeAsByte(String fileName, int value) { + byte[] bytes = ByteBuffer.allocate(4).putInt(value).array(); + try { + FileOutputStream fos = new FileOutputStream(fileName); + fos.write(bytes); + fos.flush(); + fos.close(); + } catch (IOException e) { + Log.e(TAG, "Could not write to file " + fileName, e); + return false; + } + + return true; + } +} diff --git a/cmhw/org/cyanogenmod/hardware/KeyDisabler.java b/cmhw/org/cyanogenmod/hardware/KeyDisabler.java index b101869..038e1a5 100644 --- a/cmhw/org/cyanogenmod/hardware/KeyDisabler.java +++ b/cmhw/org/cyanogenmod/hardware/KeyDisabler.java @@ -16,7 +16,10 @@ package org.cyanogenmod.hardware; -import android.util.Log; +import java.io.File; + +import org.cyanogenmod.hardware.util.FileUtils; + /* * Disable capacitive keys * @@ -28,31 +31,17 @@ import android.util.Log; public class KeyDisabler { - private static boolean isActive = false; - /* - * All HAF classes should export this boolean. - * Real implementations must, of course, return true - */ - - public static boolean isSupported() { return true; } + private static String CONTROL_PATH = "/proc/nav_switch"; - /* - * Are the keys currently blocked? - */ + public static boolean isSupported() { + return new File(CONTROL_PATH).exists(); + } public static boolean isActive() { - return isActive; + return (FileUtils.readOneLine(CONTROL_PATH).contains(":0")); } - /* - * Disable capacitive keys - */ - public static boolean setActive(boolean state) { - //throw new UnsupportedOperationException(); - isActive = state; - Log.i("KeyDisabler", "setActive " + state); - return isActive; + return FileUtils.writeLine(CONTROL_PATH, (state ? "0" : "2")); } - } diff --git a/device_m2note.mk b/device_m2note.mk index ccdd09d..67eb2b4 100644 --- a/device_m2note.mk +++ b/device_m2note.mk @@ -10,6 +10,16 @@ PRODUCT_AAPT_PREF_CONFIG := xxhdpi # Recovery allowed devices TARGET_OTA_ASSERT_DEVICE := m2note,m571,m2n,meizu6753_65c_l1 +# Keyhandlers and gestures +PRODUCT_PACKAGES += \ + CMActions \ + com.cyanogenmod.keyhandler + +PRODUCT_SYSTEM_SERVER_JARS += com.cyanogenmod.keyhandler + +# never dexopt the keyhandler +$(call add-product-dex-preopt-module-config,com.cyanogenmod.keyhandler,disable) + # init.rc's PRODUCT_COPY_FILES += \ device/meizu/m2note/rootdir/init.mt6735.rc:root/init.mt6735.rc \ diff --git a/keyhandler/Android.mk b/keyhandler/Android.mk new file mode 100644 index 0000000..d8d40fe --- /dev/null +++ b/keyhandler/Android.mk @@ -0,0 +1,13 @@ +LOCAL_PATH:= $(call my-dir) + +ifeq ($(TARGET_DEVICE),m2note) +include $(CLEAR_VARS) + +LOCAL_MODULE := com.cyanogenmod.keyhandler +LOCAL_SRC_FILES := $(call all-java-files-under,src) +LOCAL_MODULE_TAGS := optional +LOCAL_DEX_PREOPT := false + +include $(BUILD_JAVA_LIBRARY) +endif + 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); + } + } +} |
