sanders: BRINGUP A NEW LINEAGE TREE

Signed-off-by: ronaxdevil <pratabidya.007@gmail.com>
This commit is contained in:
chirayu19091997
2018-12-15 14:27:53 +00:00
committed by ronaxdevil
parent 54422cfb9b
commit 9910e9f435
68 changed files with 1035 additions and 670 deletions

34
LineageActions/Android.mk Normal file
View File

@@ -0,0 +1,34 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := LineageActions
LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
LOCAL_USE_AAPT2 := true
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-v14-preference \
android-support-v7-appcompat \
android-support-v7-preference \
android-support-v7-recyclerview \
org.lineageos.platform.internal
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
LOCAL_RESOURCE_DIR := \
$(LOCAL_PATH)/res \
$(LOCAL_PATH)/../../../../packages/resources/devicesettings/res \
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_DEX_PREOPT := false
include frameworks/base/packages/SettingsLib/common.mk
include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))

View File

@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.lineageos.settings.device"
android:sharedUserId="android.uid.system"
>
<original-package android:name="com.cyanogenmod.settings.device" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<protected-broadcast android:name="com.android.systemui.doze.pulse" />
<uses-sdk
android:minSdkVersion="26"
android:targetSdkVersion="26" />
<application
android:allowBackup="true"
android:label="@string/moto_actions_title"
android:icon="@drawable/ic_gesture"
android:persistent="true">
<provider
android:name=".LineageActionsSearchIndexablesProvider"
android:authorities="org.lineageos.settings.device"
android:multiprocess="false"
android:grantUriPermissions="true"
android:permission="android.permission.READ_SEARCH_INDEXABLES"
android:exported="true">
<intent-filter>
<action android:name="android.content.action.SEARCH_INDEXABLES_PROVIDER" />
</intent-filter>
</provider>
<receiver android:name="org.lineageos.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>
<activity
android:name=".DozeSettingsActivity"
android:label="@string/ambient_display_title"
android:theme="@style/LineageActions">
<intent-filter>
<action android:name="org.lineageos.settings.device.DOZE_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".ActionsPreferenceActivity"
android:label="@string/moto_actions_title"
android:summary="@string/device_gestures_summary"
android:theme="@style/LineageActions">
<intent-filter>
<action android:name="com.android.settings.action.IA_SETTINGS" />
</intent-filter>
<meta-data
android:name="com.android.settings.category"
android:value="com.android.settings.category.ia.homepage" />
<meta-data
android:name="com.android.settings.icon"
android:resource="@drawable/ic_settings_gestures" />
<meta-data
android:name="com.android.settings.summary"
android:resource="@string/device_gestures_summary" />
</activity>
<activity
android:name=".GestureSettingsActivity"
android:label="@string/device_gestures_title"
android:theme="@style/LineageActions">
</activity>
<activity
android:name=".FPGestureSettingsActivity"
android:label="@string/fingerprint_gestures_title"
android:theme="@style/LineageActions">
</activity>
<activity
android:name=".ScreenOffGestureSettingsActivity"
android:label="@string/screen_off_gestures_title"
android:theme="@style/LineageActions">
</activity>
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="1000.000000"
android:viewportHeight="1000.000000"
android:tint="?android:attr/colorControlNormal">
<group
android:translateY="1000.000000"
android:scaleX="0.100000"
android:scaleY="-0.100000">
<path
android:fillColor="#FFFFFFFF"
android:strokeWidth="1"
android:pathData="M3022 9600 c-109 -29 -187 -74 -272 -160 -87 -86 -131 -163 -160 -276 -20 -76 -20
-127 -20 -4094 0 -3967 0 -4018 20 -4094 29 -113 73 -190 160 -276 86 -87 163 -131
276 -160 75 -20 117 -20 1849 -20 1732 0 1774 0 1849 20 113 29 190 73 276 160 87
86 131 163 160 276 20 76 20 127 20 4094 0 3967 0 4018 -20 4094 -29 113 -73 190
-160 276 -86 87 -163 131 -276 160 -75 20 -116 20 -1853 19 -1716 0 -1778 -1 -1849
-19z m1943 -2149 c51 -23 93 -65 116 -116 14 -31 19 -65 19 -150 l0 -110 83 -19
c227 -50 446 -169 623 -338 195 -187 315 -391 387 -658 l32 -115 3 -785 2 -785 363
-357 362 -357 -2075 0 -2075 0 352 347 352 347 3 795 3 795 32 115 c72 267 192 471
387 658 177 169 396 288 624 338 l82 19 0 110 c0 85 5 119 19 150 38 84 117 135
211 135 32 0 72 -8 95 -19z m415 -4018 c-1 -27 -32 -118 -60 -172 -60 -119 -188
-221 -325 -257 -27 -8 -86 -14 -130 -14 -95 0 -157 15 -244 60 -119 60 -221 188
-257 325 -8 28 -14 53 -14 58 0 4 232 7 515 7 283 0 515 -3 515 -7z" />
</group>
</vector>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">
<path android:fillColor="#FFFFFFFF" android:pathData="M11.83,1.73C8.43,1.79 6.23,3.32 6.23,3.32C5.95,3.5 5.88,3.91 6.07,4.19C6.27,4.5 6.66,4.55 6.96,4.34C6.96,4.34 11.27,1.15 17.46,4.38C17.75,4.55 18.14,4.45 18.31,4.15C18.5,3.85 18.37,3.47 18.03,3.28C16.36,2.4 14.78,1.96 13.36,1.8C12.83,1.74 12.32,1.72 11.83,1.73M12.22,4.34C6.26,4.26 3.41,9.05 3.41,9.05C3.22,9.34 3.3,9.72 3.58,9.91C3.87,10.1 4.26,10 4.5,9.68C4.5,9.68 6.92,5.5 12.2,5.59C17.5,5.66 19.82,9.65 19.82,9.65C20,9.94 20.38,10.04 20.68,9.87C21,9.69 21.07,9.31 20.9,9C20.9,9 18.15,4.42 12.22,4.34M11.5,6.82C9.82,6.94 8.21,7.55 7,8.56C4.62,10.53 3.1,14.14 4.77,19C4.88,19.33 5.24,19.5 5.57,19.39C5.89,19.28 6.07,18.92 5.95,18.6V18.6C4.41,14.13 5.78,11.2 7.8,9.5C9.77,7.89 13.25,7.5 15.84,9.1C17.11,9.9 18.1,11.28 18.6,12.64C19.11,14 19.08,15.32 18.67,15.94C18.25,16.59 17.4,16.83 16.65,16.64C15.9,16.45 15.29,15.91 15.26,14.77C15.23,13.06 13.89,12 12.5,11.84C11.16,11.68 9.61,12.4 9.21,14C8.45,16.92 10.36,21.07 14.78,22.45C15.11,22.55 15.46,22.37 15.57,22.04C15.67,21.71 15.5,21.35 15.15,21.25C11.32,20.06 9.87,16.43 10.42,14.29C10.66,13.33 11.5,13 12.38,13.08C13.25,13.18 14,13.7 14,14.79C14.05,16.43 15.12,17.54 16.34,17.85C17.56,18.16 18.97,17.77 19.72,16.62C20.5,15.45 20.37,13.8 19.78,12.21C19.18,10.61 18.07,9.03 16.5,8.04C14.96,7.08 13.19,6.7 11.5,6.82M11.86,9.25V9.26C10.08,9.32 8.3,10.24 7.28,12.18C5.96,14.67 6.56,17.21 7.44,19.04C8.33,20.88 9.54,22.1 9.54,22.1C9.78,22.35 10.17,22.35 10.42,22.11C10.67,21.87 10.67,21.5 10.43,21.23C10.43,21.23 9.36,20.13 8.57,18.5C7.78,16.87 7.3,14.81 8.38,12.77C9.5,10.67 11.5,10.16 13.26,10.67C15.04,11.19 16.53,12.74 16.5,15.03C16.46,15.38 16.71,15.68 17.06,15.7C17.4,15.73 17.7,15.47 17.73,15.06C17.79,12.2 15.87,10.13 13.61,9.47C13.04,9.31 12.45,9.23 11.86,9.25M12.08,14.25C11.73,14.26 11.46,14.55 11.47,14.89C11.47,14.89 11.5,16.37 12.31,17.8C13.15,19.23 14.93,20.59 18.03,20.3C18.37,20.28 18.64,20 18.62,19.64C18.6,19.29 18.3,19.03 17.91,19.06C15.19,19.31 14.04,18.28 13.39,17.17C12.74,16.07 12.72,14.88 12.72,14.88C12.72,14.53 12.44,14.25 12.08,14.25Z" />
</vector>

View File

@@ -0,0 +1,29 @@
<?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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="32.0"
android:viewportHeight="32.0"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:pathData="M20,20.2V24H6V5.3h8.7l2.4,-4H7.6c-2.2,0 -4,1.8 -4,4v21.3c0,2.2 1.8,4 4,4h10.7c2.2,0 4,-1.8 4,-4V14.9L20,20.2zM15.6,28h-5.3v-1.3h5.3V28z"/>
<path
android:fillColor="#FF000000"
android:pathData="M28.5,7l1.1,-2.4L32,3.5l-2.4,-1.1L28.5,0l-1.1,2.4L25,3.5l2.4,1.1L28.5,7zM21,7.4l-2.2,-4.8l-2.2,4.8l-4.8,2.2l4.8,2.2l2.2,4.8l2.2,-4.8l4.8,-2.2L21,7.4zM28.5,12.2l-1.1,2.4L25,15.6l2.4,1.1l1.1,2.4l1.1,-2.4l2.4,-1.1l-2.4,-1.1L28.5,12.2z"/>
</vector>

View File

@@ -0,0 +1,22 @@
<!--
Copyright (C) 2016 The Android Open Source 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M9,11.24L9,7.5C9,6.12 10.12,5 11.5,5S14,6.12 14,7.5v3.74c1.21,-0.81 2,-2.18 2,-3.74C16,5.01 13.99,3 11.5,3S7,5.01 7,7.5c0,1.56 0.79,2.93 2,3.74zM18.84,15.87l-4.54,-2.26c-0.17,-0.07 -0.35,-0.11 -0.54,-0.11L13,13.5v-6c0,-0.83 -0.67,-1.5 -1.5,-1.5S10,6.67 10,7.5v10.74l-3.43,-0.72c-0.08,-0.01 -0.15,-0.03 -0.24,-0.03 -0.31,0 -0.59,0.13 -0.79,0.33l-0.79,0.8 4.94,4.94c0.27,0.27 0.65,0.44 1.06,0.44h6.79c0.75,0 1.33,-0.55 1.44,-1.28l0.75,-5.27c0.01,-0.07 0.02,-0.14 0.02,-0.2 0,-0.62 -0.38,-1.16 -0.91,-1.38z"/>
</vector>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source 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.
-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorControlHighlight">
<item android:drawable="?android:attr/colorSecondary" />
</ripple>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2014, The Android Open Source 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.
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_height="match_parent"
android:layout_width="match_parent">
<include layout="@layout/switch_bar" />
</LinearLayout>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2014, The Android Open Source 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.
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_height="match_parent"
android:layout_width="match_parent">
<include layout="@layout/switch_bar" />
</LinearLayout>

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/switch_bar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="@drawable/switchbar_background"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:clickable="true"
android:gravity="center">
<TextView android:id="@+id/switch_text"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:paddingStart="48dp"
android:maxLines="2"
android:ellipsize="end"
android:textAppearance="@android:style/TextAppearance.Material.Title"
android:textColor="?android:attr/textColorPrimary"
android:textAlignment="viewStart"
android:text="@string/switch_bar_on" />
<Switch
android:id="@android:id/switch_widget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@null"
android:theme="@style/LineageActions.SwitchBar" />
</LinearLayout>

View File

