diff --git a/LineageActions/Android.mk b/LineageActions/Android.mk index aabf60a..34e2458 100644 --- a/LineageActions/Android.mk +++ b/LineageActions/Android.mk @@ -29,10 +29,8 @@ LOCAL_RESOURCE_DIR := \ LOCAL_AAPT_FLAGS := --auto-add-overlay \ --extra-packages android.support.v14.preference:android.support.v7.appcompat:android.support.v7.preference:android.support.v7.recyclerview -ifneq ($(INCREMENTAL_BUILDS),) - LOCAL_PROGUARD_ENABLED := disabled - LOCAL_JACK_ENABLED := incremental -endif +LOCAL_PROGUARD_ENABLED := disabled +LOCAL_DEX_PREOPT := false include frameworks/base/packages/SettingsLib/common.mk diff --git a/LineageActions/AndroidManifest.xml b/LineageActions/AndroidManifest.xml index dc69823..37de0e0 100644 --- a/LineageActions/AndroidManifest.xml +++ b/LineageActions/AndroidManifest.xml @@ -10,12 +10,14 @@ + @@ -32,7 +34,7 @@ @@ -43,7 +45,8 @@ @@ -54,6 +57,27 @@ + + + + + + + + + + diff --git a/LineageActions/proguard.flags b/LineageActions/proguard.flags deleted file mode 100644 index ab22f4b..0000000 --- a/LineageActions/proguard.flags +++ /dev/null @@ -1,9 +0,0 @@ --keep class org.lineageos.LineageActions.* { - *; -} - --keepclasseswithmembers class * { - public (android.content.Context, android.util.AttributeSet); -} - --keep class ** extends android.support.v14.preference.PreferenceFragment diff --git a/LineageActions/res/drawable/ic_gesture.png b/LineageActions/res/drawable/ic_gesture.png new file mode 100644 index 0000000..c9a3646 Binary files /dev/null and b/LineageActions/res/drawable/ic_gesture.png differ diff --git a/LineageActions/res/drawable/ic_settings_doze.xml b/LineageActions/res/drawable/ic_settings_doze.xml new file mode 100644 index 0000000..1cbb485 --- /dev/null +++ b/LineageActions/res/drawable/ic_settings_doze.xml @@ -0,0 +1,29 @@ + + + + + + + diff --git a/LineageActions/res/drawable/ic_settings_fingerprint.xml b/LineageActions/res/drawable/ic_settings_fingerprint.xml new file mode 100644 index 0000000..a080e1c --- /dev/null +++ b/LineageActions/res/drawable/ic_settings_fingerprint.xml @@ -0,0 +1,9 @@ + + + + diff --git a/LineageActions/res/drawable/ic_settings_gestures.xml b/LineageActions/res/drawable/ic_settings_gestures.xml index 95cdede..a49a8d7 100644 --- a/LineageActions/res/drawable/ic_settings_gestures.xml +++ b/LineageActions/res/drawable/ic_settings_gestures.xml @@ -18,7 +18,8 @@ android:width="24dp" android:height="24dp" android:viewportWidth="24" - android:viewportHeight="24"> + android:viewportHeight="24" + android:tint="?android:attr/colorAccent"> + + + diff --git a/LineageActions/res/values-pt-rBR/strings.xml b/LineageActions/res/values-pt-rBR/strings.xml new file mode 100644 index 0000000..8a8af86 --- /dev/null +++ b/LineageActions/res/values-pt-rBR/strings.xml @@ -0,0 +1,94 @@ + + + + + Moto Ações + + + Gestos do dispositivo + Gerenciar os gestos do dispositivo + + + Gerenciar os gestos da tela ambiente + + + Gestos no sensor biométrico + Habilitar o uso de gestos no sensor biométrico + Gerenciar os gestos do sensor biométrico + Ações com a tela ligada + Toque único + Selecione a ação para toque único + Toque duplo + Selecione a ação para toque duplo + Toque longo + Selecione a ação para toque longo + Deslizar para a esquerda + Selecione a ação para deslizar para a esquerda + Deslizar para a direita + Selecione a ação para deslizar para a direita + + + Habilitar com a tela desligada + Habilitar os gestos no sensor biométrico quando a tela estiver desligada.\n\nO desbloqueio por impressão digital deve estar desativado para usar esse recurso. + Ações com a tela desligada + + + Não fazer nada + Início + Ligar/desligar tela + Acordar o dispositivo + Voltar + Recentes + Aumentar volume + Diminuir volume + Assistente de voz + Tocar/pausar + Faixa anterior + Próxima faixa + Ligar/desligar lanterna + Abrir câmera + Tirar uma captura de tela + Abrir navegador + Abrir discador + Abrir app de mail + Abrir app de mensagens + Modo picture-in-picture + + + Gestos com a tela desligada + Gerenciar os gestos com a tela desligada + Deslizar para a esquerda + Selecione a ação para deslizar para a esquerda + Deslizar para a direita + Selecione a ação para deslizar para a direita + Deslizar para cima + Selecione a ação para deslizar para cima + Deslizar para baixo + Selecione a ação para deslizar para baixo + + + Tocar para ativar + Toque duas vezes em qualquer parte da tela para ativar o dispositivo + + + Retorno tátil + Vibrar quando um gesto for detectado + + + O aplicativo não tem suporte ao modo picture-in-picture. + diff --git a/LineageActions/res/values/array.xml b/LineageActions/res/values/array.xml index eb7e711..2843b4b 100644 --- a/LineageActions/res/values/array.xml +++ b/LineageActions/res/values/array.xml @@ -16,29 +16,87 @@ --> - None - Home - Power - Back - Recents - Volume Up - Volume Down - Voice Assistant - Play/Pause - Previous Track - Next Track + @string/action_none + @string/action_home + @string/action_power + @string/action_back + @string/action_recents + @string/action_volume_up + @string/action_volume_down + @string/action_voice_assistant + @string/action_play_pause + @string/action_previous_track + @string/action_next_track + @string/action_flashlight + @string/action_camera + @string/action_screenshot + @string/action_pip 0 - 102 - 116 - 158 - 580 - 115 - 114 - 582 - 164 - 165 - 163 + 100 + 101 + 102 + 103 + 104 + 105 + 106 + 107 + 108 + 109 + 110 + 111 + 112 + 120 + + + + @string/action_none + @string/action_power + @string/action_volume_up + @string/action_volume_down + @string/action_play_pause + @string/action_previous_track + @string/action_next_track + @string/action_flashlight + @string/action_camera + + + 0 + 101 + 104 + 105 + 107 + 108 + 109 + 110 + 111 + + + + @string/action_none + @string/action_wake + @string/action_play_pause + @string/action_previous_track + @string/action_next_track + @string/action_flashlight + @string/action_camera + @string/action_browser + @string/action_dialer + @string/action_email + @string/action_messages + + + 0 + 101 + 107 + 108 + 109 + 110 + 111 + 116 + 117 + 118 + 119 diff --git a/LineageActions/res/values/strings.xml b/LineageActions/res/values/strings.xml index 6e07fe2..56bd4ed 100644 --- a/LineageActions/res/values/strings.xml +++ b/LineageActions/res/values/strings.xml @@ -16,6 +16,79 @@ limitations under the License. --> + Moto Actions - Manage custom actions and fingerprint gestures + + + Device gestures + Manage device gestures + + + Manage ambient display gestures + + + Fingerprint gestures + Use fingerprint gestures + Manage fingerprint gestures + Actions with screen on + Single tap + Select action for single tap + Double tap + Select action for double tap + Long tap + Select action for long tap + Swipe left + Select action for swipe left + Swipe right + Select action for swipe right + + + Fingerprint gestures when screen off + Use fingerprint gestures when screen off.\n\nFingerprint unlocking must be disabled to use this feature. + Actions with screen off + + + None + Home + Screen on/off + Wake + Back + Recents + Volume up + Volume down + Voice assistant + Play/pause + Previous track + Next track + Flashlight on/off + Open camera + Take screenshot + Open browser + Open dialer + Open email app + Open messages app + Picture-in-Picture mode + + + Screen off gestures + Manage gestures when screen is off + Swipe left + Select action for swipe left + Swipe right + Select action for swipe right + Swipe up + Select action for swipe up + Swipe down + Select action for swipe down + + + Tap to wake + Double-tap anywhere on the screen to wake device + + + Haptic feedback + Vibrate when a touchscreen gesture is detected + + + App does not support picture-in-picture mode. diff --git a/LineageActions/res/values/symbols.xml b/LineageActions/res/values/symbols.xml new file mode 100644 index 0000000..71b806a --- /dev/null +++ b/LineageActions/res/values/symbols.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/LineageActions/res/xml/actions_panel.xml b/LineageActions/res/xml/actions_panel.xml index 11f6c53..cf725f8 100644 --- a/LineageActions/res/xml/actions_panel.xml +++ b/LineageActions/res/xml/actions_panel.xml @@ -7,7 +7,7 @@ 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 + 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, @@ -16,157 +16,36 @@ limitations under the License. --> + xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"> - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/LineageActions/res/xml/doze_panel.xml b/LineageActions/res/xml/doze_panel.xml index bba3a9d..d50cd73 100644 --- a/LineageActions/res/xml/doze_panel.xml +++ b/LineageActions/res/xml/doze_panel.xml @@ -17,29 +17,24 @@ - + - + - - - - + diff --git a/LineageActions/res/xml/fp_gesture_panel.xml b/LineageActions/res/xml/fp_gesture_panel.xml new file mode 100644 index 0000000..63a9c84 --- /dev/null +++ b/LineageActions/res/xml/fp_gesture_panel.xml @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LineageActions/res/xml/main_panel.xml b/LineageActions/res/xml/main_panel.xml new file mode 100644 index 0000000..f368c4e --- /dev/null +++ b/LineageActions/res/xml/main_panel.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/LineageActions/res/xml/screen_off_gesture_panel.xml b/LineageActions/res/xml/screen_off_gesture_panel.xml new file mode 100644 index 0000000..f73d272 --- /dev/null +++ b/LineageActions/res/xml/screen_off_gesture_panel.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + diff --git a/LineageActions/src/org/lineageos/settings/device/ActionsPreferenceActivity.java b/LineageActions/src/org/lineageos/settings/device/ActionsPreferenceActivity.java index ceea8a6..2889b39 100644 --- a/LineageActions/src/org/lineageos/settings/device/ActionsPreferenceActivity.java +++ b/LineageActions/src/org/lineageos/settings/device/ActionsPreferenceActivity.java @@ -25,7 +25,9 @@ public class ActionsPreferenceActivity extends PreferenceActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - getFragmentManager().beginTransaction() - .replace(android.R.id.content, new ActionsPreferenceFragment()).commit(); + if (savedInstanceState == null){ + getFragmentManager().beginTransaction() + .replace(android.R.id.content, new ActionsPreferenceFragment()).commit(); + } } } diff --git a/LineageActions/src/org/lineageos/settings/device/ActionsPreferenceFragment.java b/LineageActions/src/org/lineageos/settings/device/ActionsPreferenceFragment.java index 120fce3..755c2fe 100644 --- a/LineageActions/src/org/lineageos/settings/device/ActionsPreferenceFragment.java +++ b/LineageActions/src/org/lineageos/settings/device/ActionsPreferenceFragment.java @@ -17,80 +17,12 @@ package org.lineageos.settings.device; -import android.app.ActionBar; -import android.app.AlertDialog; -import android.app.NotificationManager; import android.os.Bundle; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.support.v7.preference.PreferenceCategory; import android.support.v14.preference.PreferenceFragment; -import android.support.v7.preference.Preference; -import android.support.v14.preference.SwitchPreference; -import android.view.Menu; -import android.view.MenuItem; -import android.text.TextUtils; - -import java.io.File; - -import org.lineageos.internal.util.FileUtils; -import org.lineageos.settings.device.actions.Constants; public class ActionsPreferenceFragment extends PreferenceFragment { - private SwitchPreference mFlipPref; - private NotificationManager mNotificationManager; - private boolean mFlipClick = false; - @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { - addPreferencesFromResource(R.xml.actions_panel); - final ActionBar actionBar = getActivity().getActionBar(); - actionBar.setDisplayHomeAsUpEnabled(true); - mNotificationManager = (NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE); - mFlipPref = (SwitchPreference) findPreference("gesture_flip_to_mute"); - mFlipPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - public boolean onPreferenceClick(Preference preference) { - if (!mNotificationManager.isNotificationPolicyAccessGranted()) { - mFlipPref.setChecked(false); - new AlertDialog.Builder(getContext()) - .setTitle(getString(R.string.flip_to_mute_title)) - .setMessage(getString(R.string.dnd_access)) - .setNegativeButton(android.R.string.cancel, null) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - mFlipClick = true; - startActivity(new Intent( - android.provider.Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS)); - } - }).show(); - } - return true; - } - }); - - //Users may deny DND access after giving it - if (!mNotificationManager.isNotificationPolicyAccessGranted()) { - mFlipPref.setChecked(false); - } - } - - @Override - public void onResume() { - super.onResume(); - - if (mNotificationManager.isNotificationPolicyAccessGranted() && mFlipClick) { - mFlipPref.setChecked(true); - } - } - - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - getActivity().onBackPressed(); - return true; - } - return false; + addPreferencesFromResource(R.xml.main_panel); } } diff --git a/LineageActions/src/org/lineageos/settings/device/BootCompletedReceiver.java b/LineageActions/src/org/lineageos/settings/device/BootCompletedReceiver.java index 01d3199..9f0492c 100644 --- a/LineageActions/src/org/lineageos/settings/device/BootCompletedReceiver.java +++ b/LineageActions/src/org/lineageos/settings/device/BootCompletedReceiver.java @@ -42,7 +42,7 @@ public class BootCompletedReceiver extends BroadcastReceiver { Log.i(TAG, "Booting"); // Restore nodes to saved preference values - for (String pref : Constants.sButtonPrefKeys) { + for (String pref : Constants.sPrefKeys) { Constants.writePreference(context, pref); } diff --git a/LineageActions/src/org/lineageos/settings/device/DozePreferenceActivity.java b/LineageActions/src/org/lineageos/settings/device/DozePreferenceActivity.java deleted file mode 100644 index 0047039..0000000 --- a/LineageActions/src/org/lineageos/settings/device/DozePreferenceActivity.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2017 The LineageOS 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 org.lineageos.settings.device; - -import android.os.Bundle; -import android.preference.PreferenceActivity; -import android.provider.Settings; -import android.support.v7.preference.Preference; -import android.support.v7.preference.PreferenceCategory; -import android.support.v14.preference.PreferenceFragment; -import android.support.v14.preference.SwitchPreference; -import android.view.MenuItem; - -public class DozePreferenceActivity extends PreferenceActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getActionBar().setDisplayHomeAsUpEnabled(true); - getFragmentManager().beginTransaction() - .replace(android.R.id.content, new DozePreferenceFragment()).commit(); - } - - public class DozePreferenceFragment extends PreferenceFragment { - private static final String KEY_AMBIENT_DISPLAY_ENABLE = "doze_enabled"; - - private SwitchPreference mAmbientDisplayPreference; - - @Override - public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { - addPreferencesFromResource(R.xml.doze_panel); - boolean dozeEnabled = LineageActionsSettings.isDozeEnabled(getActivity().getContentResolver()); - mAmbientDisplayPreference = (SwitchPreference) findPreference(KEY_AMBIENT_DISPLAY_ENABLE); - // Read from DOZE_ENABLED secure setting - mAmbientDisplayPreference.setChecked(dozeEnabled); - mAmbientDisplayPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - boolean enable = (boolean) newValue; - return enableDoze(enable); - } - }); - } - - private boolean enableDoze(boolean enable) { - return Settings.Secure.putInt(getContext().getContentResolver(), - Settings.Secure.DOZE_ENABLED, enable ? 1 : 0); - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - onBackPressed(); - return true; - } - return super.onOptionsItemSelected(item); - } -} diff --git a/LineageActions/src/org/lineageos/settings/device/DozeSettings.java b/LineageActions/src/org/lineageos/settings/device/DozeSettings.java new file mode 100644 index 0000000..4f54250 --- /dev/null +++ b/LineageActions/src/org/lineageos/settings/device/DozeSettings.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017 The LineageOS 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 org.lineageos.settings.device; + +import android.os.Bundle; +import android.preference.PreferenceActivity; +import android.provider.Settings; +import android.preference.Preference; +import android.preference.PreferenceCategory; +import android.preference.SwitchPreference; +import android.view.MenuItem; + +public class DozeSettings extends PreferenceActivity { + + + private static final String KEY_AMBIENT_DISPLAY_ENABLE = "doze_enabled"; + + private SwitchPreference mAmbientDisplayPreference; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.doze_panel); + getActionBar().setDisplayHomeAsUpEnabled(true); + boolean dozeEnabled = LineageActionsSettings.isDozeEnabled(getContentResolver()); + mAmbientDisplayPreference = (SwitchPreference) findPreference(KEY_AMBIENT_DISPLAY_ENABLE); + // Read from DOZE_ENABLED secure setting + mAmbientDisplayPreference.setChecked(dozeEnabled); + mAmbientDisplayPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + boolean enable = (boolean) newValue; + return enableDoze(enable); + } + }); + } + + private boolean enableDoze(boolean enable) { + return Settings.Secure.putInt(getContentResolver(), + Settings.Secure.DOZE_ENABLED, enable ? 1 : 0); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + onBackPressed(); + return true; + } + return super.onOptionsItemSelected(item); + } +} diff --git a/LineageActions/src/org/lineageos/settings/device/FPGestureSettings.java b/LineageActions/src/org/lineageos/settings/device/FPGestureSettings.java new file mode 100644 index 0000000..b4a64bb --- /dev/null +++ b/LineageActions/src/org/lineageos/settings/device/FPGestureSettings.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016 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 org.lineageos.settings.device; + +import android.os.Bundle; +import android.content.Context; +import android.preference.PreferenceCategory; +import android.preference.SwitchPreference; +import android.hardware.fingerprint.FingerprintManager; +import android.preference.PreferenceActivity; +import android.view.MenuItem; + +public class FPGestureSettings extends PreferenceActivity { + + private SwitchPreference mFPScreenOffGesture; + private PreferenceCategory mFPScreenOffCategory; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.fp_gesture_panel); + getActionBar().setDisplayHomeAsUpEnabled(true); + mFPScreenOffGesture = (SwitchPreference) findPreference("fp_home_scr_off"); + mFPScreenOffCategory = (PreferenceCategory) findPreference("fp_keys_scr_off"); + boolean hasEnrolledFingerprints = hasEnrolledFingerprints(); + mFPScreenOffGesture.setEnabled(!hasEnrolledFingerprints); + mFPScreenOffCategory.setEnabled(!hasEnrolledFingerprints); + } + + private boolean hasEnrolledFingerprints(){ + FingerprintManager fingerprintManager = (FingerprintManager) getSystemService(Context.FINGERPRINT_SERVICE); + return fingerprintManager.hasEnrolledFingerprints(); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + onBackPressed(); + return true; + } + return super.onOptionsItemSelected(item); + } + +} diff --git a/LineageActions/src/org/lineageos/settings/device/GestureSettings.java b/LineageActions/src/org/lineageos/settings/device/GestureSettings.java new file mode 100644 index 0000000..f92f167 --- /dev/null +++ b/LineageActions/src/org/lineageos/settings/device/GestureSettings.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2016 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 org.lineageos.settings.device; + +import android.app.AlertDialog; +import android.app.NotificationManager; +import android.os.Bundle; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.preference.PreferenceActivity; +import android.preference.PreferenceCategory; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceClickListener; +import android.preference.SwitchPreference; +import android.view.MenuItem; + +public class GestureSettings extends PreferenceActivity { + + private SwitchPreference mFlipPref; + private NotificationManager mNotificationManager; + private boolean mFlipClick = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.actions_panel); + getActionBar().setDisplayHomeAsUpEnabled(true); + mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + mFlipPref = (SwitchPreference) findPreference("gesture_flip_to_mute"); + + mFlipPref.setOnPreferenceClickListener(new OnPreferenceClickListener() { + public boolean onPreferenceClick(Preference preference) { + if (!mNotificationManager.isNotificationPolicyAccessGranted()) { + mFlipPref.setChecked(false); + new AlertDialog.Builder(GestureSettings.this) + .setTitle(getString(R.string.flip_to_mute_title)) + .setMessage(getString(R.string.dnd_access)) + .setNegativeButton(android.R.string.cancel, null) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + mFlipClick = true; + startActivity(new Intent( + android.provider.Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS)); + } + }).show(); + } + return true; + } + }); + + //Users may deny DND access after giving it + if (!mNotificationManager.isNotificationPolicyAccessGranted()) { + mFlipPref.setChecked(false); + } + } + + @Override + public void onResume() { + super.onResume(); + if (mNotificationManager.isNotificationPolicyAccessGranted() && mFlipClick) { + mFlipPref.setChecked(true); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + onBackPressed(); + return true; + } + return super.onOptionsItemSelected(item); + } + +} diff --git a/LineageActions/src/org/lineageos/settings/device/KeyHandler.java b/LineageActions/src/org/lineageos/settings/device/KeyHandler.java new file mode 100644 index 0000000..78d335c --- /dev/null +++ b/LineageActions/src/org/lineageos/settings/device/KeyHandler.java @@ -0,0 +1,951 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * Copyright (C) 2017 The LineageOS 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 org.lineageos.settings.device; + +import android.app.ActivityManager; +import android.app.ActivityManagerNative; +import android.app.KeyguardManager; +import android.app.NotificationManager; +import android.app.ISearchManager; +import android.widget.Toast; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.database.ContentObserver; +import android.content.res.Resources; +import android.content.pm.ActivityInfo; +import android.content.ComponentName; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.provider.MediaStore; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.hardware.camera2.CameraAccessException; +import android.hardware.camera2.CameraCharacteristics; +import android.hardware.camera2.CameraManager; +import android.hardware.input.InputManager; +import android.media.AudioAttributes; +import android.media.session.MediaSessionLegacyHelper; +import android.os.Bundle; +import android.net.Uri; +import android.os.Handler; +import android.os.Looper; +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.os.VibrationEffect; +import android.util.Log; +import android.provider.Settings; +import android.view.InputDevice; +import android.view.KeyCharacterMap; +import android.view.KeyEvent; +import android.view.ViewConfiguration; +import android.view.IWindowManager; +import android.view.WindowManagerGlobal; +import android.text.TextUtils; +import android.Manifest; + +import java.util.List; + +import com.android.internal.os.DeviceKeyHandler; +import com.android.internal.util.ArrayUtils; + +import lineageos.providers.LineageSettings; +import org.lineageos.internal.util.FileUtils; + +import static org.lineageos.settings.device.actions.Constants.*; + +public class KeyHandler implements DeviceKeyHandler { + + private static final String TAG = KeyHandler.class.getSimpleName(); + + private static final int GESTURE_REQUEST = 1; + private static final int FP_ACTION_REQUEST = 2; + + private static final String ACTION_DISMISS_KEYGUARD = + "com.android.keyguard.action.DISMISS_KEYGUARD_SECURELY"; + + private static final String GESTURE_WAKEUP_REASON = "keyhandler-gesture-wakeup"; + private static final int GESTURE_WAKELOCK_DURATION = 3000; + + private final Context mContext; + private final PowerManager mPowerManager; + private final NotificationManager mNotificationManager; + WakeLock mProximityWakeLock; + WakeLock mGestureWakeLock; + private KeyguardManager mKeyguardManager; + private ScreenOffGesturesHandler mScreenOffGesturesHandler; + private FPScreenOffGesturesHandler mFPScreenOffGesturesHandler; + private SensorManager mSensorManager; + private CameraManager mCameraManager; + private String mRearCameraId; + private boolean mTorchEnabled; + private Sensor mProximitySensor; + private Vibrator mVibrator; + private int mProximityTimeOut; + private boolean mProximityWakeSupported; + + private ISearchManager mSearchManagerService; + + private Handler mHandler; + private int fpTapCounts = 0; + private boolean fpTapPending = false; + private boolean screenOffGesturePending = false; + + public boolean mIsHapticFeedbackEnabledOnSystem; + + private SettingsObserver mSettingsObserver; + + private class SettingsObserver extends ContentObserver { + SettingsObserver(Handler handler) { + super(handler); + } + + void observe() { + mContext.getContentResolver().registerContentObserver(Settings.System.getUriFor( + Settings.System.HAPTIC_FEEDBACK_ENABLED), false, this, UserHandle.USER_ALL); + update(); + } + + @Override + public void onChange(boolean selfChange) { + update(); + } + + public void update() { + mIsHapticFeedbackEnabledOnSystem = Settings.System.getIntForUser(mContext.getContentResolver(), + Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 1; + } + } + + private void setHapticFeedbackEnabledOnSystem(boolean enabled){ + Settings.System.putIntForUser(mContext.getContentResolver(), + Settings.System.HAPTIC_FEEDBACK_ENABLED, enabled ? 1 : 0, UserHandle.USER_CURRENT); + } + + private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) + .build(); + + public KeyHandler(Context context) { + mContext = context; + + mSettingsObserver = new SettingsObserver(new Handler()); + mSettingsObserver.observe(); + + mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + mNotificationManager + = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + mScreenOffGesturesHandler = new ScreenOffGesturesHandler(); + mFPScreenOffGesturesHandler = new FPScreenOffGesturesHandler(); + + mGestureWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, + "GestureWakeLock"); + + final Resources resources = mContext.getResources(); + mProximityTimeOut = resources.getInteger( + org.lineageos.platform.internal.R.integer.config_proximityCheckTimeout); + mProximityWakeSupported = resources.getBoolean( + org.lineageos.platform.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; + } + + mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE); + mCameraManager.registerTorchCallback(new MyTorchCallback(), mScreenOffGesturesHandler); + mCameraManager.registerTorchCallback(new MyTorchCallback(), mFPScreenOffGesturesHandler); + + mHandler = new Handler(Looper.getMainLooper()); + } + + static long[] getLongIntArray(Resources r, int resid) { + int[] ar = r.getIntArray(resid); + if (ar == null) { + return null; + } + long[] out = new long[ar.length]; + for (int i=0; i resInfo = pm.queryIntentActivities(intent, 0); + if (resInfo.isEmpty()) { + return null; + } + return pm.getLaunchIntentForPackage(resInfo.get(0).activityInfo.packageName); + } + + private void triggerCameraAction(){ + ensureKeyguardManager(); + WakeLock wl = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "GestureWakeLock"); + wl.acquire(500); + if (mKeyguardManager.inKeyguardRestrictedInputMode()) { + launchSecureCamera(); + } else { + launchCamera(); + } + } + + private void launchCamera() { + Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags(Intent.FLAG_FROM_BACKGROUND); + if (getBestActivityInfo(intent) != null) { + // Only launch if we can succeed, but let the user pick the action + mContext.startActivity(intent); + } + } + + private void launchSecureCamera() { + // Keyguard won't allow a picker, try to pick the secure intent in the package + // that would be the one used for a default action of launching the camera + Intent normalIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); + normalIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + normalIntent.addFlags(Intent.FLAG_FROM_BACKGROUND); + + Intent secureIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE); + secureIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + secureIntent.addFlags(Intent.FLAG_FROM_BACKGROUND); + + ActivityInfo normalActivity = getBestActivityInfo(normalIntent); + ActivityInfo secureActivity = getBestActivityInfo(secureIntent, normalActivity); + if (secureActivity != null) { + secureIntent.setComponent(new ComponentName(secureActivity.applicationInfo.packageName, secureActivity.name)); + mContext.startActivity(secureIntent); + } + } + + private ActivityInfo getBestActivityInfo(Intent intent) { + PackageManager pm = mContext.getPackageManager(); + ResolveInfo resolveInfo = pm.resolveActivity(intent, 0); + if (resolveInfo != null) { + return resolveInfo.activityInfo; + } else { + // If the resolving failed, just find our own best match + return getBestActivityInfo(intent, null); + } + } + + private ActivityInfo getBestActivityInfo(Intent intent, ActivityInfo match) { + PackageManager pm = mContext.getPackageManager(); + List activities = pm.queryIntentActivities(intent, 0); + ActivityInfo best = null; + if (activities.size() > 0) { + best = activities.get(0).activityInfo; + if (match != null) { + String packageName = match.applicationInfo.packageName; + for (int i = activities.size()-1; i >= 0; i--) { + ActivityInfo activityInfo = activities.get(i).activityInfo; + if (packageName.equals(activityInfo.applicationInfo.packageName)) { + best = activityInfo; + } + } + } + } + return best; + } + + private void openBrowser() { + mGestureWakeLock.acquire(GESTURE_WAKELOCK_DURATION); + mPowerManager.wakeUp(SystemClock.uptimeMillis(), GESTURE_WAKEUP_REASON); + final Intent intent = getLaunchableIntent( + new Intent(Intent.ACTION_VIEW, Uri.parse("http:"))); + startActivitySafely(intent); + } + + private void openDialer() { + mGestureWakeLock.acquire(GESTURE_WAKELOCK_DURATION); + mPowerManager.wakeUp(SystemClock.uptimeMillis(), GESTURE_WAKEUP_REASON); + final Intent intent = new Intent(Intent.ACTION_DIAL, null); + startActivitySafely(intent); + } + + private void openEmail() { + mGestureWakeLock.acquire(GESTURE_WAKELOCK_DURATION); + mPowerManager.wakeUp(SystemClock.uptimeMillis(), GESTURE_WAKEUP_REASON); + final Intent intent = getLaunchableIntent( + new Intent(Intent.ACTION_VIEW, Uri.parse("mailto:"))); + startActivitySafely(intent); + } + + private void openMessages() { + mGestureWakeLock.acquire(GESTURE_WAKELOCK_DURATION); + mPowerManager.wakeUp(SystemClock.uptimeMillis(), GESTURE_WAKEUP_REASON); + final String defaultApplication = Settings.Secure.getString( + mContext.getContentResolver(), "sms_default_application"); + final PackageManager pm = mContext.getPackageManager(); + final Intent intent = pm.getLaunchIntentForPackage(defaultApplication); + if (intent != null) { + startActivitySafely(intent); + } + } + + private void toggleFlashlight(){ + String rearCameraId = getRearCameraId(); + if (rearCameraId != null) { + mGestureWakeLock.acquire(GESTURE_WAKELOCK_DURATION); + try { + mCameraManager.setTorchMode(rearCameraId, !mTorchEnabled); + mTorchEnabled = !mTorchEnabled; + } catch (CameraAccessException e) { + // Ignore + } + } + } + + private void ensureKeyguardManager() { + if (mKeyguardManager == null) { + mKeyguardManager = + (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); + } + } + + private void resetDoubleTapOnFP() { + fpTapCounts = 0; + fpTapPending = false; + mHandler.removeCallbacks(doubleTapRunnable); + } + + private Runnable doubleTapRunnable = new Runnable() { + public void run() { + int action = 0; + if (fpTapCounts > 1){ + action = str2int(FileUtils.readOneLine(getFPNodeBasedOnScreenState(FP_KEY_DBLTAP_NODE))); + }else{ + if (isSingleTapEnabledOnFP()){ + action = str2int(FileUtils.readOneLine(getFPNodeBasedOnScreenState(FP_KEYS_NODE))); + } + } + + if (action != 0){ + boolean isActionSupported = ArrayUtils.contains(mPowerManager.isScreenOn() ? sFPSupportedActions : sFPSupportedActionsScreenOff, action); + if (isActionSupported){ + fireFPAction(action, false); + } + } + resetDoubleTapOnFP(); + } + }; + + private void detectDoubleTapOnFP() { + fpTapCounts++; + if (fpTapCounts == 1 || fpTapCounts == 2){ + doHapticFeedbackFP(false); + } + if (!fpTapPending){ + fpTapPending = true; + mHandler.postDelayed(doubleTapRunnable, ViewConfiguration.getDoubleTapTimeout()); + } + } + + private boolean isSingleTapEnabledOnFP() { + return !FileUtils.readOneLine(getFPNodeBasedOnScreenState(FP_KEYS_NODE)).equals("0"); + } + + private boolean isDoubleTapEnabledOnFP() { + return !FileUtils.readOneLine(getFPNodeBasedOnScreenState(FP_KEY_DBLTAP_NODE)).equals("0"); + } + + private boolean isHapticFeedbackEnabledOnFP() { + return !FileUtils.readOneLine(getFPNodeBasedOnScreenState(FP_HAPTIC_NODE)).equals("0"); + } + + private String getFPNodeBasedOnScreenState(String node){ + if (mPowerManager.isScreenOn()){ + return node; + } + switch (node) { + case FP_KEYS_NODE: + return FP_KEYS_SCREENOFF_NODE; + case FP_HAPTIC_NODE: + return FP_HAPTIC_SCREENOFF_NODE; + case FP_KEY_DBLTAP_NODE: + return FP_KEY_SCREENOFF_DBLTAP_NODE; + case FP_KEY_HOLD_NODE: + return FP_KEY_SCREENOFF_HOLD_NODE; + case FP_KEY_RIGHT_NODE: + return FP_KEY_SCREENOFF_RIGHT_NODE; + case FP_KEY_LEFT_NODE: + return FP_KEY_SCREENOFF_LEFT_NODE; + } + return node; + } + + public boolean handleKeyEvent(KeyEvent event) { + int scanCode = event.getScanCode(); + + if (DEBUG){ + Log.d(TAG, "DEBUG: action=" + event.getAction() + + ", flags=" + event.getFlags() + + ", keyCode=" + event.getKeyCode() + + ", scanCode=" + event.getScanCode() + + ", metaState=" + event.getMetaState() + + ", repeatCount=" + event.getRepeatCount()); + } + + boolean isFPScanCode = ArrayUtils.contains(sSupportedFPGestures, scanCode); + boolean isScreenOffGesturesScanCode = ArrayUtils.contains(sSupportedScreenOffGestures, scanCode); + if (!isFPScanCode && !isScreenOffGesturesScanCode) { + return false; + } + + boolean isFPGestureEnabled = FileUtils.readOneLine(FP_HOME_NODE).equals("1"); + boolean isFPGestureEnabledOnScreenOff = FileUtils.readOneLine(FP_HOME_OFF_NODE).equals("1"); + + boolean isScreenOn = mPowerManager.isScreenOn(); + + // We only want ACTION_UP event + if (event.getAction() != KeyEvent.ACTION_UP) { + return true; + } + + if (scanCode != FP_TAP_SCANCODE){ + resetDoubleTapOnFP(); + } + + if (isFPScanCode) { + if((!isFPGestureEnabled) || (!isScreenOn && !isFPGestureEnabledOnScreenOff)){ + resetDoubleTapOnFP(); + return false; + } + if (!isScreenOn && isFPGestureEnabledOnScreenOff){ + processFPScreenOffScancode(scanCode); + }else{ + processFPScancode(scanCode); + } + }else if (isScreenOffGesturesScanCode) { + processScreenOffScancode(scanCode); + } + return true; + } + + private void processFPScancode(int scanCode){ + int action = 0; + boolean isScreenOn = mPowerManager.isScreenOn(); + switch (scanCode) { + case FP_TAP_SCANCODE: + if (isDoubleTapEnabledOnFP()) { + detectDoubleTapOnFP(); + return; + }else{ + resetDoubleTapOnFP(); + action = str2int(FileUtils.readOneLine(getFPNodeBasedOnScreenState(FP_KEYS_NODE))); + } + break; + case FP_HOLD_SCANCODE: + action = str2int(FileUtils.readOneLine(getFPNodeBasedOnScreenState(FP_KEY_HOLD_NODE))); + break; + case FP_RIGHT_SCANCODE: + action = str2int(FileUtils.readOneLine(getFPNodeBasedOnScreenState(FP_KEY_RIGHT_NODE))); + break; + case FP_LEFT_SCANCODE: + action = str2int(FileUtils.readOneLine(getFPNodeBasedOnScreenState(FP_KEY_LEFT_NODE))); + break; + } + boolean isActionSupported = ArrayUtils.contains(isScreenOn ? sFPSupportedActions : sFPSupportedActionsScreenOff, action); + if (isActionSupported){ + fireFPAction(action, true); + } + } + + private void fireFPAction(int action, boolean haptic){ + ensureKeyguardManager(); + boolean isHapticFeedbackEnabledOnFP = isHapticFeedbackEnabledOnFP(); + if (!haptic){ + isHapticFeedbackEnabledOnFP = false; + } + if (isHapticFeedbackEnabledOnFP && (action == ACTION_CAMERA || action == ACTION_FLASHLIGHT)){ + vibrate(action == ACTION_CAMERA ? 500 : 250); + } + switch (action) { + case ACTION_HOME: + if (!mKeyguardManager.inKeyguardRestrictedInputMode()){ + triggerVirtualKeypress(mHandler, KeyEvent.KEYCODE_HOME); + } + break; + case ACTION_POWER: + toggleScreenState(); + break; + case ACTION_BACK: + triggerVirtualKeypress(mHandler, KeyEvent.KEYCODE_BACK); + break; + case ACTION_RECENTS: + if (!mKeyguardManager.inKeyguardRestrictedInputMode()){ + triggerVirtualKeypress(mHandler, KeyEvent.KEYCODE_APP_SWITCH); + } + break; + case ACTION_VOLUME_UP: + triggerVirtualKeypress(mHandler, KeyEvent.KEYCODE_VOLUME_UP); + break; + case ACTION_VOLUME_DOWN: + triggerVirtualKeypress(mHandler, KeyEvent.KEYCODE_VOLUME_DOWN); + break; + case ACTION_VOICE_ASSISTANT: + if (!mKeyguardManager.inKeyguardRestrictedInputMode()){ + fireGoogleNowOnTap(); + } + return; + case ACTION_PLAY_PAUSE: + dispatchMediaKeyWithWakeLock(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, mContext); + break; + case ACTION_PREVIOUS_TRACK: + dispatchMediaKeyWithWakeLock(KeyEvent.KEYCODE_MEDIA_PREVIOUS, mContext); + break; + case ACTION_NEXT_TRACK: + dispatchMediaKeyWithWakeLock(KeyEvent.KEYCODE_MEDIA_NEXT, mContext); + break; + case ACTION_FLASHLIGHT: + toggleFlashlight(); + break; + case ACTION_CAMERA: + triggerCameraAction(); + break; + case ACTION_SCREENSHOT: + triggerVirtualKeypress(mHandler, KeyEvent.KEYCODE_SYSRQ); + break; + case ACTION_PIP: + if (!mKeyguardManager.inKeyguardRestrictedInputMode()){ + goToPipMode(); + } + break; + } + if (isHapticFeedbackEnabledOnFP && action != ACTION_VOICE_ASSISTANT && action != ACTION_CAMERA && action != ACTION_FLASHLIGHT){ // prevent double vibration + doHapticFeedbackFP(false); + } + } + + private void vibrate(int intensity){ + if (mVibrator == null) { + return; + } + mVibrator.vibrate(intensity); + } + + private void goToPipMode(){ + ActivityInfo ai = getRunningActivityInfo(mContext); + if (ai != null && !ai.supportsPictureInPicture()) { + try { + PackageManager pm = mContext.getPackageManager(); + Resources resources = pm.getResourcesForApplication("org.lineageos.settings.device"); + int resId = resources.getIdentifier("app_does_not_support_pip", "string", "org.lineageos.settings.device"); + final String text = resources.getString(resId); + mHandler.post(new Runnable() { + public void run() { + Toast.makeText(mContext, text, Toast.LENGTH_SHORT).show(); + } + }); + } catch (Exception e) { + } + return; + } + triggerVirtualKeypress(mHandler, 171); + } + + private static ActivityInfo getRunningActivityInfo(Context context) { + final ActivityManager am = (ActivityManager) context + .getSystemService(Context.ACTIVITY_SERVICE); + final PackageManager pm = context.getPackageManager(); + + List tasks = am.getRunningTasks(1); + if (tasks != null && !tasks.isEmpty()) { + ActivityManager.RunningTaskInfo top = tasks.get(0); + try { + return pm.getActivityInfo(top.topActivity, 0); + } catch (PackageManager.NameNotFoundException e) { + } + } + return null; + } + + private void toggleScreenState(){ + if(mPowerManager.isScreenOn()){ + mPowerManager.goToSleep(SystemClock.uptimeMillis()); + }else{ + mPowerManager.wakeUp(SystemClock.uptimeMillis()); + } + } + + private static void dispatchMediaKeyWithWakeLock(int keycode, Context context) { + if (ActivityManagerNative.isSystemReady()) { + KeyEvent event = new KeyEvent(SystemClock.uptimeMillis(), + SystemClock.uptimeMillis(), KeyEvent.ACTION_DOWN, keycode, 0); + MediaSessionLegacyHelper.getHelper(context).sendMediaButtonEvent(event, true); + event = KeyEvent.changeAction(event, KeyEvent.ACTION_UP); + MediaSessionLegacyHelper.getHelper(context).sendMediaButtonEvent(event, true); + } + } + + private void triggerVirtualKeypress(final Handler handler, final int keyCode) { + final boolean mIsHapticFeedbackEnabledOnSystem_ = mIsHapticFeedbackEnabledOnSystem; + if (mIsHapticFeedbackEnabledOnSystem_){ + setHapticFeedbackEnabledOnSystem(false); + } + final InputManager im = InputManager.getInstance(); + long now = SystemClock.uptimeMillis(); + + final KeyEvent downEvent = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, + keyCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, + KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY, InputDevice.SOURCE_CLASS_BUTTON); + final KeyEvent upEvent = KeyEvent.changeAction(downEvent, + KeyEvent.ACTION_UP); + + // add a small delay to make sure everything behind got focus + handler.post(new Runnable(){ + @Override + public void run() { + im.injectInputEvent(downEvent,InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); + }}); + + handler.postDelayed(new Runnable(){ + @Override + public void run() { + im.injectInputEvent(upEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); + if (mIsHapticFeedbackEnabledOnSystem_){ + setHapticFeedbackEnabledOnSystem(true); + } + }}, 10); + } + + private static void sendCloseSystemWindows(String reason) { + if (ActivityManagerNative.isSystemReady()) { + try { + ActivityManagerNative.getDefault().closeSystemDialogs(reason); + } catch (RemoteException e) { + } + } + } + + private void fireGoogleNowOnTap() { + doHapticFeedbackFP(false); + mSearchManagerService = ISearchManager.Stub.asInterface(ServiceManager.getService(Context.SEARCH_SERVICE)); + if (mSearchManagerService != null) { + try { + mSearchManagerService.launchAssist(new Bundle()); + } catch (RemoteException e) { + } + } + doHapticFeedbackFP(true); + } + + private int str2int(String str){ + if (str == null || str.isEmpty()){ + return 0; + } + try { + return Integer.valueOf(str); + } catch (Exception e) { + return 0; + } + } + + private void processFPScreenOffScancode(int scanCode){ + if (!mFPScreenOffGesturesHandler.hasMessages(FP_ACTION_REQUEST)) { + Message msg = mFPScreenOffGesturesHandler.obtainMessage(FP_ACTION_REQUEST); + msg.arg1 = scanCode; + boolean defaultProximity = mContext.getResources().getBoolean( + org.lineageos.platform.internal.R.bool.config_proximityCheckOnWakeEnabledByDefault); + boolean proximityWakeCheckEnabled = LineageSettings.System.getInt(mContext.getContentResolver(), + LineageSettings.System.PROXIMITY_ON_WAKE, defaultProximity ? 1 : 0) == 1; + if (mProximityWakeSupported && proximityWakeCheckEnabled && mProximitySensor != null) { + mFPScreenOffGesturesHandler.sendMessageDelayed(msg, mProximityTimeOut); + registerFPScreenOffListener(scanCode); + }else{ + mFPScreenOffGesturesHandler.sendMessage(msg); + } + } + } + + private void registerFPScreenOffListener(final int scanCode) { + mProximityWakeLock.acquire(); + mSensorManager.registerListener(new SensorEventListener() { + @Override + public void onSensorChanged(SensorEvent event) { + mProximityWakeLock.release(); + mSensorManager.unregisterListener(this); + if (!mFPScreenOffGesturesHandler.hasMessages(FP_ACTION_REQUEST)) { + // The sensor took to long, ignoring. + return; + } + mFPScreenOffGesturesHandler.removeMessages(FP_ACTION_REQUEST); + if (event.values[0] == mProximitySensor.getMaximumRange()) { + Message msg = mFPScreenOffGesturesHandler.obtainMessage(FP_ACTION_REQUEST); + msg.arg1 = scanCode; + mFPScreenOffGesturesHandler.sendMessage(msg); + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + } + + }, mProximitySensor, SensorManager.SENSOR_DELAY_FASTEST); + } + + + private void resetScreenOffGestureDelay() { + screenOffGesturePending = false; + mHandler.removeCallbacks(screenOffGestureRunnable); + } + + private Runnable screenOffGestureRunnable = new Runnable() { + public void run() { + resetScreenOffGestureDelay(); + } + }; + + private void processScreenOffScancode(int scanCode){ + if (screenOffGesturePending){ + return; + }else{ + resetScreenOffGestureDelay(); + screenOffGesturePending = true; + mHandler.postDelayed(screenOffGestureRunnable, 500); + } + if (!mScreenOffGesturesHandler.hasMessages(GESTURE_REQUEST)) { + Message msg = mScreenOffGesturesHandler.obtainMessage(GESTURE_REQUEST); + msg.arg1 = scanCode; + boolean defaultProximity = mContext.getResources().getBoolean( + org.lineageos.platform.internal.R.bool.config_proximityCheckOnWakeEnabledByDefault); + boolean proximityWakeCheckEnabled = LineageSettings.System.getInt(mContext.getContentResolver(), + LineageSettings.System.PROXIMITY_ON_WAKE, defaultProximity ? 1 : 0) == 1; + if (mProximityWakeSupported && proximityWakeCheckEnabled && mProximitySensor != null) { + mScreenOffGesturesHandler.sendMessageDelayed(msg, mProximityTimeOut); + registerScreenOffGesturesListener(scanCode); + } else { + mScreenOffGesturesHandler.sendMessage(msg); + } + } + } + + private void registerScreenOffGesturesListener(final int scanCode) { + mProximityWakeLock.acquire(); + mSensorManager.registerListener(new SensorEventListener() { + @Override + public void onSensorChanged(SensorEvent event) { + mProximityWakeLock.release(); + mSensorManager.unregisterListener(this); + if (!mScreenOffGesturesHandler.hasMessages(GESTURE_REQUEST)) { + // The sensor took to long, ignoring. + return; + } + mScreenOffGesturesHandler.removeMessages(GESTURE_REQUEST); + if (event.values[0] == mProximitySensor.getMaximumRange()) { + Message msg = mScreenOffGesturesHandler.obtainMessage(GESTURE_REQUEST); + msg.arg1 = scanCode; + mScreenOffGesturesHandler.sendMessage(msg); + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + } + + }, mProximitySensor, SensorManager.SENSOR_DELAY_FASTEST); + } + + private class ScreenOffGesturesHandler extends Handler { + @Override + public void handleMessage(Message msg) { + int scanCode = msg.arg1; + int action = 0; + switch (scanCode) { + case GESTURE_SWIPE_RIGHT_SCANCODE: + action = str2int(FileUtils.readOneLine(GESTURE_SWIPE_RIGHT_NODE)); + break; + case GESTURE_SWIPE_LEFT_SCANCODE: + action = str2int(FileUtils.readOneLine(GESTURE_SWIPE_LEFT_NODE)); + break; + case GESTURE_SWIPE_DOWN_SCANCODE: + action = str2int(FileUtils.readOneLine(GESTURE_SWIPE_DOWN_NODE)); + break; + case GESTURE_SWIPE_UP_SCANCODE: + action = str2int(FileUtils.readOneLine(GESTURE_SWIPE_UP_NODE)); + break; + case GESTURE_DOUBLE_TAP_SCANCODE: + action = str2int(FileUtils.readOneLine(GESTURE_DOUBLE_TAP_NODE)); + if (action != 0){ + action = ACTION_POWER; + } + break; + } + boolean isActionSupported = ArrayUtils.contains(sScreenOffSupportedActions, action); + if(isActionSupported){ + fireScreenOffAction(action); + } + } + } + + private void fireScreenOffAction(int action){ + boolean haptic = Settings.System.getInt(mContext.getContentResolver(), KEY_GESTURE_ENABLE_HAPTIC_FEEDBACK, 1) != 0; + if (haptic && (action == ACTION_CAMERA || action == ACTION_FLASHLIGHT)){ + vibrate(action == ACTION_CAMERA ? 500 : 250); + } + switch (action) { + case ACTION_POWER: + toggleScreenState(); + break; + case ACTION_PLAY_PAUSE: + dispatchMediaKeyWithWakeLock(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, mContext); + break; + case ACTION_PREVIOUS_TRACK: + dispatchMediaKeyWithWakeLock(KeyEvent.KEYCODE_MEDIA_PREVIOUS, mContext); + break; + case ACTION_NEXT_TRACK: + dispatchMediaKeyWithWakeLock(KeyEvent.KEYCODE_MEDIA_NEXT, mContext); + break; + case ACTION_FLASHLIGHT: + toggleFlashlight(); + break; + case ACTION_CAMERA: + triggerCameraAction(); + break; + case ACTION_BROWSER: + openBrowser(); + break; + case ACTION_DIALER: + openDialer(); + break; + case ACTION_EMAIL: + openEmail(); + break; + case ACTION_MESSAGES: + openMessages(); + break; + } + if (action != ACTION_FLASHLIGHT && action != ACTION_CAMERA){ + doHapticFeedbackScreenOff(); + } + } + + private class FPScreenOffGesturesHandler extends Handler { + @Override + public void handleMessage(Message msg) { + processFPScancode(msg.arg1); + } + } + + 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 + } + } + + private void doHapticFeedbackScreenOff() { + if (mVibrator == null) { + return; + } + boolean enabled = Settings.System.getInt(mContext.getContentResolver(), KEY_GESTURE_ENABLE_HAPTIC_FEEDBACK, 1) != 0; + if (enabled) { + mVibrator.vibrate(50); + } + } + + private void doHapticFeedbackFP(boolean longpress) { + if (mVibrator == null) { + return; + } + + if (isHapticFeedbackEnabledOnFP()) { + long[] pattern = null; + int owningUid; + String owningPackage; + owningUid = android.os.Process.myUid(); + owningPackage = mContext.getOpPackageName(); + VibrationEffect effect; + if (longpress){ + pattern = getLongIntArray(mContext.getResources(),com.android.internal.R.array.config_longPressVibePattern); + }else{ + pattern = getLongIntArray(mContext.getResources(),com.android.internal.R.array.config_virtualKeyVibePattern); + } + if (pattern.length == 0) { + // No vibration + return; + } else if (pattern.length == 1) { + // One-shot vibration + effect = VibrationEffect.createOneShot(pattern[0], VibrationEffect.DEFAULT_AMPLITUDE); + } else { + // Pattern vibration + effect = VibrationEffect.createWaveform(pattern, -1); + } + mVibrator.vibrate(owningUid, owningPackage, effect, VIBRATION_ATTRIBUTES); + } + } + + private class MyTorchCallback extends CameraManager.TorchCallback { + @Override + public void onTorchModeChanged(String cameraId, boolean enabled) { + if (!cameraId.equals(mRearCameraId)) + return; + mTorchEnabled = enabled; + } + + @Override + public void onTorchModeUnavailable(String cameraId) { + if (!cameraId.equals(mRearCameraId)) + return; + mTorchEnabled = false; + } + } +} diff --git a/LineageActions/src/org/lineageos/settings/device/LineageActionsSettings.java b/LineageActions/src/org/lineageos/settings/device/LineageActionsSettings.java index 8cb1804..c552d10 100644 --- a/LineageActions/src/org/lineageos/settings/device/LineageActionsSettings.java +++ b/LineageActions/src/org/lineageos/settings/device/LineageActionsSettings.java @@ -134,7 +134,9 @@ public class LineageActionsSettings { mFlipToMuteEnabled = sharedPreferences.getBoolean(GESTURE_FLIP_TO_MUTE_KEY, false); } else if (GESTURE_LIFT_TO_SILENCE_KEY.equals(key)) { mLiftToSilenceEnabled = sharedPreferences.getBoolean(GESTURE_LIFT_TO_SILENCE_KEY, false); - } else if (Constants.FP_HOME_KEY.equals(key) || Constants.FP_HAPTIC_KEY.equals(key) || Constants.FP_KEYS.equals(key) || Constants.FP_KEY_HOLD.equals(key) || Constants.FP_KEY_LEFT.equals(key) || Constants.FP_KEY_RIGHT.equals(key)) { + } else if (Constants.FP_HOME_KEY.equals(key) || Constants.FP_HAPTIC_KEY.equals(key) || Constants.FP_HOME_KEY_OFF.equals(key) || Constants.FP_HAPTIC_SCREENOFF_KEY.equals(key) || Constants.FP_KEYS.equals(key) || Constants.FP_KEY_DBLTAP.equals(key) || Constants.FP_KEY_HOLD.equals(key) || Constants.FP_KEY_LEFT.equals(key) || Constants.FP_KEY_RIGHT.equals(key) + || Constants.FP_KEYS_OFF.equals(key) || Constants.FP_KEY_DBLTAP_OFF.equals(key) || Constants.FP_KEY_HOLD_OFF.equals(key) || Constants.FP_KEY_LEFT_OFF.equals(key) || Constants.FP_KEY_RIGHT_OFF.equals(key) + || Constants.GESTURE_SWIPE_RIGHT.equals(key) || Constants.GESTURE_SWIPE_LEFT.equals(key) || Constants.GESTURE_SWIPE_DOWN.equals(key) || Constants.GESTURE_SWIPE_UP.equals(key)) { Constants.writePreference(mContext, key); updated = false; } else { diff --git a/LineageActions/src/org/lineageos/settings/device/ScreenOffGestureSettings.java b/LineageActions/src/org/lineageos/settings/device/ScreenOffGestureSettings.java new file mode 100644 index 0000000..107c914 --- /dev/null +++ b/LineageActions/src/org/lineageos/settings/device/ScreenOffGestureSettings.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016 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 org.lineageos.settings.device; + +import android.os.Bundle; +import android.provider.Settings; +import android.preference.Preference; +import android.preference.SwitchPreference; +import android.preference.PreferenceActivity; +import android.view.MenuItem; + +import static android.provider.Settings.Secure.DOUBLE_TAP_TO_WAKE; +import static org.lineageos.settings.device.actions.Constants.KEY_GESTURE_ENABLE_HAPTIC_FEEDBACK; + +public class ScreenOffGestureSettings extends PreferenceActivity { + + private SwitchPreference mTapToWake; + private SwitchPreference mHapticFeedback; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.screen_off_gesture_panel); + getActionBar().setDisplayHomeAsUpEnabled(true); + mTapToWake = (SwitchPreference) findPreference("tap_to_wake"); + mTapToWake.setChecked(Settings.Secure.getInt(getContentResolver(), DOUBLE_TAP_TO_WAKE, 0) == 1); + mTapToWake.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object objValue) { + boolean value = (Boolean) objValue; + Settings.Secure.putInt(getContentResolver(), DOUBLE_TAP_TO_WAKE, value ? 1 : 0); + return true; + } + }); + + mHapticFeedback = (SwitchPreference) findPreference("haptic_feedback"); + mHapticFeedback.setChecked(Settings.System.getInt(getContentResolver(), KEY_GESTURE_ENABLE_HAPTIC_FEEDBACK, 1) == 1); + mHapticFeedback.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object objValue) { + boolean value = (Boolean) objValue; + Settings.System.putInt(getContentResolver(), KEY_GESTURE_ENABLE_HAPTIC_FEEDBACK, value ? 1 : 0); + return true; + } + }); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + onBackPressed(); + return true; + } + return super.onOptionsItemSelected(item); + } + +} diff --git a/LineageActions/src/org/lineageos/settings/device/actions/Constants.java b/LineageActions/src/org/lineageos/settings/device/actions/Constants.java index 9f7d287..d94fca9 100644 --- a/LineageActions/src/org/lineageos/settings/device/actions/Constants.java +++ b/LineageActions/src/org/lineageos/settings/device/actions/Constants.java @@ -29,8 +29,68 @@ import org.lineageos.internal.util.FileUtils; public class Constants { + public static final boolean DEBUG = false; + private static final String TAG = "LineageActions"; + // FP gestures + public static final int FP_TAP_SCANCODE = 616; + public static final int FP_HOLD_SCANCODE = 617; + public static final int FP_RIGHT_SCANCODE = 620; + public static final int FP_LEFT_SCANCODE = 621; + public static final int[] sSupportedFPGestures = new int[]{ + FP_TAP_SCANCODE, + FP_HOLD_SCANCODE, + FP_RIGHT_SCANCODE, + FP_LEFT_SCANCODE + }; + + // FP actions + public static final int ACTION_HOME = 100; + public static final int ACTION_POWER = 101; + public static final int ACTION_BACK = 102; + public static final int ACTION_RECENTS = 103; + public static final int ACTION_VOLUME_UP = 104; + public static final int ACTION_VOLUME_DOWN = 105; + public static final int ACTION_VOICE_ASSISTANT = 106; + public static final int ACTION_PLAY_PAUSE = 107; + public static final int ACTION_PREVIOUS_TRACK = 108; + public static final int ACTION_NEXT_TRACK = 109; + public static final int ACTION_FLASHLIGHT = 110; + public static final int ACTION_CAMERA = 111; + public static final int ACTION_SCREENSHOT = 112; + public static final int ACTION_BROWSER = 116; + public static final int ACTION_DIALER = 117; + public static final int ACTION_EMAIL = 118; + public static final int ACTION_MESSAGES = 119; + public static final int ACTION_PIP = 120; + public static final int[] sFPSupportedActions = new int[]{ + ACTION_HOME, + ACTION_POWER, + ACTION_BACK, + ACTION_RECENTS, + ACTION_VOLUME_UP, + ACTION_VOLUME_DOWN, + ACTION_VOICE_ASSISTANT, + ACTION_PLAY_PAUSE, + ACTION_PREVIOUS_TRACK, + ACTION_NEXT_TRACK, + ACTION_FLASHLIGHT, + ACTION_CAMERA, + ACTION_SCREENSHOT, + ACTION_PIP + }; + public static final int[] sFPSupportedActionsScreenOff = new int[]{ + ACTION_POWER, + ACTION_VOLUME_UP, + ACTION_VOLUME_DOWN, + ACTION_PLAY_PAUSE, + ACTION_PREVIOUS_TRACK, + ACTION_NEXT_TRACK, + ACTION_FLASHLIGHT, + ACTION_CAMERA + }; + // Swap keys public static final String FP_HOME_KEY = "fp_home"; public static final String FP_HOME_KEY_OFF = "fp_home_scr_off"; @@ -42,71 +102,142 @@ public class Constants { // Haptic node public static final String FP_HAPTIC_NODE = "/sys/homebutton/haptic"; public static final String FP_HAPTIC_KEY = "fp_haptic"; + public static final String FP_HAPTIC_SCREENOFF_NODE = "/sys/homebutton/haptic_off"; + public static final String FP_HAPTIC_SCREENOFF_KEY = "fp_haptic_scr_off"; // List of keys public static final String FP_KEYS = "fp_keys"; + public static final String FP_KEY_DBLTAP = "fp_key_dbltap"; public static final String FP_KEY_HOLD = "fp_key_hold"; public static final String FP_KEY_LEFT = "fp_key_left"; public static final String FP_KEY_RIGHT = "fp_key_right"; public static final String FP_KEYS_OFF = "fp_keys_off"; + public static final String FP_KEY_DBLTAP_OFF = "fp_key_dbltap_off"; public static final String FP_KEY_HOLD_OFF = "fp_key_hold_off"; public static final String FP_KEY_LEFT_OFF = "fp_key_left_off"; public static final String FP_KEY_RIGHT_OFF = "fp_key_right_off"; // Keys nodes public static final String FP_KEYS_NODE = "/sys/homebutton/key"; + public static final String FP_KEY_DBLTAP_NODE = "/sys/homebutton/key_dbltap"; public static final String FP_KEY_HOLD_NODE = "/sys/homebutton/key_hold"; public static final String FP_KEY_LEFT_NODE = "/sys/homebutton/key_left"; public static final String FP_KEY_RIGHT_NODE = "/sys/homebutton/key_right"; + public static final String FP_KEYS_SCREENOFF_NODE = "/sys/homebutton/key_screenoff"; + public static final String FP_KEY_SCREENOFF_DBLTAP_NODE = "/sys/homebutton/key_screenoff_dbltap"; + public static final String FP_KEY_SCREENOFF_HOLD_NODE = "/sys/homebutton/key_screenoff_hold"; + public static final String FP_KEY_SCREENOFF_LEFT_NODE = "/sys/homebutton/key_screenoff_left"; + public static final String FP_KEY_SCREENOFF_RIGHT_NODE = "/sys/homebutton/key_screenoff_right"; + + // Screen off gestures + public static final int GESTURE_SWIPE_RIGHT_SCANCODE = 622; + public static final int GESTURE_SWIPE_LEFT_SCANCODE = 623; + public static final int GESTURE_SWIPE_DOWN_SCANCODE = 624; + public static final int GESTURE_SWIPE_UP_SCANCODE = 625; + public static final int GESTURE_DOUBLE_TAP_SCANCODE = 626; + public static final int[] sSupportedScreenOffGestures = new int[]{ + GESTURE_SWIPE_RIGHT_SCANCODE, + GESTURE_SWIPE_LEFT_SCANCODE, + GESTURE_SWIPE_DOWN_SCANCODE, + GESTURE_SWIPE_UP_SCANCODE, + GESTURE_DOUBLE_TAP_SCANCODE + }; + public static final int[] sScreenOffSupportedActions = new int[]{ + ACTION_POWER, + ACTION_PLAY_PAUSE, + ACTION_PREVIOUS_TRACK, + ACTION_NEXT_TRACK, + ACTION_FLASHLIGHT, + ACTION_CAMERA, + ACTION_BROWSER, + ACTION_DIALER, + ACTION_EMAIL, + ACTION_MESSAGES + }; + + // List of screen off gestures keys + public static final String GESTURE_SWIPE_RIGHT = "screen_off_gestures_swipe_right"; + public static final String GESTURE_SWIPE_LEFT = "screen_off_gestures_swipe_left"; + public static final String GESTURE_SWIPE_DOWN = "screen_off_gestures_swipe_down"; + public static final String GESTURE_SWIPE_UP = "screen_off_gestures_swipe_up"; + + // Screen off gestures nodes + public static final String GESTURE_SWIPE_RIGHT_NODE = "/sys/android_touch/gesture_swipe_right"; + public static final String GESTURE_SWIPE_LEFT_NODE = "/sys/android_touch/gesture_swipe_left"; + public static final String GESTURE_SWIPE_DOWN_NODE = "/sys/android_touch/gesture_swipe_down"; + public static final String GESTURE_SWIPE_UP_NODE = "/sys/android_touch/gesture_swipe_up"; + public static final String GESTURE_DOUBLE_TAP_NODE = "/sys/android_touch/doubletap2wake"; + + // Screen off gestures haptic + public static final String KEY_GESTURE_ENABLE_HAPTIC_FEEDBACK = "screen_off_gesture_haptic_feedback"; + // Holds -> mapping public static final Map sBooleanNodePreferenceMap = new HashMap<>(); // Holds -> mapping public static final Map sNodeDefaultMap = new HashMap<>(); - public static final String[] sButtonPrefKeys = { + public static final String[] sPrefKeys = { FP_HOME_KEY, FP_HOME_KEY_OFF, + FP_HAPTIC_KEY, + FP_HAPTIC_SCREENOFF_KEY, FP_KEYS, + FP_KEY_DBLTAP, FP_KEY_HOLD, FP_KEY_RIGHT, FP_KEY_LEFT, - FP_HAPTIC_KEY, - }; - - public static final String[] sButtonScreenOffPrefKeys = { FP_KEYS_OFF, + FP_KEY_DBLTAP_OFF, FP_KEY_HOLD_OFF, FP_KEY_RIGHT_OFF, FP_KEY_LEFT_OFF, FP_HOME_KEY_OFF, + GESTURE_SWIPE_RIGHT, + GESTURE_SWIPE_LEFT, + GESTURE_SWIPE_DOWN, + GESTURE_SWIPE_UP }; static { sBooleanNodePreferenceMap.put(FP_HOME_KEY, FP_HOME_NODE); sBooleanNodePreferenceMap.put(FP_HOME_KEY_OFF, FP_HOME_OFF_NODE); + sBooleanNodePreferenceMap.put(FP_HAPTIC_KEY, FP_HAPTIC_NODE); + sBooleanNodePreferenceMap.put(FP_HAPTIC_SCREENOFF_KEY, FP_HAPTIC_SCREENOFF_NODE); sBooleanNodePreferenceMap.put(FP_KEYS, FP_KEYS_NODE); + sBooleanNodePreferenceMap.put(FP_KEY_DBLTAP, FP_KEY_DBLTAP_NODE); sBooleanNodePreferenceMap.put(FP_KEY_HOLD, FP_KEY_HOLD_NODE); sBooleanNodePreferenceMap.put(FP_KEY_LEFT, FP_KEY_LEFT_NODE); sBooleanNodePreferenceMap.put(FP_KEY_RIGHT, FP_KEY_RIGHT_NODE); - sBooleanNodePreferenceMap.put(FP_HAPTIC_KEY, FP_HAPTIC_NODE); - sBooleanNodePreferenceMap.put(FP_KEYS_OFF, FP_KEYS_NODE); - sBooleanNodePreferenceMap.put(FP_KEY_HOLD_OFF, FP_KEY_HOLD_NODE); - sBooleanNodePreferenceMap.put(FP_KEY_LEFT_OFF, FP_KEY_LEFT_NODE); - sBooleanNodePreferenceMap.put(FP_KEY_RIGHT_OFF, FP_KEY_RIGHT_NODE); + sBooleanNodePreferenceMap.put(FP_KEYS_OFF, FP_KEYS_SCREENOFF_NODE); + sBooleanNodePreferenceMap.put(FP_KEY_DBLTAP_OFF, FP_KEY_SCREENOFF_DBLTAP_NODE); + sBooleanNodePreferenceMap.put(FP_KEY_HOLD_OFF, FP_KEY_SCREENOFF_HOLD_NODE); + sBooleanNodePreferenceMap.put(FP_KEY_LEFT_OFF, FP_KEY_SCREENOFF_LEFT_NODE); + sBooleanNodePreferenceMap.put(FP_KEY_RIGHT_OFF, FP_KEY_SCREENOFF_RIGHT_NODE); + sBooleanNodePreferenceMap.put(GESTURE_SWIPE_RIGHT, GESTURE_SWIPE_RIGHT_NODE); + sBooleanNodePreferenceMap.put(GESTURE_SWIPE_LEFT, GESTURE_SWIPE_LEFT_NODE); + sBooleanNodePreferenceMap.put(GESTURE_SWIPE_DOWN, GESTURE_SWIPE_DOWN_NODE); + sBooleanNodePreferenceMap.put(GESTURE_SWIPE_UP, GESTURE_SWIPE_UP_NODE); sNodeDefaultMap.put(FP_HOME_KEY, false); sNodeDefaultMap.put(FP_HOME_KEY_OFF, false); + sNodeDefaultMap.put(FP_HAPTIC_KEY, false); + sNodeDefaultMap.put(FP_HAPTIC_SCREENOFF_KEY, false); sNodeDefaultMap.put(FP_KEYS, "0"); + sNodeDefaultMap.put(FP_KEY_DBLTAP, "0"); sNodeDefaultMap.put(FP_KEY_HOLD, "0"); sNodeDefaultMap.put(FP_KEY_LEFT, "0"); sNodeDefaultMap.put(FP_KEY_RIGHT, "0"); sNodeDefaultMap.put(FP_KEYS_OFF, "0"); + sNodeDefaultMap.put(FP_KEY_DBLTAP_OFF, "0"); sNodeDefaultMap.put(FP_KEY_HOLD_OFF, "0"); sNodeDefaultMap.put(FP_KEY_LEFT_OFF, "0"); sNodeDefaultMap.put(FP_KEY_RIGHT_OFF, "0"); - sNodeDefaultMap.put(FP_HAPTIC_KEY, false); + sNodeDefaultMap.put(GESTURE_SWIPE_RIGHT, "0"); + sNodeDefaultMap.put(GESTURE_SWIPE_LEFT, "0"); + sNodeDefaultMap.put(GESTURE_SWIPE_DOWN, "0"); + sNodeDefaultMap.put(GESTURE_SWIPE_UP, "0"); } public static boolean isPreferenceEnabled(Context context, String key) { @@ -123,8 +254,8 @@ public class Constants { String value = "1"; Log.e(TAG, "Write Pref: " + pref); - if (!pref.equals(FP_KEYS) && !pref.equals(FP_KEY_HOLD) && !pref.equals(FP_KEY_LEFT) && !pref.equals(FP_KEY_RIGHT) && - !pref.equals(FP_KEYS_OFF) && !pref.equals(FP_KEY_HOLD_OFF) && !pref.equals(FP_KEY_LEFT_OFF) && !pref.equals(FP_KEY_RIGHT_OFF)) + if (!pref.equals(FP_KEYS) && !pref.equals(FP_KEY_DBLTAP) && !pref.equals(FP_KEY_HOLD) && !pref.equals(FP_KEY_LEFT) && !pref.equals(FP_KEY_RIGHT) && + !pref.equals(FP_KEYS_OFF) && !pref.equals(FP_KEY_DBLTAP_OFF) && !pref.equals(FP_KEY_HOLD_OFF) && !pref.equals(FP_KEY_LEFT_OFF) && !pref.equals(FP_KEY_RIGHT_OFF) && !pref.equals(GESTURE_SWIPE_RIGHT) && !pref.equals(GESTURE_SWIPE_LEFT) && !pref.equals(GESTURE_SWIPE_DOWN) && !pref.equals(GESTURE_SWIPE_UP)) value = isPreferenceEnabled(context, pref) ? "1" : "0"; else value = GetPreference(context, pref); diff --git a/LineageActions/src/org/lineageos/settings/device/doze/ScreenReceiver.java b/LineageActions/src/org/lineageos/settings/device/doze/ScreenReceiver.java index 924c2b1..cec01d0 100644 --- a/LineageActions/src/org/lineageos/settings/device/doze/ScreenReceiver.java +++ b/LineageActions/src/org/lineageos/settings/device/doze/ScreenReceiver.java @@ -41,16 +41,8 @@ public class ScreenReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { mNotifier.screenTurnedOff(); - - for (String pref : Constants.sButtonScreenOffPrefKeys) { - Constants.writePreference(context, pref); - } } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { mNotifier.screenTurnedOn(); - - for (String pref : Constants.sButtonPrefKeys) { - Constants.writePreference(context, pref); - } } } } diff --git a/overlay-lineage/lineage-sdk/lineage/res/res/values/config.xml b/overlay-lineage/lineage-sdk/lineage/res/res/values/config.xml index bb1ca9f..7e966fb 100644 --- a/overlay-lineage/lineage-sdk/lineage/res/res/values/config.xml +++ b/overlay-lineage/lineage-sdk/lineage/res/res/values/config.xml @@ -56,4 +56,14 @@ false + + + /system/priv-app/LineageActions/LineageActions.apk + + + + + org.lineageos.settings.device.KeyHandler + + diff --git a/rootdir/etc/init.qcom.rc b/rootdir/etc/init.qcom.rc index 4ca5a18..9838bc3 100644 --- a/rootdir/etc/init.qcom.rc +++ b/rootdir/etc/init.qcom.rc @@ -200,17 +200,29 @@ on boot chown system system /sys/homebutton/enable chown system system /sys/homebutton/enable_off chown system system /sys/homebutton/haptic + chown system system /sys/homebutton/haptic_off chown system system /sys/homebutton/key chown system system /sys/homebutton/key_hold - chown system system /sys/homebutton/key_up - chown system system /sys/homebutton/key_down chown system system /sys/homebutton/key_dbltap chown system system /sys/homebutton/key_left chown system system /sys/homebutton/key_right + chown system system /sys/homebutton/key_screenoff + chown system system /sys/homebutton/key_screenoff_hold + chown system system /sys/homebutton/key_screenoff_dbltap + chown system system /sys/homebutton/key_screenoff_left + chown system system /sys/homebutton/key_screenoff_right - # Wake Gestures + # Screen off Gestures chown system radio /sys/android_touch/doubletap2wake chmod 0660 /sys/android_touch/doubletap2wake + chown system radio /sys/android_touch/gesture_swipe_right + chmod 0660 /sys/android_touch/gesture_swipe_right + chown system radio /sys/android_touch/gesture_swipe_left + chmod 0660 /sys/android_touch/gesture_swipe_left + chown system radio /sys/android_touch/gesture_swipe_down + chmod 0660 /sys/android_touch/gesture_swipe_down + chown system radio /sys/android_touch/gesture_swipe_up + chmod 0660 /sys/android_touch/gesture_swipe_up # Display chown system graphics /sys/class/graphics/fb1/hpd @@ -853,7 +865,7 @@ on property:sys.boot_completed=1 # Apply inter-cluster load balancer restrictions write /proc/sys/kernel/sched_restrict_cluster_spill 1 - + # set sync wakee policy tunable write /proc/sys/kernel/sched_prefer_sync_wakee_to_waker 1 @@ -872,7 +884,7 @@ on property:sys.boot_completed=1 write /sys/class/devfreq/soc:qcom,cpubw/bw_hwmon/up_scale 250 write /sys/class/devfreq/soc:qcom,cpubw/min_freq 1611 write /sys/class/devfreq/soc:qcom,gpubw/bw_hwmon/io_percent 40 - + # disable thermal & BCL core_control to update interactive gov settings write /sys/module/msm_thermal/core_control/enabled 0 write /sys/devices/soc/soc:qcom,bcl/mode "disable"