@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2013-2016 The CyanogenMod Project
(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.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Title and summary -->
<string name="moto_actions_title">Moto Ações</string>
<!-- Device gestures -->
<string name="device_gestures_title">Gestos do dispositivo</string>
<string name="device_gestures_summary">Gerenciar os gestos do dispositivo</string>
<!-- Ambient display gestures -->
<string name="ambient_display_manage_summary">Gerenciar os gestos da tela ambiente</string>
<!-- Fingerprint gestures -->
<string name="fingerprint_gestures_title">Gestos no sensor biométrico</string>
<string name="fingerprint_gestures_summary">Habilitar o uso de gestos no sensor biométrico</string>
<string name="fingerprint_gestures_manage_summary">Gerenciar os gestos do sensor biométrico</string>
<string name="fingerprint_actions_screenon">Ações com a tela ligada</string>
<string name="fingerprint_tap_title">Toque único</string>
<string name="fingerprint_tap_dlg_title">Selecione a ação para toque único</string>
<string name="fingerprint_double_tap_title">Toque duplo</string>
<string name="fingerprint_double_tap_dlg_title">Selecione a ação para toque duplo</string>
<string name="fingerprint_long_tap_title">Toque longo</string>
<string name="fingerprint_long_tap_dlg_title">Selecione a ação para toque longo</string>
<string name="fingerprint_swipe_left_title">Deslizar para a esquerda</string>
<string name="fingerprint_swipe_left_dlg_title">Selecione a ação para deslizar para a esquerda</string>
<string name="fingerprint_swipe_right_title">Deslizar para a direita</string>
<string name="fingerprint_swipe_right_dlg_title">Selecione a ação para deslizar para a direita</string>
<!-- Fingerprint gestures screen off -->
<string name="fingerprint_gestures_screenoff_title">Habilitar com a tela desligada</string>
<string name="fingerprint_gestures_screenoff_summary">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.</string>
<string name="fingerprint_actions_screenoff">Ações com a tela desligada</string>
<!-- Actions -->
<string name="action_none">Não fazer nada</string>
<string name="action_home">Início</string>
<string name="action_power">Ligar/desligar tela</string>
<string name="action_wake">Acordar o dispositivo</string>
<string name="action_back">Voltar</string>
<string name="action_recents">Recentes</string>
<string name="action_last_app">Último app</string>
<string name="action_volume_up">Aumentar volume</string>
<string name="action_volume_down">Diminuir volume</string>
<string name="action_voice_assistant">Assistente de voz</string>
<string name="action_play_pause">Tocar/pausar</string>
<string name="action_previous_track">Faixa anterior</string>
<string name="action_next_track">Próxima faixa</string>
<string name="action_flashlight">Ligar/desligar lanterna</string>
<string name="action_camera">Abrir câmera</string>
<string name="action_screenshot">Tirar uma captura de tela</string>
<string name="action_browser">Abrir navegador</string>
<string name="action_dialer">Abrir discador</string>
<string name="action_email">Abrir app de mail</string>
<string name="action_messages">Abrir app de mensagens</string>
<!-- Screen off gestures -->
<string name="screen_off_gestures_title">Gestos com a tela desligada</string>
<string name="screen_off_gestures_manage_summary">Gerenciar os gestos com a tela desligada</string>
<string name="screen_off_gestures_swipe_left_title">Deslizar para a esquerda</string>
<string name="screen_off_gestures_swipe_left_dlg_title">Selecione a ação para deslizar para a esquerda</string>
<string name="screen_off_gestures_swipe_right_title">Deslizar para a direita</string>
<string name="screen_off_gestures_swipe_right_dlg_title">Selecione a ação para deslizar para a direita</string>
<string name="screen_off_gestures_swipe_up_title">Deslizar para cima</string>
<string name="screen_off_gestures_swipe_up_dlg_title">Selecione a ação para deslizar para cima</string>
<string name="screen_off_gestures_swipe_down_title">Deslizar para baixo</string>
<string name="screen_off_gestures_swipe_down_dlg_title">Selecione a ação para deslizar para baixo</string>
<!-- Double tap to wake -->
<string name="tap_to_wake">Tocar para ativar</string>
<string name="tap_to_wake_summary">Toque duas vezes em qualquer parte da tela para ativar o dispositivo</string>
<!-- Screen off gestures haptic feedback -->
<string name="haptic_feedback">Retorno tátil</string>
<string name="haptic_feedback_summary">Vibrar quando um gesto for detectado</string>
<!-- Proximity sensor -->
<string name="allow_proximity_sensor_title">Habilitar o sensor de proximidade</string>
<string name="allow_proximity_sensor_summary">Verificar o sensor de proximidade antes de executar a ação</string>
</resources>

View File

@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<resources>
<string-array name="fp_keys_listArray">
<item>@string/action_none</item>
<item>@string/action_home</item>
<item>@string/action_power</item>
<item>@string/action_back</item>
<item>@string/action_recents</item>
<item>@string/action_last_app</item>
<item>@string/action_volume_up</item>
<item>@string/action_volume_down</item>
<item>@string/action_voice_assistant</item>
<item>@string/action_play_pause</item>
<item>@string/action_previous_track</item>
<item>@string/action_next_track</item>
<item>@string/action_flashlight</item>
<item>@string/action_camera</item>
<item>@string/action_screenshot</item>
</string-array>
<string-array name="fp_keys_listValues">
<item>0</item>
<item>100</item> <!-- home -->
<item>101</item> <!-- power -->
<item>102</item> <!-- back -->
<item>103</item> <!-- recents -->
<item>121</item> <!-- last app -->
<item>104</item> <!-- volume up -->
<item>105</item> <!-- volume down -->
<item>106</item> <!-- voice assistant -->
<item>107</item> <!-- play/pause -->
<item>108</item> <!-- previous track -->
<item>109</item> <!-- next track -->
<item>110</item> <!-- flashlight -->
<item>111</item> <!-- camera -->
<item>112</item> <!-- screenshot -->
</string-array>
<string-array name="fp_keys_screen_off_listArray">
<item>@string/action_none</item>
<item>@string/action_power</item>
<item>@string/action_volume_up</item>
<item>@string/action_volume_down</item>
<item>@string/action_play_pause</item>
<item>@string/action_previous_track</item>
<item>@string/action_next_track</item>
<item>@string/action_flashlight</item>
<item>@string/action_camera</item>
</string-array>
<string-array name="fp_keys_screen_off_listValues">
<item>0</item>
<item>101</item> <!-- power -->
<item>104</item> <!-- volume up -->
<item>105</item> <!-- volume down -->
<item>107</item> <!-- play/pause -->
<item>108</item> <!-- previous track -->
<item>109</item> <!-- next track -->
<item>110</item> <!-- flashlight -->
<item>111</item> <!-- camera -->
</string-array>
<string-array name="screen_off_listArray">
<item>@string/action_none</item>
<item>@string/action_wake</item>
<item>@string/action_play_pause</item>
<item>@string/action_previous_track</item>
<item>@string/action_next_track</item>
<item>@string/action_flashlight</item>
<item>@string/action_camera</item>
<item>@string/action_browser</item>
<item>@string/action_dialer</item>
<item>@string/action_email</item>
<item>@string/action_messages</item>
</string-array>
<string-array name="screen_off_listValues">
<item>0</item>
<item>101</item> <!-- wake/power -->
<item>107</item> <!-- play/pause -->
<item>108</item> <!-- previous track -->
<item>109</item> <!-- next track -->
<item>110</item> <!-- flashlight -->
<item>111</item> <!-- camera -->
<item>116</item> <!-- browser -->
<item>117</item> <!-- dialer -->
<item>118</item> <!-- email -->
<item>119</item> <!-- messages -->
</string-array>
</resources>

View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2013-2016 The CyanogenMod Project
(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.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Title and summary -->
<string name="moto_actions_title">Moto Actions</string>
<!-- Device gestures -->
<string name="device_gestures_title">Device gestures</string>
<string name="device_gestures_summary">Manage device gestures</string>
<!-- Ambient display gestures -->
<string name="ambient_display_manage_summary">Manage ambient display gestures</string>
<!-- Fingerprint gestures -->
<string name="fingerprint_gestures_title">Fingerprint gestures</string>
<string name="fingerprint_gestures_summary">Use fingerprint gestures</string>
<string name="fingerprint_gestures_manage_summary">Manage fingerprint gestures</string>
<string name="fingerprint_actions_screenon">Actions with screen on</string>
<string name="fingerprint_tap_title">Single tap</string>
<string name="fingerprint_tap_dlg_title">Select action for single tap</string>
<string name="fingerprint_double_tap_title">Double tap</string>
<string name="fingerprint_double_tap_dlg_title">Select action for double tap</string>
<string name="fingerprint_long_tap_title">Long tap</string>
<string name="fingerprint_long_tap_dlg_title">Select action for long tap</string>
<string name="fingerprint_swipe_left_title">Swipe left</string>
<string name="fingerprint_swipe_left_dlg_title">Select action for swipe left</string>
<string name="fingerprint_swipe_right_title">Swipe right</string>
<string name="fingerprint_swipe_right_dlg_title">Select action for swipe right</string>
<!-- Fingerprint gestures screen off -->
<string name="fingerprint_gestures_screenoff_title">Fingerprint gestures when screen off</string>
<string name="fingerprint_gestures_screenoff_summary">Use fingerprint gestures when screen off.\n\nFingerprint unlocking must be disabled to use this feature.</string>
<string name="fingerprint_actions_screenoff">Actions with screen off</string>
<!-- Actions -->
<string name="action_none">None</string>
<string name="action_home">Home</string>
<string name="action_power">Screen on/off</string>
<string name="action_wake">Wake</string>
<string name="action_back">Back</string>
<string name="action_recents">Recents</string>
<string name="action_last_app">Last app</string>
<string name="action_volume_up">Volume up</string>
<string name="action_volume_down">Volume down</string>
<string name="action_voice_assistant">Voice assistant</string>
<string name="action_play_pause">Play/pause</string>
<string name="action_previous_track">Previous track</string>
<string name="action_next_track">Next track</string>
<string name="action_flashlight">Flashlight on/off</string>
<string name="action_camera">Open camera</string>
<string name="action_screenshot">Take screenshot</string>
<string name="action_browser">Open browser</string>
<string name="action_dialer">Open dialer</string>
<string name="action_email">Open email app</string>
<string name="action_messages">Open messages app</string>
<!-- Screen off gestures -->
<string name="screen_off_gestures_title">Screen off gestures</string>
<string name="screen_off_gestures_manage_summary">Manage gestures when screen is off</string>
<string name="screen_off_gestures_swipe_left_title">Swipe left</string>
<string name="screen_off_gestures_swipe_left_dlg_title">Select action for swipe left</string>
<string name="screen_off_gestures_swipe_right_title">Swipe right</string>
<string name="screen_off_gestures_swipe_right_dlg_title">Select action for swipe right</string>
<string name="screen_off_gestures_swipe_up_title">Swipe up</string>
<string name="screen_off_gestures_swipe_up_dlg_title">Select action for swipe up</string>
<string name="screen_off_gestures_swipe_down_title">Swipe down</string>
<string name="screen_off_gestures_swipe_down_dlg_title">Select action for swipe down</string>
<!-- Double tap to wake -->
<string name="tap_to_wake">Tap to wake</string>
<string name="tap_to_wake_summary">Double-tap anywhere on the screen to wake device</string>
<!-- Screen off gestures haptic feedback -->
<string name="haptic_feedback">Haptic feedback</string>
<string name="haptic_feedback_summary">Vibrate when a touchscreen gesture is detected</string>
<!-- Proximity sensor -->
<string name="allow_proximity_sensor_title">Allow proximity sensor</string>
<string name="allow_proximity_sensor_summary">Check the proximity sensor before performing the action</string>
</resources>

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<style name="LineageActions" parent="@android:style/Theme.DeviceDefault.Settings">
<item name="dialogPreferenceStyle">@style/LineageActions.DialogPreferenceStyle</item>
<item name="preferenceCategoryStyle">@style/LineageActions.PreferenceCategoryStyle</item>
<item name="preferenceFragmentStyle">@style/LineageActions.PreferenceFragmentStyle</item>
<item name="preferenceStyle">@style/LineageActions.PreferenceStyle</item>
<item name="preferenceTheme">@style/LineageActions.PreferenceTheme</item>
<item name="switchPreferenceStyle">@style/LineageActions.SwitchPreferenceStyle</item>
</style>
<style name="LineageActions.DialogPreferenceStyle" parent="@style/LineageActions.PreferenceStyle">
</style>
<style name="LineageActions.PreferenceCategoryStyle" parent="@*android:style/Preference.DeviceDefault.Category">
<item name="allowDividerAbove">true</item>
<item name="allowDividerBelow">true</item>
<item name="android:layout">@layout/preference_category_material_settings</item>
</style>
<style name="LineageActions.PreferenceFragmentStyle" parent="@*android:style/PreferenceFragment.Material">
<item name="allowDividerAfterLastItem">false</item>
</style>
<style name="LineageActions.PreferenceStyle" parent="@*android:style/Preference.DeviceDefault">
<item name="allowDividerAbove">false</item>
<item name="allowDividerBelow">true</item>
<item name="singleLineTitle">false</item>
<item name="android:layout">@layout/preference_material_settings</item>
</style>
<style name="LineageActions.PreferenceTheme">
</style>
<style name="LineageActions.SwitchPreferenceStyle" parent="@style/LineageActions.PreferenceStyle">
<item name="widgetLayout">@*android:layout/preference_widget_switch</item>
</style>
<style name="LineageActions.SwitchBar" parent="@android:style/ThemeOverlay.Material.ActionBar">
</style>
</resources>

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015-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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
<SwitchPreference
android:key="gesture_camera_action"
android:defaultValue="true"
android:title="@string/camera_gesture_title"
android:summary="@string/camera_gesture_summary" />
<SwitchPreference
android:key="gesture_chop_chop"
android:defaultValue="true"
android:title="@string/chop_chop_gesture_title"
android:summary="@string/chop_chop_gesture_summary" />
<SwitchPreference
android:key="gesture_ir_silencer"
android:defaultValue="false"
android:title="@string/hand_wave_silencer_title"
android:summary="@string/hand_wave_silencer_summary" />
<SwitchPreference
android:key="gesture_flip_to_mute"
android:defaultValue="false"
android:title="@string/flip_to_mute_title"
android:summary="@string/flip_to_mute_summary" />
<SwitchPreference
android:key="gesture_lift_to_silence"
android:defaultValue="false"
android:title="@string/lift_to_silence_title"
android:summary="@string/lift_to_silence_summary" />
</PreferenceScreen>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
<SwitchPreference
android:key="gesture_pick_up"
android:defaultValue="true"
android:title="@string/pick_up_gesture_title"
android:summary="@string/pick_up_gesture_summary" />
<SwitchPreference
android:key="gesture_hand_wave"
android:defaultValue="true"
android:title="@string/hand_wave_gesture_title"
android:summary="@string/hand_wave_gesture_summary" />
</PreferenceScreen>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015-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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
<Preference
android:key="doze"
android:title="@string/ambient_display_title"
android:summary="@string/ambient_display_manage_summary"
android:icon="@drawable/ic_settings_doze" />
</PreferenceScreen>

View File

@@ -0,0 +1,151 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015-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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
<SwitchPreference
android:key="fp_home_scr_off"
android:enabled="false"
android:title="@string/fingerprint_gestures_screenoff_title"
android:summary="@string/fingerprint_gestures_screenoff_summary" />
<PreferenceCategory
android:key="fp_keys_scr_on"
android:title="@string/fingerprint_actions_screenon" >
<SwitchPreference
android:key="fp_haptic"
android:defaultValue="0"
android:title="@string/haptic_feedback"
android:summary="@string/haptic_feedback_summary" />
<ListPreference
android:title="@string/fingerprint_tap_title"
android:summary="%s"
android:dialogTitle="@string/fingerprint_tap_dlg_title"
android:key="fp_keys"
android:defaultValue="0"
android:entries="@array/fp_keys_listArray"
android:entryValues="@array/fp_keys_listValues" />
<ListPreference
android:title="@string/fingerprint_double_tap_title"
android:summary="%s"
android:dialogTitle="@string/fingerprint_double_tap_dlg_title"
android:key="fp_key_dbltap"
android:defaultValue="0"
android:entries="@array/fp_keys_listArray"
android:entryValues="@array/fp_keys_listValues" />
<ListPreference
android:title="@string/fingerprint_long_tap_title"
android:summary="%s"
android:dialogTitle="@string/fingerprint_long_tap_dlg_title"
android:key="fp_key_hold"
android:defaultValue="0"
android:entries="@array/fp_keys_listArray"
android:entryValues="@array/fp_keys_listValues" />
<ListPreference
android:title="@string/fingerprint_swipe_left_title"
android:summary="%s"
android:dialogTitle="@string/fingerprint_swipe_left_dlg_title"
android:key="fp_key_left"
android:defaultValue="0"
android:entries="@array/fp_keys_listArray"
android:entryValues="@array/fp_keys_listValues" />
<ListPreference
android:title="@string/fingerprint_swipe_right_title"
android:summary="%s"
android:dialogTitle="@string/fingerprint_swipe_right_dlg_title"
android:key="fp_key_right"
android:defaultValue="0"
android:entries="@array/fp_keys_listArray"
android:entryValues="@array/fp_keys_listValues" />
</PreferenceCategory>
<PreferenceCategory
android:key="fp_keys_scr_off"
android:title="@string/fingerprint_actions_screenoff"
android:enabled="false" >
<SwitchPreference
android:key="fp_haptic_scr_off"
android:dependency="fp_home_scr_off"
android:defaultValue="0"
android:title="@string/haptic_feedback"
android:summary="@string/haptic_feedback_summary" />
<SwitchPreference
android:key="fp_proximity_check_scr_off"
android:dependency="fp_home_scr_off"
android:defaultValue="1"
android:title="@string/allow_proximity_sensor_title"
android:summary="@string/allow_proximity_sensor_summary" />
<ListPreference
android:dependency="fp_home_scr_off"
android:title="@string/fingerprint_tap_title"
android:summary="%s"
android:dialogTitle="@string/fingerprint_tap_dlg_title"
android:key="fp_keys_off"
android:defaultValue="0"
android:entries="@array/fp_keys_screen_off_listArray"
android:entryValues="@array/fp_keys_screen_off_listValues" />
<ListPreference
android:dependency="fp_home_scr_off"
android:title="@string/fingerprint_double_tap_title"
android:summary="%s"
android:dialogTitle="@string/fingerprint_double_tap_dlg_title"
android:key="fp_key_dbltap_off"
android:defaultValue="0"
android:entries="@array/fp_keys_screen_off_listArray"
android:entryValues="@array/fp_keys_screen_off_listValues" />
<ListPreference
android:dependency="fp_home_scr_off"
android:title="@string/fingerprint_long_tap_title"
android:summary="%s"
android:dialogTitle="@string/fingerprint_long_tap_dlg_title"
android:key="fp_key_hold_off"
android:defaultValue="0"
android:entries="@array/fp_keys_screen_off_listArray"
android:entryValues="@array/fp_keys_screen_off_listValues" />
<ListPreference
android:dependency="fp_home_scr_off"
android:title="@string/fingerprint_swipe_left_title"
android:summary="%s"
android:dialogTitle="@string/fingerprint_swipe_left_dlg_title"
android:key="fp_key_left_off"
android:defaultValue="0"
android:entries="@array/fp_keys_screen_off_listArray"
android:entryValues="@array/fp_keys_screen_off_listValues" />
<ListPreference
android:dependency="fp_home_scr_off"
android:title="@string/fingerprint_swipe_right_title"
android:summary="%s"
android:dialogTitle="@string/fingerprint_swipe_right_dlg_title"
android:key="fp_key_right_off"
android:defaultValue="0"
android:entries="@array/fp_keys_screen_off_listArray"
android:entryValues="@array/fp_keys_screen_off_listValues" />
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015-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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
<Preference
android:key="fp_gestures"
android:title="@string/fingerprint_gestures_title"
android:summary="@string/fingerprint_gestures_manage_summary"
android:icon="@drawable/ic_settings_fingerprint" />
</PreferenceScreen>

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015-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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
<Preference
android:key="gestures"
android:title="@string/device_gestures_title"
android:summary="@string/device_gestures_summary"
android:icon="@drawable/ic_settings_gestures">
<intent
android:targetPackage="org.lineageos.settings.device"
android:targetClass="org.lineageos.settings.device.GestureSettingsActivity" />
</Preference>
<Preference
android:key="doze"
android:title="@string/ambient_display_title"
android:summary="@string/ambient_display_manage_summary"
android:icon="@drawable/ic_settings_doze">
<intent
android:targetPackage="org.lineageos.settings.device"
android:targetClass="org.lineageos.settings.device.DozeSettingsActivity" />
</Preference>
<Preference
android:key="fp_gestures"
android:title="@string/fingerprint_gestures_title"
android:summary="@string/fingerprint_gestures_manage_summary"
android:icon="@drawable/ic_settings_fingerprint">
<intent
android:targetPackage="org.lineageos.settings.device"
android:targetClass="org.lineageos.settings.device.FPGestureSettingsActivity" />
</Preference>
<Preference
android:key="screen_off_gestures"
android:title="@string/screen_off_gestures_title"
android:summary="@string/screen_off_gestures_manage_summary"
android:icon="@drawable/ic_settings_screen_off_gestures">
<intent
android:targetPackage="org.lineageos.settings.device"
android:targetClass="org.lineageos.settings.device.ScreenOffGestureSettingsActivity" />
</Preference>
</PreferenceScreen>

View File

@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015-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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
<SwitchPreference
android:key="tap_to_wake"
android:title="@string/tap_to_wake"
android:summary="@string/tap_to_wake_summary" />
<SwitchPreference
android:key="haptic_feedback"
android:title="@string/haptic_feedback"
android:summary="@string/haptic_feedback_summary" />
<SwitchPreference
android:key="proximity_sensor"
android:title="@string/allow_proximity_sensor_title"
android:summary="@string/allow_proximity_sensor_summary" />
<ListPreference
android:title="@string/screen_off_gestures_swipe_left_title"
android:summary="%s"
android:dialogTitle="@string/screen_off_gestures_swipe_left_dlg_title"
android:key="screen_off_gestures_swipe_left"
android:defaultValue="0"
android:entries="@array/screen_off_listArray"
android:entryValues="@array/screen_off_listValues" />
<ListPreference
android:title="@string/screen_off_gestures_swipe_right_title"
android:summary="%s"
android:dialogTitle="@string/screen_off_gestures_swipe_right_dlg_title"
android:key="screen_off_gestures_swipe_right"
android:defaultValue="0"
android:entries="@array/screen_off_listArray"
android:entryValues="@array/screen_off_listValues" />
<ListPreference
android:title="@string/screen_off_gestures_swipe_up_title"
android:summary="%s"
android:dialogTitle="@string/screen_off_gestures_swipe_up_dlg_title"
android:key="screen_off_gestures_swipe_up"
android:defaultValue="0"
android:entries="@array/screen_off_listArray"
android:entryValues="@array/screen_off_listValues" />
<ListPreference
android:title="@string/screen_off_gestures_swipe_down_title"
android:summary="%s"
android:dialogTitle="@string/screen_off_gestures_swipe_down_dlg_title"
android:key="screen_off_gestures_swipe_down"
android:defaultValue="0"
android:entries="@array/screen_off_listArray"
android:entryValues="@array/screen_off_listValues" />
</PreferenceScreen>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015-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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
<Preference
android:key="screen_off_gestures"
android:title="@string/screen_off_gestures_title"
android:summary="@string/screen_off_gestures_manage_summary"
android:icon="@drawable/ic_settings_screen_off_gestures" />
</PreferenceScreen>

View File

@@ -0,0 +1,33 @@
/*
* 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.preference.PreferenceActivity;
public class ActionsPreferenceActivity extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null){
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new ActionsPreferenceFragment()).commit();
}
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) 2015-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.os.Bundle;
import android.support.v14.preference.PreferenceFragment;
public class ActionsPreferenceFragment extends PreferenceFragment {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.main_panel);
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 2015 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.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.util.Log;
import lineageos.providers.LineageSettings;
import org.lineageos.settings.device.util.FileUtils;
import org.lineageos.settings.device.actions.Constants;
import org.lineageos.settings.device.ServiceWrapper.LocalBinder;
public class BootCompletedReceiver extends BroadcastReceiver {
static final String TAG = "LineageActions";
final String NAVBAR_SHOWN = "navbar_shown";
private ServiceWrapper mServiceWrapper;
@Override
public void onReceive(final Context context, Intent intent) {
Log.i(TAG, "Booting");
// Restore nodes to saved preference values
for (String pref : Constants.sPrefKeys) {
Constants.writePreference(context, pref);
}
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
if (!preferences.getBoolean(NAVBAR_SHOWN, false)) {
enableNavBar(true, context);
preferences.edit().putBoolean(NAVBAR_SHOWN, true).commit();
}
context.startService(new Intent(context, ServiceWrapper.class));
}
protected static void enableNavBar(boolean enable, Context context) {
// LineageSettings.Global.putInt(context.getContentResolver(),
// LineageSettings.Global.DEV_FORCE_SHOW_NAVBAR, enable ? 1 : 0);
}
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;
}
};
}

View File

@@ -0,0 +1,33 @@
/*
* 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.preference.PreferenceActivity;
public class DozeSettingsActivity extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null){
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new DozeSettingsFragment()).commit();
}
}
}

View File

@@ -0,0 +1,110 @@
/*
* 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.ActionBar;
import android.os.Bundle;
import android.support.v14.preference.PreferenceFragment;
import android.provider.Settings;
import android.support.v7.preference.Preference;
import android.support.v14.preference.SwitchPreference;
import android.view.MenuItem;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;
public class DozeSettingsFragment extends PreferenceFragment {
private SwitchPreference mHandwavePreference;
private SwitchPreference mPickupPreference;
private TextView mSwitchBarText;
private Switch mAmbientDisplaySwitch;
private String KEY_GESTURE_HAND_WAVE = "gesture_hand_wave";
private String KEY_GESTURE_PICK_UP = "gesture_pick_up";
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ActionBar actionbar = getActivity().getActionBar();
actionbar.setDisplayHomeAsUpEnabled(true);
actionbar.setTitle(R.string.ambient_display_title);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = LayoutInflater.from(getContext()).inflate(R.layout.doze, container, false);
((ViewGroup) view).addView(super.onCreateView(inflater, container, savedInstanceState));
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
View switchBar = view.findViewById(R.id.switch_bar);
mAmbientDisplaySwitch = (Switch) switchBar.findViewById(android.R.id.switch_widget);
mAmbientDisplaySwitch.setChecked(LineageActionsSettings.isDozeEnabled(getActivity().getContentResolver()));
mAmbientDisplaySwitch.setOnCheckedChangeListener(mAmbientDisplayPrefListener);
switchBar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mAmbientDisplaySwitch.toggle();
}
});
mSwitchBarText = switchBar.findViewById(R.id.switch_text);
mSwitchBarText.setText(LineageActionsSettings.isDozeEnabled(getActivity().getContentResolver()) ? R.string.switch_bar_on :
R.string.switch_bar_off);
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.doze_panel);
boolean dozeEnabled = LineageActionsSettings.isDozeEnabled(getActivity().getContentResolver());
mHandwavePreference = (SwitchPreference) findPreference(KEY_GESTURE_HAND_WAVE);
mPickupPreference = (SwitchPreference) findPreference(KEY_GESTURE_PICK_UP);
updatePrefs(dozeEnabled);
}
private CompoundButton.OnCheckedChangeListener mAmbientDisplayPrefListener =
new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean enable) {
if (enableDoze(enable)) {
updatePrefs(enable);
mSwitchBarText.setText(enable ? R.string.switch_bar_on : R.string.switch_bar_off);
}
}
};
private void updatePrefs(boolean enabled){
mHandwavePreference.setEnabled(enabled);
mPickupPreference.setEnabled(enabled);
}
private boolean enableDoze(boolean enable) {
return Settings.Secure.putInt(getActivity().getContentResolver(),
Settings.Secure.DOZE_ENABLED, enable ? 1 : 0);
}
}

View File

@@ -0,0 +1,33 @@
/*
* 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.preference.PreferenceActivity;
public class FPGestureSettingsActivity extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null){
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new FPGestureSettingsFragment()).commit();
}
}
}

View File

@@ -0,0 +1,128 @@
/*
* 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.ActionBar;
import android.os.Bundle;
import android.content.Context;
import android.content.SharedPreferences.Editor;
import android.preference.PreferenceManager;
import android.support.v7.preference.PreferenceCategory;
import android.support.v14.preference.SwitchPreference;
import android.hardware.fingerprint.FingerprintManager;
import android.support.v14.preference.PreferenceFragment;
import android.view.MenuItem;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;
import org.lineageos.settings.device.actions.Constants;
import static org.lineageos.settings.device.actions.Constants.FP_HOME_KEY;
import static org.lineageos.settings.device.actions.Constants.FP_HOME_KEY_OFF;
public class FPGestureSettingsFragment extends PreferenceFragment {
private SwitchPreference mFPScreenOffGesture;
private PreferenceCategory mFPScreenOffCategory;
private PreferenceCategory mFPScreenOnCategory;
private TextView mSwitchBarText;
private Switch mFPGestureSwitch;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ActionBar actionbar = getActivity().getActionBar();
actionbar.setDisplayHomeAsUpEnabled(true);
actionbar.setTitle(R.string.fingerprint_gestures_title);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = LayoutInflater.from(getContext()).inflate(R.layout.fp_gesture, container, false);
((ViewGroup) view).addView(super.onCreateView(inflater, container, savedInstanceState));
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
View switchBar = view.findViewById(R.id.switch_bar);
mFPGestureSwitch = (Switch) switchBar.findViewById(android.R.id.switch_widget);
mFPGestureSwitch.setChecked(isFPGestureEnabled());
mFPGestureSwitch.setOnCheckedChangeListener(mFPGesturePrefListener);
switchBar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mFPGestureSwitch.toggle();
}
});
mSwitchBarText = switchBar.findViewById(R.id.switch_text);
mSwitchBarText.setText(isFPGestureEnabled() ? R.string.switch_bar_on :
R.string.switch_bar_off);
}
private void updatePrefs(boolean enabled){
Editor prefEditor = PreferenceManager.getDefaultSharedPreferences(getActivity()).edit();
prefEditor.putBoolean(FP_HOME_KEY, enabled);
prefEditor.apply();
mFPScreenOnCategory.setEnabled(enabled);
mFPScreenOffGesture.setEnabled(enabled);
mFPScreenOffCategory.setEnabled(enabled);
if(enabled){
boolean hasEnrolledFingerprints = hasEnrolledFingerprints();
mFPScreenOffGesture.setEnabled(!hasEnrolledFingerprints);
mFPScreenOffCategory.setEnabled(!hasEnrolledFingerprints);
}
}
private boolean isFPGestureEnabled(){
return Constants.isPreferenceEnabled(getActivity(), FP_HOME_KEY);
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.fp_gesture_panel);
mFPScreenOffGesture = (SwitchPreference) findPreference(FP_HOME_KEY_OFF);
mFPScreenOffCategory = (PreferenceCategory) findPreference("fp_keys_scr_off");
mFPScreenOnCategory = (PreferenceCategory) findPreference("fp_keys_scr_on");
updatePrefs(isFPGestureEnabled());
}
private CompoundButton.OnCheckedChangeListener mFPGesturePrefListener =
new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean enable) {
updatePrefs(enable);
mSwitchBarText.setText(enable ? R.string.switch_bar_on : R.string.switch_bar_off);
}
};
private boolean hasEnrolledFingerprints(){
FingerprintManager fingerprintManager = (FingerprintManager) getActivity().getSystemService(Context.FINGERPRINT_SERVICE);
return fingerprintManager.hasEnrolledFingerprints();
}
}

View File

@@ -0,0 +1,33 @@
/*
* 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.preference.PreferenceActivity;
public class GestureSettingsActivity extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null){
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new GestureSettingsFragment()).commit();
}
}
}

View File

@@ -0,0 +1,35 @@
/*
* 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.support.v14.preference.PreferenceFragment;
public class GestureSettingsFragment extends PreferenceFragment {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.actions_panel);
}
}

View File

@@ -0,0 +1,929 @@
/*
* 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.ISearchManager;
import android.app.KeyguardManager;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
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.net.Uri;
import android.os.Bundle;
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.VibrationEffect;
import android.os.Vibrator;
import android.provider.MediaStore;
import android.provider.Settings;
import android.util.Log;
import android.view.InputDevice;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.ViewConfiguration;
import com.android.internal.os.DeviceKeyHandler;
import com.android.internal.util.ArrayUtils;
import org.lineageos.settings.device.util.FileUtils;
import java.util.List;
import lineageos.providers.LineageSettings;
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 static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
.build();
private final Context mContext;
private final PowerManager mPowerManager;
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;
private boolean fpGesturePending = false;
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, true);
}
}
resetDoubleTapOnFP();
}
};
private Runnable screenOffGestureRunnable = new Runnable() {
public void run() {
resetScreenOffGestureDelay();
}
};
private Runnable fpGestureRunnable = new Runnable() {
public void run() {
resetFPGestureDelay();
}
};
public KeyHandler(Context context) {
mContext = context;
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_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(), null);
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 < ar.length; i++) {
out[i] = ar[i];
}
return out;
}
private static ActivityInfo getRunningActivityInfo(Context context) {
final ActivityManager am = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
final PackageManager pm = context.getPackageManager();
List<ActivityManager.RunningTaskInfo> 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 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 static void switchToLastApp(Context context) {
final ActivityManager am =
(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.RunningTaskInfo lastTask = getLastTask(context, am);
if (lastTask != null) {
am.moveTaskToFront(lastTask.id, ActivityManager.MOVE_TASK_NO_USER_ACTION);
}
}
private static ActivityManager.RunningTaskInfo getLastTask(Context context,
final ActivityManager am) {
final String defaultHomePackage = resolveCurrentLauncherPackage(context);
List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(5);
for (int i = 1; i < tasks.size(); i++) {
String packageName = tasks.get(i).topActivity.getPackageName();
if (!packageName.equals(defaultHomePackage)
&& !packageName.equals(context.getPackageName())
&& !packageName.equals("com.android.systemui")) {
return tasks.get(i);
}
}
return null;
}
private static String resolveCurrentLauncherPackage(Context context) {
final Intent launcherIntent = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_HOME);
final PackageManager pm = context.getPackageManager();
final ResolveInfo launcherInfo = pm.resolveActivity(launcherIntent, 0);
return launcherInfo.activityInfo.packageName;
}
private String getRearCameraId() {
if (mRearCameraId == null) {
try {
for (final String cameraId : mCameraManager.getCameraIdList()) {
CameraCharacteristics characteristics =
mCameraManager.getCameraCharacteristics(cameraId);
int cOrientation = characteristics.get(CameraCharacteristics.LENS_FACING);
if (cOrientation == CameraCharacteristics.LENS_FACING_BACK) {
mRearCameraId = cameraId;
break;
}
}
} catch (CameraAccessException e) {
// Ignore
}
}
return mRearCameraId;
}
private Intent getLaunchableIntent(Intent intent) {
PackageManager pm = mContext.getPackageManager();
List<ResolveInfo> 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<ResolveInfo> 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 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 boolean isProximityEnabledOnScreenOffGesturesFP() {
return !FileUtils.readOneLine(getFPNodeBasedOnScreenState(FP_PROXIMITY_CHECK_SCREENOFF_NODE)).equals("0");
}
private boolean isProximityEnabledOnScreenOffGestures() {
return Settings.System.getInt(mContext.getContentResolver(), KEY_GESTURE_ENABLE_PROXIMITY_SENSOR, 1) != 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 KeyEvent 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 event;
}
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 null;
}
if (isFPScanCode){
if (fpGesturePending) {
return event;
} else {
resetFPGestureDelay();
fpGesturePending = true;
mHandler.postDelayed(fpGestureRunnable, 10);
}
}
if (scanCode != FP_TAP_SCANCODE) {
resetDoubleTapOnFP();
}
if (isFPScanCode) {
if ((!isFPGestureEnabled) || (!isScreenOn && !isFPGestureEnabledOnScreenOff)) {
resetDoubleTapOnFP();
return event;
}
if (!isScreenOn && isFPGestureEnabledOnScreenOff) {
processFPScreenOffScancode(scanCode);
} else {
processFPScancode(scanCode);
}
} else if (isScreenOffGesturesScanCode) {
handleScreenOffScancode(scanCode);
}
return null;
}
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, false);
}
}
private void fireFPAction(int action, boolean isDoubleTap) {
ensureKeyguardManager();
boolean isHapticFeedbackEnabledOnFP = isHapticFeedbackEnabledOnFP();
if (isDoubleTap && action != ACTION_CAMERA && action != ACTION_FLASHLIGHT) {
isHapticFeedbackEnabledOnFP = false;
}
if (isHapticFeedbackEnabledOnFP){
if (action == ACTION_CAMERA || action == ACTION_FLASHLIGHT) {
vibrate(action == ACTION_CAMERA ? 500 : 250);
}else if (action != ACTION_VOICE_ASSISTANT) {
doHapticFeedbackFP(false);
}
}
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_LAST_APP:
if (!mKeyguardManager.inKeyguardRestrictedInputMode()) {
switchToLastApp(mContext);
}
break;
}
}
private void vibrate(int intensity) {
if (mVibrator == null) {
return;
}
mVibrator.vibrate(intensity);
}
private void toggleScreenState() {
if (mPowerManager.isScreenOn()) {
mPowerManager.goToSleep(SystemClock.uptimeMillis());
} else {
mPowerManager.wakeUp(SystemClock.uptimeMillis());
}
}
private void triggerVirtualKeypress(final Handler handler, final int keyCode) {
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, 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.postDelayed(new Runnable() {
@Override
public void run() {
im.injectInputEvent(downEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
}
}, 10);
handler.postDelayed(new Runnable() {
@Override
public void run() {
im.injectInputEvent(upEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
}
}, 20);
}
private void fireGoogleNowOnTap() {
doHapticFeedbackFP(true);
mSearchManagerService = ISearchManager.Stub.asInterface(ServiceManager.getService(Context.SEARCH_SERVICE));
if (mSearchManagerService != null) {
try {
mSearchManagerService.launchAssist(new Bundle());
} catch (RemoteException e) {
}
}
}
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 (isProximityEnabledOnScreenOffGesturesFP() && !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);
}
}else{
processFPScancode(scanCode);
}
}
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 void resetFPGestureDelay() {
fpGesturePending = false;
mHandler.removeCallbacks(fpGestureRunnable);
}
private void handleScreenOffScancode(int scanCode) {
if (screenOffGesturePending) {
return;
} else {
resetScreenOffGestureDelay();
screenOffGesturePending = true;
mHandler.postDelayed(screenOffGestureRunnable, 500);
}
if (isProximityEnabledOnScreenOffGestures() && !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);
}
}else{
processScreenOffScancode(scanCode);
}
}
private void processScreenOffScancode(int scanCode) {
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 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 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);
}
if (haptic && action == ACTION_POWER){
doHapticFeedbackScreenOff();
}
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 && action != ACTION_POWER) {
doHapticFeedbackScreenOff();
}
}
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()) {
mHandler.post(new Runnable() {
public void run() {
int owningUid;
String owningPackage;
owningUid = android.os.Process.myUid();
owningPackage = mContext.getOpPackageName();
VibrationEffect effect = VibrationEffect.createOneShot(longpress ? 50 : 40, VibrationEffect.DEFAULT_AMPLITUDE);
mVibrator.vibrate(owningUid, owningPackage, effect, VIBRATION_ATTRIBUTES);
}
});
}
}
private class ScreenOffGesturesHandler extends Handler {
@Override
public void handleMessage(Message msg) {
int scanCode = msg.arg1;
processScreenOffScancode(scanCode);
}
}
private class FPScreenOffGesturesHandler extends Handler {
@Override
public void handleMessage(Message msg) {
processFPScancode(msg.arg1);
}
}
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;
}
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (c) 2015 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.database.Cursor;
import android.database.MatrixCursor;
import android.provider.SearchIndexableResource;
import android.provider.SearchIndexablesProvider;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_CLASS_NAME;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_ICON_RESID;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_ACTION;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RANK;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RESID;
import static android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS;
import static android.provider.SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS;
import static android.provider.SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS;
public class LineageActionsSearchIndexablesProvider extends SearchIndexablesProvider {
private static final String TAG = "LineageActionsSearchIndexablesProvider";
@Override
public boolean onCreate() {
return true;
}
@Override
public Cursor queryXmlResources(String[] projection) {
MatrixCursor cursor = new MatrixCursor(INDEXABLES_XML_RES_COLUMNS);
cursor.addRow(generateResourceRef(new SearchIndexableResource(1, R.xml.actions_panel,
GestureSettingsActivity.class.getName(),
R.drawable.ic_settings_gestures)));
cursor.addRow(generateResourceRef(new SearchIndexableResource(1, R.xml.fp_gesture_panel,
FPGestureSettingsActivity.class.getName(),
R.drawable.ic_settings_fingerprint)));
cursor.addRow(generateResourceRef(new SearchIndexableResource(1, R.xml.fp_gesture_panel_indexable,
FPGestureSettingsActivity.class.getName(),
R.drawable.ic_settings_fingerprint)));
cursor.addRow(generateResourceRef(new SearchIndexableResource(1, R.xml.screen_off_gesture_panel,
ScreenOffGestureSettingsActivity.class.getName(),
R.drawable.ic_settings_screen_off_gestures)));
cursor.addRow(generateResourceRef(new SearchIndexableResource(1, R.xml.screen_off_gesture_panel_indexable,
ScreenOffGestureSettingsActivity.class.getName(),
R.drawable.ic_settings_screen_off_gestures)));
cursor.addRow(generateResourceRef(new SearchIndexableResource(1, R.xml.doze_panel,
DozeSettingsActivity.class.getName(),
R.drawable.ic_settings_doze)));
cursor.addRow(generateResourceRef(new SearchIndexableResource(1, R.xml.doze_panel_indexable,
DozeSettingsActivity.class.getName(),
R.drawable.ic_settings_doze)));
return cursor;
}
private static Object[] generateResourceRef(SearchIndexableResource sir) {
Object[] ref = new Object[7];
ref[COLUMN_INDEX_XML_RES_RANK] = sir.rank;
ref[COLUMN_INDEX_XML_RES_RESID] = sir.xmlResId;
ref[COLUMN_INDEX_XML_RES_CLASS_NAME] = null;
ref[COLUMN_INDEX_XML_RES_ICON_RESID] = sir.iconResId;
ref[COLUMN_INDEX_XML_RES_INTENT_ACTION] = "com.android.settings.action.EXTRA_SETTINGS";
ref[COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE] = "org.lineageos.settings.device";
ref[COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS] = sir.className;
return ref;
}
@Override
public Cursor queryRawData(String[] projection) {
MatrixCursor cursor = new MatrixCursor(INDEXABLES_RAW_COLUMNS);
return cursor;
}
@Override
public Cursor queryNonIndexableKeys(String[] projection) {
MatrixCursor cursor = new MatrixCursor(NON_INDEXABLES_KEYS_COLUMNS);
return cursor;
}
}

View File

@@ -0,0 +1,122 @@
/*
* Copyright (c) 2015 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.IntentService;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.provider.Settings;
import android.util.Log;
import java.util.List;
import java.util.LinkedList;
import org.lineageos.settings.device.actions.UpdatedStateNotifier;
import org.lineageos.settings.device.actions.CameraActivationSensor;
import org.lineageos.settings.device.actions.ChopChopSensor;
import org.lineageos.settings.device.actions.FlipToMute;
import org.lineageos.settings.device.actions.LiftToSilence;
import org.lineageos.settings.device.actions.ProximitySilencer;
import org.lineageos.settings.device.doze.DozePulseAction;
import org.lineageos.settings.device.doze.ProximitySensor;
import org.lineageos.settings.device.doze.ScreenReceiver;
import org.lineageos.settings.device.doze.ScreenStateNotifier;
import org.lineageos.settings.device.doze.StowSensor;
public class LineageActionsService extends IntentService implements ScreenStateNotifier,
UpdatedStateNotifier {
private static final String TAG = "LineageActions";
private final Context mContext;
private final DozePulseAction mDozePulseAction;
private final PowerManager mPowerManager;
private final PowerManager.WakeLock mWakeLock;
private final ScreenReceiver mScreenReceiver;
private final SensorHelper mSensorHelper;
private final List<ScreenStateNotifier> mScreenStateNotifiers = new LinkedList<ScreenStateNotifier>();
private final List<UpdatedStateNotifier> mUpdatedStateNotifiers =
new LinkedList<UpdatedStateNotifier>();
public LineageActionsService(Context context) {
super("LineageActionService");
mContext = context;
Log.d(TAG, "Starting");
LineageActionsSettings lineageActionsSettings = new LineageActionsSettings(context, this);
mSensorHelper = new SensorHelper(context);
mScreenReceiver = new ScreenReceiver(context, this);
mDozePulseAction = new DozePulseAction(context);
mScreenStateNotifiers.add(mDozePulseAction);
// Actionable sensors get screen on/off notifications
mScreenStateNotifiers.add(new ProximitySensor(lineageActionsSettings, mSensorHelper, mDozePulseAction));
mScreenStateNotifiers.add(new StowSensor(lineageActionsSettings, mSensorHelper, mDozePulseAction));
// Other actions that are always enabled
mUpdatedStateNotifiers.add(new CameraActivationSensor(lineageActionsSettings, mSensorHelper));
mUpdatedStateNotifiers.add(new ChopChopSensor(lineageActionsSettings, mSensorHelper));
mUpdatedStateNotifiers.add(new ProximitySilencer(lineageActionsSettings, context, mSensorHelper));
mUpdatedStateNotifiers.add(new FlipToMute(lineageActionsSettings, context, mSensorHelper));
mUpdatedStateNotifiers.add(new LiftToSilence(lineageActionsSettings, context, mSensorHelper));
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "LineageActionsWakeLock");
updateState();
}
@Override
protected void onHandleIntent(Intent intent) {
}
@Override
public void screenTurnedOn() {
if (!mWakeLock.isHeld()) {
mWakeLock.acquire();
}
for (ScreenStateNotifier screenStateNotifier : mScreenStateNotifiers) {
screenStateNotifier.screenTurnedOn();
}
}
@Override
public void screenTurnedOff() {
if (mWakeLock.isHeld()) {
mWakeLock.release();
}
for (ScreenStateNotifier screenStateNotifier : mScreenStateNotifiers) {
screenStateNotifier.screenTurnedOff();
}
}
public void updateState() {
if (mPowerManager.isInteractive()) {
screenTurnedOn();
} else {
screenTurnedOff();
}
for (UpdatedStateNotifier notifier : mUpdatedStateNotifiers) {
notifier.updateState();
}
}
}

View File

@@ -0,0 +1,151 @@
/*
* Copyright (c) 2015 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.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.util.Log;
import org.lineageos.settings.device.actions.Constants;
import org.lineageos.settings.device.actions.UpdatedStateNotifier;
import org.lineageos.settings.device.actions.CameraActivationAction;
import org.lineageos.settings.device.actions.TorchAction;
public class LineageActionsSettings {
private static final String TAG = "LineageActions";
private static final String GESTURE_CAMERA_ACTION_KEY = "gesture_camera_action";
private static final String GESTURE_CHOP_CHOP_KEY = "gesture_chop_chop";
private static final String GESTURE_PICK_UP_KEY = "gesture_pick_up";
private static final String GESTURE_IR_WAKEUP_KEY = "gesture_hand_wave";
private static final String GESTURE_IR_SILENCER_KEY = "gesture_ir_silencer";
private static final String GESTURE_FLIP_TO_MUTE_KEY = "gesture_flip_to_mute";
private static final String GESTURE_LIFT_TO_SILENCE_KEY = "gesture_lift_to_silence";
private final Context mContext;
private final UpdatedStateNotifier mUpdatedStateNotifier;
private boolean mCameraGestureEnabled;
private boolean mChopChopEnabled;
private boolean mPickUpGestureEnabled;
private boolean mIrWakeUpEnabled;
private boolean mIrSilencerEnabled;
private boolean mFlipToMuteEnabled;
private boolean mLiftToSilenceEnabled;
public LineageActionsSettings(Context context, UpdatedStateNotifier updatedStateNotifier) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
loadPreferences(sharedPrefs);
sharedPrefs.registerOnSharedPreferenceChangeListener(mPrefListener);
mContext = context;
mUpdatedStateNotifier = updatedStateNotifier;
}
public boolean isCameraGestureEnabled() {
return mCameraGestureEnabled;
}
public boolean isChopChopGestureEnabled() {
return mChopChopEnabled;
}
public static boolean isDozeEnabled(ContentResolver contentResolver) {
return (Settings.Secure.getInt(contentResolver, Settings.Secure.DOZE_ENABLED, 1) != 0);
}
public boolean isDozeEnabled() {
return isDozeEnabled(mContext.getContentResolver());
}
public boolean isIrWakeupEnabled() {
return isDozeEnabled() && mIrWakeUpEnabled;
}
public boolean isPickUpEnabled() {
return isDozeEnabled() && mPickUpGestureEnabled;
}
public boolean isIrSilencerEnabled() {
return mIrSilencerEnabled;
}
public boolean isFlipToMuteEnabled() {
return mFlipToMuteEnabled;
}
public boolean isLiftToSilenceEnabled() {
return mLiftToSilenceEnabled;
}
public void cameraAction() {
new CameraActivationAction(mContext).action();
}
public void chopChopAction() {
new TorchAction(mContext).action();
}
private void loadPreferences(SharedPreferences sharedPreferences) {
mCameraGestureEnabled = sharedPreferences.getBoolean(GESTURE_CAMERA_ACTION_KEY, true);
mChopChopEnabled = sharedPreferences.getBoolean(GESTURE_CHOP_CHOP_KEY, true);
mIrWakeUpEnabled = sharedPreferences.getBoolean(GESTURE_IR_WAKEUP_KEY, true);
mPickUpGestureEnabled = sharedPreferences.getBoolean(GESTURE_PICK_UP_KEY, true);
mIrSilencerEnabled = sharedPreferences.getBoolean(GESTURE_IR_SILENCER_KEY, false);
mFlipToMuteEnabled = sharedPreferences.getBoolean(GESTURE_FLIP_TO_MUTE_KEY, false);
mLiftToSilenceEnabled = sharedPreferences.getBoolean(GESTURE_LIFT_TO_SILENCE_KEY, false);
}
private SharedPreferences.OnSharedPreferenceChangeListener mPrefListener =
new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
boolean updated = true;
if (GESTURE_CAMERA_ACTION_KEY.equals(key)) {
mCameraGestureEnabled = sharedPreferences.getBoolean(GESTURE_CAMERA_ACTION_KEY, true);
} else if (GESTURE_CHOP_CHOP_KEY.equals(key)) {
mChopChopEnabled = sharedPreferences.getBoolean(GESTURE_CHOP_CHOP_KEY, true);
} else if (GESTURE_IR_WAKEUP_KEY.equals(key)) {
mIrWakeUpEnabled = sharedPreferences.getBoolean(GESTURE_IR_WAKEUP_KEY, true);
} else if (GESTURE_PICK_UP_KEY.equals(key)) {
mPickUpGestureEnabled = sharedPreferences.getBoolean(GESTURE_PICK_UP_KEY, true);
} else if (GESTURE_IR_SILENCER_KEY.equals(key)) {
mIrSilencerEnabled = sharedPreferences.getBoolean(GESTURE_IR_SILENCER_KEY, false);
} else if (GESTURE_FLIP_TO_MUTE_KEY.equals(key)) {
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_HOME_KEY_OFF.equals(key) || Constants.FP_HAPTIC_SCREENOFF_KEY.equals(key) ||Constants.FP_PROXIMITY_CHECK_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 {
updated = false;
}
if (updated) {
mUpdatedStateNotifier.updateState();
}
}
};
}

View File

@@ -0,0 +1,32 @@
/*
* 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.preference.PreferenceActivity;
public class ScreenOffGestureSettingsActivity extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null){
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new ScreenOffGestureSettingsFragment()).commit();
}
}
}

View File

@@ -0,0 +1,79 @@
/*
* 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.support.v7.preference.Preference;
import android.support.v14.preference.SwitchPreference;
import android.support.v14.preference.PreferenceFragment;
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;
import static org.lineageos.settings.device.actions.Constants.KEY_GESTURE_ENABLE_PROXIMITY_SENSOR;
public class ScreenOffGestureSettingsFragment extends PreferenceFragment {
private SwitchPreference mTapToWake;
private SwitchPreference mHapticFeedback;
private SwitchPreference mProximitySensor;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.screen_off_gesture_panel);
mTapToWake = (SwitchPreference) findPreference("tap_to_wake");
mTapToWake.setChecked(Settings.Secure.getInt(getActivity().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(getActivity().getContentResolver(), DOUBLE_TAP_TO_WAKE, value ? 1 : 0);
return true;
}
});
mHapticFeedback = (SwitchPreference) findPreference("haptic_feedback");
mHapticFeedback.setChecked(Settings.System.getInt(getActivity().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(getActivity().getContentResolver(), KEY_GESTURE_ENABLE_HAPTIC_FEEDBACK, value ? 1 : 0);
return true;
}
});
mProximitySensor = (SwitchPreference) findPreference("proximity_sensor");
mProximitySensor.setChecked(Settings.System.getInt(getActivity().getContentResolver(), KEY_GESTURE_ENABLE_PROXIMITY_SENSOR, 1) == 1);
mProximitySensor.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object objValue) {
boolean value = (Boolean) objValue;
Settings.System.putInt(getActivity().getContentResolver(), KEY_GESTURE_ENABLE_PROXIMITY_SENSOR, value ? 1 : 0);
return true;
}
});
}
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright (c) 2015 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;
public interface SensorAction {
public void action();
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2015 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 java.util.List;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.TriggerEventListener;
import android.util.Log;
public class SensorHelper {
private static final String TAG = "LineageActions";
private static final int SENSOR_TYPE_MMI_CAMERA_ACTIVATION = 65540;
private static final int SENSOR_TYPE_MMI_CHOP_CHOP = 65546;
private static final int SENSOR_TYPE_MMI_FLAT_UP = 65537;
private static final int SENSOR_TYPE_MMI_FLAT_DOWN = 65538;
private static final int SENSOR_TYPE_MMI_STOW = 65539;
private static final int BATCH_LATENCY_IN_MS = 100;
private final Context mContext;
private final SensorManager mSensorManager;
public SensorHelper(Context context) {
mContext = context;
mSensorManager = (SensorManager) mContext .getSystemService(Context.SENSOR_SERVICE);
dumpSensorsList();
}
private void dumpSensorsList() {
try {
FileOutputStream out = mContext.openFileOutput("sensors.txt", Context.MODE_PRIVATE);
OutputStreamWriter writer = new OutputStreamWriter(out);
List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
for (Sensor sensor : sensorList) {
writer.write("sensor " + sensor.getType() + " = " + sensor.getName()
+ " max batch: " + sensor.getFifoMaxEventCount() + " isWakeUp: " + sensor.isWakeUpSensor() + "\n");
}
writer.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public Sensor getCameraActivationSensor() {
return mSensorManager.getDefaultSensor(SENSOR_TYPE_MMI_CAMERA_ACTIVATION, true);
}
public Sensor getChopChopSensor() {
return mSensorManager.getDefaultSensor(SENSOR_TYPE_MMI_CHOP_CHOP, true);
}
public Sensor getFlatUpSensor() {
return mSensorManager.getDefaultSensor(SENSOR_TYPE_MMI_FLAT_UP, true);
}
public Sensor getFlatDownSensor() {
return mSensorManager.getDefaultSensor(SENSOR_TYPE_MMI_FLAT_DOWN, true);
}
public Sensor getProximitySensor() {
return mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY, true);
}
public Sensor getStowSensor() {
return mSensorManager.getDefaultSensor(SENSOR_TYPE_MMI_STOW, true);
}
public void registerListener(Sensor sensor, SensorEventListener listener) {
if (!mSensorManager.registerListener(listener, sensor,
SensorManager.SENSOR_DELAY_NORMAL, BATCH_LATENCY_IN_MS * 1000)) {
throw new RuntimeException("Failed to registerListener for sensor " + sensor);
}
}
public void unregisterListener(SensorEventListener listener) {
mSensorManager.unregisterListener(listener);
}
/* TriggerSensor */
public void requestTriggerSensor(Sensor sensor, TriggerEventListener listener) {
if (!mSensorManager.requestTriggerSensor(listener, sensor)) {
throw new RuntimeException("Failed to requestTriggerSensor for sensor " + sensor);
}
}
public void cancelTriggerSensor(Sensor sensor, TriggerEventListener listener) {
mSensorManager.cancelTriggerSensor(listener, sensor);
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 2015 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.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 = "LineageActions-ServiceWrapper";
private final IBinder mBinder = new LocalBinder();
private LineageActionsService mLineageActionsService;
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();
mLineageActionsService = new LineageActionsService(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() {
}
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright (c) 2015 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.actions;
import java.util.List;
import android.app.KeyguardManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.Vibrator;
import android.provider.MediaStore;
import android.util.Log;
import org.lineageos.settings.device.SensorAction;
public class CameraActivationAction implements SensorAction {
private static final String TAG = "LineageActions";
private static final int TURN_SCREEN_ON_WAKE_LOCK_MS = 500;
private final Context mContext;
private final KeyguardManager mKeyguardManager;
private final PackageManager mPackageManager;
private final PowerManager mPowerManager;
public CameraActivationAction(Context context) {
mContext = context;
mKeyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mPackageManager = context.getPackageManager();
}
@Override
public void action() {
vibrate();
turnScreenOn();
if (mKeyguardManager.inKeyguardRestrictedInputMode()) {
launchSecureCamera();
} else {
launchCamera();
}
}
private void vibrate() {
Vibrator v = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(500);
}
private void turnScreenOn() {
PowerManager.WakeLock wl = mPowerManager.newWakeLock(
PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, TAG);
wl.acquire(TURN_SCREEN_ON_WAKE_LOCK_MS);
}
private void launchCamera() {
Intent intent = createIntent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
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 = createIntent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
Intent secureIntent = createIntent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
ActivityInfo normalActivity = getBestActivityInfo(normalIntent);
ActivityInfo secureActivity = getBestActivityInfo(secureIntent, normalActivity);
if (secureActivity != null) {
secureIntent.setComponent(componentName(secureActivity));
mContext.startActivity(secureIntent);
}
}
private Intent createIntent(String intentName) {
Intent intent = new Intent(intentName);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_FROM_BACKGROUND);
return intent;
}
private ActivityInfo getBestActivityInfo(Intent intent) {
ResolveInfo resolveInfo = mPackageManager.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) {
List <ResolveInfo> activities = mPackageManager.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 ComponentName componentName(ActivityInfo activity) {
return new ComponentName(activity.applicationInfo.packageName, activity.name);
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 2015 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.actions;
import java.util.List;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
import org.lineageos.settings.device.LineageActionsSettings;
import org.lineageos.settings.device.SensorHelper;
public class CameraActivationSensor implements SensorEventListener, UpdatedStateNotifier {
private static final String TAG = "LineageActions-CameraSensor";
private static final int TURN_SCREEN_ON_WAKE_LOCK_MS = 500;
private final LineageActionsSettings mLineageActionsSettings;
private final SensorHelper mSensorHelper;
private final Sensor mSensor;
private boolean mIsEnabled;
public CameraActivationSensor(LineageActionsSettings lineageActionsSettings, SensorHelper sensorHelper) {
mLineageActionsSettings = lineageActionsSettings;
mSensorHelper = sensorHelper;
mSensor = sensorHelper.getCameraActivationSensor();
mSensorHelper.registerListener(mSensor, this);
}
@Override
public synchronized void updateState() {
if (mLineageActionsSettings.isCameraGestureEnabled() && !mIsEnabled) {
Log.d(TAG, "Enabling");
mIsEnabled = true;
} else if (! mLineageActionsSettings.isCameraGestureEnabled() && mIsEnabled) {
Log.d(TAG, "Disabling");
mIsEnabled = false;
}
}
@Override
public void onSensorChanged(SensorEvent event) {
Log.d(TAG, "activate camera");
if (mIsEnabled) mLineageActionsSettings.cameraAction();
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 2015-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.actions;
import java.util.List;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
import org.lineageos.settings.device.LineageActionsSettings;
import org.lineageos.settings.device.SensorHelper;
public class ChopChopSensor implements SensorEventListener, UpdatedStateNotifier {
private static final String TAG = "LineageActions-ChopChopSensor";
private static final int TURN_SCREEN_ON_WAKE_LOCK_MS = 500;
private final LineageActionsSettings mLineageActionsSettings;
private final SensorHelper mSensorHelper;
private final Sensor mSensor;
private final Sensor mProx;
private boolean mIsEnabled;
private boolean mProxIsCovered;
public ChopChopSensor(LineageActionsSettings lineageActionsSettings, SensorHelper sensorHelper) {
mLineageActionsSettings = lineageActionsSettings;
mSensorHelper = sensorHelper;
mSensor = sensorHelper.getChopChopSensor();
mProx = sensorHelper.getProximitySensor();
}
@Override
public synchronized void updateState() {
if (mLineageActionsSettings.isChopChopGestureEnabled() && !mIsEnabled) {
Log.d(TAG, "Enabling");
mSensorHelper.registerListener(mSensor, this);
mSensorHelper.registerListener(mProx, mProxListener);
mIsEnabled = true;
} else if (! mLineageActionsSettings.isChopChopGestureEnabled() && mIsEnabled) {
Log.d(TAG, "Disabling");
mSensorHelper.unregisterListener(this);
mSensorHelper.unregisterListener(mProxListener);
mIsEnabled = false;
}
}
@Override
public void onSensorChanged(SensorEvent event) {
Log.d(TAG, "chop chop triggered");
if (mProxIsCovered) {
Log.d(TAG, "proximity sensor covered, ignoring chop-chop");
return;
}
mLineageActionsSettings.chopChopAction();
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
private SensorEventListener mProxListener = new SensorEventListener() {
@Override
public synchronized void onSensorChanged(SensorEvent event) {
mProxIsCovered = event.values[0] < mProx.getMaximumRange();
}
@Override
public void onAccuracyChanged(Sensor mSensor, int accuracy) {
}
};
}

View File

@@ -0,0 +1,278 @@
/*
* 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.actions;
import java.util.HashMap;
import java.util.Map;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
import org.lineageos.settings.device.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_LAST_APP = 121;
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_LAST_APP
};
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";
// Swap nodes
public static final String FP_HOME_NODE = "/sys/homebutton/enable";
public static final String FP_HOME_OFF_NODE = "/sys/homebutton/enable_off";
// 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";
// Proximity check node
public static final String FP_PROXIMITY_CHECK_SCREENOFF_NODE = "/sys/homebutton/proximity_check_off";
public static final String FP_PROXIMITY_CHECK_SCREENOFF_KEY = "fp_proximity_check_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";
public static final String KEY_GESTURE_ENABLE_PROXIMITY_SENSOR = "screen_off_gesture_proximity_sensor";
// Holds <preference_key> -> <proc_node> mapping
public static final Map<String, String> sBooleanNodePreferenceMap = new HashMap<>();
// Holds <preference_key> -> <default_values> mapping
public static final Map<String, Object> sNodeDefaultMap = new HashMap<>();
public static final String[] sPrefKeys = {
FP_HOME_KEY,
FP_HOME_KEY_OFF,
FP_HAPTIC_KEY,
FP_HAPTIC_SCREENOFF_KEY,
FP_PROXIMITY_CHECK_SCREENOFF_KEY,
FP_KEYS,
FP_KEY_DBLTAP,
FP_KEY_HOLD,
FP_KEY_RIGHT,
FP_KEY_LEFT,
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_PROXIMITY_CHECK_SCREENOFF_KEY, FP_PROXIMITY_CHECK_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_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_PROXIMITY_CHECK_SCREENOFF_KEY, true);
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(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) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getBoolean(key, (Boolean) sNodeDefaultMap.get(key));
}
public static String GetPreference(Context context, String key) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString(key, (String) sNodeDefaultMap.get(key));
}
public static void writePreference(Context context, String pref) {
String value = "1";
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);
String node = sBooleanNodePreferenceMap.get(pref);
if (!FileUtils.writeLine(node, value)) {
Log.w(TAG, "Write " + value + " to node " + node +
"failed while restoring saved preference values");
}
}
}

View File

@@ -0,0 +1,127 @@
/*
* 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.actions;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.util.Log;
import org.lineageos.settings.device.LineageActionsSettings;
import org.lineageos.settings.device.SensorHelper;
public class FlipToMute implements UpdatedStateNotifier {
private static final String TAG = "LineageActions-FlipToMute";
private final NotificationManager mNotificationManager;
private final LineageActionsSettings mLineageActionsSettings;
private final SensorHelper mSensorHelper;
private final Sensor mFlatDown;
private final Sensor mStow;
private boolean mIsEnabled;
private boolean mIsFlatDown;
private boolean mIsStowed;
private int mFilter;
private Context mContext;
private Receiver mReceiver;
public FlipToMute(LineageActionsSettings lineageActionsSettings, Context context,
SensorHelper sensorHelper) {
mLineageActionsSettings = lineageActionsSettings;
mContext = context;
mSensorHelper = sensorHelper;
mFlatDown = sensorHelper.getFlatDownSensor();
mStow = sensorHelper.getStowSensor();
mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mFilter = mNotificationManager.getCurrentInterruptionFilter();
mReceiver = new Receiver();
}
@Override
public void updateState() {
if (mLineageActionsSettings.isFlipToMuteEnabled() && !mIsEnabled) {
Log.d(TAG, "Enabling");
mSensorHelper.registerListener(mFlatDown, mFlatDownListener);
mSensorHelper.registerListener(mStow, mStowListener);
mContext.registerReceiver(mReceiver,
new IntentFilter(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED));
mIsEnabled = true;
} else if (!mLineageActionsSettings.isFlipToMuteEnabled() && mIsEnabled) {
Log.d(TAG, "Disabling");
mSensorHelper.unregisterListener(mFlatDownListener);
mSensorHelper.unregisterListener(mStowListener);
mContext.unregisterReceiver(mReceiver);
mIsEnabled = false;
}
}
private SensorEventListener mFlatDownListener = new SensorEventListener() {
@Override
public synchronized void onSensorChanged(SensorEvent event) {
mIsFlatDown = (event.values[0] != 0);
sensorChange();
}
@Override
public void onAccuracyChanged(Sensor mSensor, int accuracy) {
}
};
private SensorEventListener mStowListener = new SensorEventListener() {
@Override
public synchronized void onSensorChanged(SensorEvent event) {
mIsStowed = (event.values[0] != 0);
sensorChange();
}
@Override
public void onAccuracyChanged(Sensor mSensor, int accuracy) {
}
};
private void sensorChange() {
Log.d(TAG, "event: " + mIsFlatDown + " mIsStowed=" + mIsStowed);
if (mIsFlatDown && mIsStowed) {
mNotificationManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);
Log.d(TAG, "Interrupt filter: Allow priority");
} else if (!mIsFlatDown) {
mNotificationManager.setInterruptionFilter(mFilter);
Log.d(TAG, "Interrupt filter: Restore");
}
}
public class Receiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (!mIsFlatDown && !mIsStowed) {
mFilter = mNotificationManager.getCurrentInterruptionFilter();
Log.d(TAG, "Interrupt filter: Backup");
}
}
}
}

View File

@@ -0,0 +1,109 @@
/*
* 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.actions;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.telephony.PhoneStateListener;
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import org.lineageos.settings.device.LineageActionsSettings;
import org.lineageos.settings.device.SensorHelper;
public class LiftToSilence extends PhoneStateListener implements SensorEventListener, UpdatedStateNotifier {
private static final String TAG = "LineageActions-LiftToSilence";
private final LineageActionsSettings mLineageActionsSettings;
private final SensorHelper mSensorHelper;
private final Sensor mFlatUpSensor;
private final Sensor mStowSensor;
private final TelecomManager mTelecomManager;
private final TelephonyManager mTelephonyManager;
private boolean mIsRinging;
private boolean mIsStowed;
private boolean mLastFlatUp;
public LiftToSilence(LineageActionsSettings lineageActionsSettings, Context context,
SensorHelper sensorHelper) {
mLineageActionsSettings = lineageActionsSettings;
mSensorHelper = sensorHelper;
mFlatUpSensor = sensorHelper.getFlatUpSensor();
mStowSensor = sensorHelper.getStowSensor();
mTelecomManager = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
}
@Override
public void updateState() {
if (mLineageActionsSettings.isLiftToSilenceEnabled()) {
mTelephonyManager.listen(this, LISTEN_CALL_STATE);
} else {
mTelephonyManager.listen(this, 0);
}
}
@Override
public synchronized void onCallStateChanged(int state, String incomingNumber) {
if (state == TelephonyManager.CALL_STATE_RINGING && !mIsRinging) {
Log.d(TAG, "Ringing started");
mSensorHelper.registerListener(mFlatUpSensor, this);
mSensorHelper.registerListener(mStowSensor, mStowListener);
mIsRinging = true;
} else if (state != TelephonyManager.CALL_STATE_RINGING && mIsRinging) {
Log.d(TAG, "Ringing stopped");
mSensorHelper.unregisterListener(this);
mSensorHelper.unregisterListener(mStowListener);
mIsRinging = false;
}
}
@Override
public synchronized void onSensorChanged(SensorEvent event) {
boolean thisFlatUp = (event.values[0] != 0);
Log.d(TAG, "event: " + thisFlatUp + " mLastFlatUp=" + mLastFlatUp + " mIsStowed=" +
mIsStowed);
if (mLastFlatUp && !thisFlatUp && !mIsStowed) {
mTelecomManager.silenceRinger();
}
mLastFlatUp = thisFlatUp;
}
@Override
public void onAccuracyChanged(Sensor mSensor, int accuracy) {
}
private SensorEventListener mStowListener = new SensorEventListener() {
@Override
public synchronized void onSensorChanged(SensorEvent event) {
mIsStowed = (event.values[0] != 0);
}
@Override
public void onAccuracyChanged(Sensor mSensor, int accuracy) {
}
};
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2015 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.actions;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.telephony.PhoneStateListener;
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import org.lineageos.settings.device.LineageActionsSettings;
import org.lineageos.settings.device.SensorHelper;
import static android.telephony.TelephonyManager.*;
public class ProximitySilencer extends PhoneStateListener implements SensorEventListener, UpdatedStateNotifier {
private static final String TAG = "LineageActions-ProximitySilencer";
private static final int SILENCE_DELAY_MS = 500;
private final TelecomManager mTelecomManager;
private final TelephonyManager mTelephonyManager;
private final LineageActionsSettings mLineageActionsSettings;
private final SensorHelper mSensorHelper;
private final Sensor mSensor;
private boolean mIsRinging;
private long mRingStartedMs;
private boolean mCoveredRinging;
public ProximitySilencer(LineageActionsSettings lineageActionsSettings, Context context,
SensorHelper sensorHelper) {
mTelecomManager = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
mLineageActionsSettings = lineageActionsSettings;
mSensorHelper = sensorHelper;
mSensor = sensorHelper.getProximitySensor();
mCoveredRinging = false;
mIsRinging = false;
}
@Override
public void updateState() {
if (mLineageActionsSettings.isIrSilencerEnabled()) {
mTelephonyManager.listen(this, LISTEN_CALL_STATE);
} else {
mTelephonyManager.listen(this, 0);
}
}
@Override
public synchronized void onSensorChanged(SensorEvent event) {
boolean isNear = event.values[0] < mSensor.getMaximumRange();
long now = System.currentTimeMillis();
if (isNear){
if (mIsRinging && (now - mRingStartedMs >= SILENCE_DELAY_MS)){
mCoveredRinging = true;
} else {
mCoveredRinging = false;
}
return;
}
if (!isNear && mIsRinging) {
Log.d(TAG, "event: " + event.values[0] + ", " + " covered " + Boolean.toString(mCoveredRinging));
if (mCoveredRinging) {
Log.d(TAG, "Silencing ringer");
mTelecomManager.silenceRinger();
} else {
Log.d(TAG, "Ignoring silence gesture: " + now + " is too close to " +
mRingStartedMs + ", delay=" + SILENCE_DELAY_MS + " or covered " + Boolean.toString(mCoveredRinging));
}
mCoveredRinging = false;
}
}
@Override
public synchronized void onCallStateChanged(int state, String incomingNumber) {
if (state == CALL_STATE_RINGING && !mIsRinging) {
Log.d(TAG, "Ringing started");
mSensorHelper.registerListener(mSensor, this);
mIsRinging = true;
mRingStartedMs = System.currentTimeMillis();
} else if (state != CALL_STATE_RINGING && mIsRinging) {
Log.d(TAG, "Ringing stopped");
mSensorHelper.unregisterListener(this);
mIsRinging = false;
}
}
@Override
public void onAccuracyChanged(Sensor mSensor, int accuracy) {
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (c) 2015 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.actions;
import android.content.Context;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraAccessException;
import android.os.Vibrator;
import android.util.Log;
import org.lineageos.settings.device.SensorAction;
public class TorchAction implements SensorAction {
private static final String TAG = "LineageActions";
private static final int TURN_SCREEN_ON_WAKE_LOCK_MS = 500;
private CameraManager mCameraManager;
private final Vibrator mVibrator;
private String mRearCameraId;
private static boolean mTorchEnabled;
public TorchAction(Context mContext) {
mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
mCameraManager.registerTorchCallback(new MyTorchCallback(), null);
mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
try {
for (final String cameraId : mCameraManager.getCameraIdList()) {
CameraCharacteristics characteristics =
mCameraManager.getCameraCharacteristics(cameraId);
int cOrientation = characteristics.get(CameraCharacteristics.LENS_FACING);
if (cOrientation == CameraCharacteristics.LENS_FACING_BACK) {
mRearCameraId = cameraId;
break;
}
}
} catch (CameraAccessException e) {
}
}
@Override
public void action() {
mVibrator.vibrate(250);
if (mRearCameraId != null) {
try {
mCameraManager.setTorchMode(mRearCameraId, !mTorchEnabled);
mTorchEnabled = !mTorchEnabled;
} catch (CameraAccessException e) {
}
}
}
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;
}
}
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright (c) 2015 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.actions;
public interface UpdatedStateNotifier {
public void updateState();
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 2015 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.doze;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import org.lineageos.settings.device.SensorAction;
public class DozePulseAction implements SensorAction, ScreenStateNotifier {
private static final String TAG = "LineageActions";
private static final int DELAY_BETWEEN_DOZES_IN_MS = 1500;
private final Context mContext;
private long mLastDoze;
public DozePulseAction(Context context) {
mContext = context;
}
@Override
public void screenTurnedOn() {
}
@Override
public void screenTurnedOff() {
mLastDoze = System.currentTimeMillis();
}
public void action() {
if (mayDoze()) {
Log.d(TAG, "Sending doze.pulse intent");
mContext.sendBroadcast(new Intent("com.android.systemui.doze.pulse"));
}
}
public synchronized boolean mayDoze() {
long now = System.currentTimeMillis();
if (now - mLastDoze > DELAY_BETWEEN_DOZES_IN_MS) {
Log.d(TAG, "Allowing doze");
mLastDoze = now;
return true;
} else {
Log.d(TAG, "Denying doze");
return false;
}
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 2015 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.doze;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.util.Log;
import org.lineageos.settings.device.LineageActionsSettings;
import org.lineageos.settings.device.SensorAction;
import org.lineageos.settings.device.SensorHelper;
public class ProximitySensor implements ScreenStateNotifier, SensorEventListener {
private static final String TAG = "LineageActions-ProximitySensor";
private final LineageActionsSettings mLineageActionsSettings;
private final SensorHelper mSensorHelper;
private final SensorAction mSensorAction;
private final Sensor mSensor;
private boolean mEnabled;
private boolean mSawNear = false;
public ProximitySensor(LineageActionsSettings lineageActionsSettings, SensorHelper sensorHelper,
SensorAction action) {
mLineageActionsSettings = lineageActionsSettings;
mSensorHelper = sensorHelper;
mSensorAction = action;
mSensor = sensorHelper.getProximitySensor();
}
@Override
public void screenTurnedOn() {
if (mEnabled) {
Log.d(TAG, "Disabling");
mSensorHelper.unregisterListener(this);
mEnabled = false;
}
}
@Override
public void screenTurnedOff() {
if (mLineageActionsSettings.isIrWakeupEnabled() && !mEnabled) {
Log.d(TAG, "Enabling");
mSensorHelper.registerListener(mSensor, this);
mEnabled = true;
}
}
@Override
public void onSensorChanged(SensorEvent event) {
boolean isNear = event.values[0] < mSensor.getMaximumRange();
if (mSawNear && !isNear) {
Log.d(TAG, "wave triggered");
mSensorAction.action();
}
mSawNear = isNear;
}
@Override
public void onAccuracyChanged(Sensor mSensor, int accuracy) {
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2015 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.doze;
import java.util.List;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import org.lineageos.settings.device.actions.Constants;
public class ScreenReceiver extends BroadcastReceiver {
private final ScreenStateNotifier mNotifier;
public ScreenReceiver(Context context, ScreenStateNotifier notifier) {
mNotifier = notifier;
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
context.registerReceiver(this, filter);
}
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
mNotifier.screenTurnedOff();
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
mNotifier.screenTurnedOn();
}
}
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright (c) 2015 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.doze;
public interface ScreenStateNotifier {
public void screenTurnedOn();
public void screenTurnedOff();
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 2015 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.doze;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.util.Log;
import java.lang.System;
import org.lineageos.settings.device.LineageActionsSettings;
import org.lineageos.settings.device.SensorAction;
import org.lineageos.settings.device.SensorHelper;
public class StowSensor implements ScreenStateNotifier, SensorEventListener {
private static final String TAG = "LineageActions-StowSensor";
private static final int IN_POCKET_MIN_TIME = 5000;
private final LineageActionsSettings mLineageActionsSettings;
private final SensorHelper mSensorHelper;
private final SensorAction mSensorAction;
private final Sensor mSensor;
private boolean mEnabled;
private boolean mLastStowed;
private long isStowedTime;
public StowSensor(LineageActionsSettings lineageActionsSettings, SensorHelper sensorHelper,
SensorAction action) {
mLineageActionsSettings = lineageActionsSettings;
mSensorHelper = sensorHelper;
mSensorAction = action;
mSensor = sensorHelper.getStowSensor();
}
@Override
public void screenTurnedOn() {
if (mEnabled) {
Log.d(TAG, "Disabling");
mSensorHelper.unregisterListener(this);
mEnabled = false;
}
}
@Override
public void screenTurnedOff() {
if (!mLineageActionsSettings.isIrWakeupEnabled() &&
mLineageActionsSettings.isPickUpEnabled() && !mEnabled) {
Log.d(TAG, "Enabling");
mSensorHelper.registerListener(mSensor, this);
mEnabled = true;
}
}
@Override
public void onSensorChanged(SensorEvent event) {
boolean thisStowed = (event.values[0] != 0);
if(thisStowed){
isStowedTime = System.currentTimeMillis();
} else if (mLastStowed && !thisStowed) {
long inPocketTime = System.currentTimeMillis() - isStowedTime;
if(inPocketTime >= IN_POCKET_MIN_TIME){
Log.d(TAG, "Triggered after " + inPocketTime / 1000 + " seconds");
mSensorAction.action();
}
}
mLastStowed = thisStowed;
Log.d(TAG, "event: " + thisStowed);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}

View File

@@ -0,0 +1,125 @@
/*
* 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.util;
import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
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.
* Reference {@link BufferedReader#readLine()} for clarification on what a line is
*
* @return the read line contents, or null on failure
*/
public static String readOneLine(String fileName) {
String line = "0";
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(fileName), 512);
line = reader.readLine();
} catch (FileNotFoundException e) {
Log.w(TAG, "No such file " + fileName + " for reading", e);
} 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) {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(fileName));
writer.write(value);
} catch (FileNotFoundException e) {
Log.w(TAG, "No such file " + fileName + " for writing", e);
return false;
} catch (IOException e) {
Log.e(TAG, "Could not write to file " + fileName, e);
return false;
} finally {
try {
if (writer != null) {
writer.close();
}
} catch (IOException e) {
// Ignored, not much we can do anyway
}
}
return true;
}
/**
* Checks whether the given file exists
*
* @return true if exists, false if not
*/
public static boolean fileExists(String fileName) {
final File file = new File(fileName);
return file.exists();
}
/**
* Checks whether the given file is readable
*
* @return true if readable, false if not
*/
public static boolean isFileReadable(String fileName) {
final File file = new File(fileName);
return file.exists() && file.canRead();
}
/**
* Checks whether the given file is writable
*
* @return true if writable, false if not
*/
public static boolean isFileWritable(String fileName) {
final File file = new File(fileName);
return file.exists() && file.canWrite();
}
}