potter: add back CMActions

Change-Id: Ib3ab414d6684c2ced1a3c998e3d3933f3334b2d0
This commit is contained in:
Vachounet
2017-09-08 13:44:46 +02:00
parent 7bce7ed232
commit 001ef83dbd
34 changed files with 2519 additions and 0 deletions

40
cmactions/Android.mk Normal file
View File

@@ -0,0 +1,40 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := CMActions
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-v14-preference \
android-support-v7-appcompat \
android-support-v7-preference \
android-support-v7-recyclerview
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
LOCAL_RESOURCE_DIR := \
$(LOCAL_PATH)/res \
$(LOCAL_PATH)/../../../../packages/resources/devicesettings/res \
frameworks/support/v14/preference/res \
frameworks/support/v7/appcompat/res \
frameworks/support/v7/preference/res \
frameworks/support/v7/recyclerview/res
LOCAL_AAPT_FLAGS := --auto-add-overlay \
--extra-packages android.support.v14.preference:android.support.v7.appcompat:android.support.v7.preference:android.support.v7.recyclerview
ifneq ($(INCREMENTAL_BUILDS),)
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_JACK_ENABLED := incremental
endif
include frameworks/base/packages/SettingsLib/common.mk
include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cyanogenmod.settings.device"
android:sharedUserId="android.uid.system"
>
<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" />
<protected-broadcast android:name="com.android.systemui.doze.pulse" />
<application
android:allowBackup="true"
android:label="@string/device_settings_app_name"
android:persistent="true">
<receiver android:name="com.cyanogenmod.settings.device.BootCompletedReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service android:name="ServiceWrapper" android:permission="ServiceWrapper">
<intent-filter>
<action android:name="ServiceWrapper"/>
</intent-filter>
</service>
<activity
android:name=".DozePreferenceActivity"
android:label="@string/ambient_display_title"
android:theme="@style/CMActions">
<intent-filter>
<action android:name="org.cyanogenmod.settings.device.DOZE_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".TouchscreenGesturePreferenceActivity"
android:label="@string/moto_actions_title"
android:summary="@string/moto_actions_summary"
android:theme="@style/CMActions">
<intent-filter>
<action android:name="com.android.settings.action.EXTRA_SETTINGS" />
</intent-filter>
<meta-data
android:name="com.android.settings.category"
android:value="com.android.settings.category.device" />
<meta-data
android:name="com.android.settings.icon"
android:resource="@drawable/ic_settings_gestures" />
</activity>
</application>
</manifest>

9
cmactions/proguard.flags Normal file
View File

@@ -0,0 +1,9 @@
-keep class org.cyanogenmod.CMActions.* {
*;
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keep class ** extends android.support.v14.preference.PreferenceFragment

View File

@@ -0,0 +1,32 @@
<?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="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M4.7,6.9c0.7-0.7,1.4-1.4,1.7-1.2c0.5,0.2,0,1-0.3,1.5c-0.2,0.4-2.8,3.9-2.8,6.3c0,1.3,0.5,2.3,1.3,3
c0.7,0.6,1.7,0.7,2.6,0.5c1.1-0.3,1.9-1.4,3-2.8c1.2-1.5,2.8-3.4,4-3.4c1.6,0,1.6,1,1.7,1.8c-3.7,0.6-5.3,3.7-5.3,5.4
s1.4,3.1,3.2,3.1c1.6,0,4.3-1.3,4.6-6.1H21v-2.5h-2.4c-0.1-1.7-1.1-4.2-4-4.2c-2.2,0-4.1,1.9-4.9,2.8c-0.6,0.7-2,2.5-2.3,2.7
c-0.2,0.3-0.7,0.8-1.1,0.8c-0.4,0-0.7-0.8-0.4-1.9c0.3-1.1,1.4-2.9,1.8-3.5C8.5,8,9.1,7.2,9.1,5.9C9.1,3.7,7.4,3,6.6,3
C5.3,3,4.1,4,3.9,4.3C3.5,4.6,3.2,4.9,3,5.2L4.7,6.9z
M13.9,18.6c-0.3,0-0.7-0.3-0.7-0.7c0-0.6,0.7-2.2,2.8-2.8
C15.8,17.8,14.6,18.6,13.9,18.6z" />
</vector>

View File

@@ -0,0 +1,44 @@
<?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>None</item>
<item>Home</item>
<item>Power</item>
<item>Back</item>
<item>Recents</item>
<item>Volume Up</item>
<item>Volume Down</item>
<item>Voice Assistant</item>
<item>Play/Pause</item>
<item>Previous Track</item>
<item>Next Track</item>
</string-array>
<string-array name="fp_keys_listValues">
<item>0</item>
<item>102</item>
<item>116</item>
<item>158</item>
<item>580</item>
<item>115</item>
<item>114</item>
<item>582</item>
<item>164</item>
<item>165</item>
<item>163</item>
</string-array>
</resources>

View File

@@ -0,0 +1,21 @@
<?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">
<string name="moto_actions_title">Moto Actions</string>
<string name="moto_actions_summary">Manage custom actions and fingerprint gestures</string>
</resources>

View File

@@ -0,0 +1,29 @@
<?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="CMActions" parent="@android:style/Theme.DeviceDefault.Settings">
<item name="preferenceTheme">@style/SettingsPreference</item>
</style>
<!-- Preferences -->
<style name="SettingsPreference">
<item name="allowDividerAbove">false</item>
<item name="allowDividerBelow">true</item>
<item name="singleLineTitle">false</item>
</style>
</resources>

View File

@@ -0,0 +1,45 @@
<?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">
<PreferenceCategory
android:key="ambient_display_key"
android:title="@string/ambient_display_title">
<cyanogenmod.preference.SecureSettingSwitchPreference
android:key="doze_enabled"
android:defaultValue="true"
android:title="@string/ambient_display_enable_title"
android:summary="@string/ambient_display_enable_summary" />
<SwitchPreference
android:key="gesture_pick_up"
android:defaultValue="true"
android:title="@string/pick_up_gesture_title"
android:summary="@string/pick_up_gesture_summary"
android:dependency="doze_enabled" />
<SwitchPreference
android:key="gesture_hand_wave"
android:defaultValue="true"
android:title="@string/hand_wave_gesture_title"
android:summary="@string/hand_wave_gesture_summary"
android:dependency="doze_enabled" />
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -0,0 +1,172 @@
<?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">
<PreferenceCategory
android:key="actions_key"
android:title="@string/actions_title">
<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" />
</PreferenceCategory>
<PreferenceCategory
android:key="fp_key"
android:title="@string/fingerprint_title" >
<SwitchPreference
android:key="fp_home"
android:title="Fingerprint Gestures"
android:summary="Use fingerprint gestures" />
<SwitchPreference
android:key="fp_home_scr_off"
android:dependency="fp_home"
android:title="Fingerprint Gestures when screen off"
android:summary="Use fingerprint gestures when screen off" />
<SwitchPreference
android:key="fp_haptic"
android:dependency="fp_home"
android:defaultValue="0"
android:title="Fingerprint Gestures Haptic Feedback"
android:summary="Vibrate on actions" />
</PreferenceCategory>
<PreferenceCategory
android:key="fp_keys_scr_on"
android:title="Screen On Gestures" >
<ListPreference
android:dependency="fp_home"
android:title="Fingerprint Tap"
android:summary="%s"
android:dialogTitle="Select action for single tap"
android:key="fp_keys"
android:defaultValue="0"
android:entries="@array/fp_keys_listArray"
android:entryValues="@array/fp_keys_listValues" />
<ListPreference
android:dependency="fp_home"
android:title="Fingerprint Long Press"
android:summary="%s"
android:dialogTitle="Select action for long press"
android:key="fp_key_hold"
android:defaultValue="0"
android:entries="@array/fp_keys_listArray"
android:entryValues="@array/fp_keys_listValues" />
<ListPreference
android:dependency="fp_home"
android:title="Fingerprint Swipe Left"
android:summary="%s"
android:dialogTitle="Select action for swipe left"
android:key="fp_key_left"
android:defaultValue="0"
android:entries="@array/fp_keys_listArray"
android:entryValues="@array/fp_keys_listValues" />
<ListPreference
android:dependency="fp_home"
android:title="Fingerprint Swipe Right"
android:summary="%s"
android:dialogTitle="Select action for swipe right"
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="Screen Off Gestures" >
<ListPreference
android:dependency="fp_home_scr_off"
android:title="Fingerprint Tap"
android:summary="%s"
android:dialogTitle="Select action for single tap"
android:key="fp_keys_off"
android:defaultValue="0"
android:entries="@array/fp_keys_listArray"
android:entryValues="@array/fp_keys_listValues" />
<ListPreference
android:dependency="fp_home_scr_off"
android:title="Fingerprint Long Press"
android:summary="%s"
android:dialogTitle="Select action for long press"
android:key="fp_key_hold_off"
android:defaultValue="0"
android:entries="@array/fp_keys_listArray"
android:entryValues="@array/fp_keys_listValues" />
<ListPreference
android:dependency="fp_home_scr_off"
android:title="Fingerprint Swipe Left"
android:summary="%s"
android:dialogTitle="Select action for swipe left"
android:key="fp_key_left_off"
android:defaultValue="0"
android:entries="@array/fp_keys_listArray"
android:entryValues="@array/fp_keys_listValues" />
<ListPreference
android:dependency="fp_home_scr_off"
android:title="Fingerprint Swipe Right"
android:summary="%s"
android:dialogTitle="Select action for swipe right"
android:key="fp_key_right_off"
android:defaultValue="0"
android:entries="@array/fp_keys_listArray"
android:entryValues="@array/fp_keys_listValues" />
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cyanogenmod.settings.device;
import android.content.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 com.cyanogenmod.settings.device.ServiceWrapper.LocalBinder;
public class BootCompletedReceiver extends BroadcastReceiver {
static final String TAG = "CMActions";
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.sButtonPrefKeys) {
Constants.writePreference(context, pref);
}
context.startService(new Intent(context, ServiceWrapper.class));
}
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,109 @@
/*
* Copyright (c) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cyanogenmod.settings.device;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.provider.Settings;
import android.util.Log;
import java.util.List;
import java.util.LinkedList;
public class CMActionsService extends IntentService implements ScreenStateNotifier,
UpdatedStateNotifier {
private static final String TAG = "CMActions";
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 CMActionsService(Context context) {
super("CMActionService");
mContext = context;
Log.d(TAG, "Starting");
CMActionsSettings cmActionsSettings = new CMActionsSettings(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 GlanceSensor(cmActionsSettings, mSensorHelper, mDozePulseAction));
mScreenStateNotifiers.add(new ProximitySensor(cmActionsSettings, mSensorHelper, mDozePulseAction));
mScreenStateNotifiers.add(new StowSensor(cmActionsSettings, mSensorHelper, mDozePulseAction));
// Other actions that are always enabled
mUpdatedStateNotifiers.add(new CameraActivationSensor(cmActionsSettings, mSensorHelper));
mUpdatedStateNotifiers.add(new ChopChopSensor(cmActionsSettings, mSensorHelper));
mUpdatedStateNotifiers.add(new ProximitySilencer(cmActionsSettings, context, mSensorHelper));
mUpdatedStateNotifiers.add(new FlipToMute(cmActionsSettings, context, mSensorHelper));
mUpdatedStateNotifiers.add(new LiftToSilence(cmActionsSettings, context, mSensorHelper));
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "CMActionsWakeLock");
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,143 @@
/*
* Copyright (c) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cyanogenmod.settings.device;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.util.Log;
public class CMActionsSettings {
private static final String TAG = "CMActions";
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 CMActionsSettings(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_KEYS.equals(key) || Constants.FP_KEY_HOLD.equals(key) || Constants.FP_KEY_LEFT.equals(key) || Constants.FP_KEY_RIGHT.equals(key)) {
Constants.writePreference(mContext, key);
updated = false;
} else {
updated = false;
}
if (updated) {
mUpdatedStateNotifier.updateState();
}
}
};
}

View File

@@ -0,0 +1,132 @@
/*
* Copyright (c) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cyanogenmod.settings.device;
import 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;
public class CameraActivationAction implements SensorAction {
private static final String TAG = "CMActions";
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,66 @@
/*
* Copyright (c) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cyanogenmod.settings.device;
import java.util.List;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
public class CameraActivationSensor implements SensorEventListener, UpdatedStateNotifier {
private static final String TAG = "CMActions-CameraSensor";
private static final int TURN_SCREEN_ON_WAKE_LOCK_MS = 500;
private final CMActionsSettings mCMActionsSettings;
private final SensorHelper mSensorHelper;
private final Sensor mSensor;
private boolean mIsEnabled;
public CameraActivationSensor(CMActionsSettings cmActionsSettings, SensorHelper sensorHelper) {
mCMActionsSettings = cmActionsSettings;
mSensorHelper = sensorHelper;
mSensor = sensorHelper.getCameraActivationSensor();
mSensorHelper.registerListener(mSensor, this);
}
@Override
public synchronized void updateState() {
if (mCMActionsSettings.isCameraGestureEnabled() && !mIsEnabled) {
Log.d(TAG, "Enabling");
mIsEnabled = true;
} else if (! mCMActionsSettings.isCameraGestureEnabled() && mIsEnabled) {
Log.d(TAG, "Disabling");
mIsEnabled = false;
}
}
@Override
public void onSensorChanged(SensorEvent event) {
Log.d(TAG, "activate camera");
if (mIsEnabled) mCMActionsSettings.cameraAction();
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2015-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 com.cyanogenmod.settings.device;
import java.util.List;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
public class ChopChopSensor implements SensorEventListener, UpdatedStateNotifier {
private static final String TAG = "CMActions-ChopChopSensor";
private static final int TURN_SCREEN_ON_WAKE_LOCK_MS = 500;
private final CMActionsSettings mCMActionsSettings;
private final SensorHelper mSensorHelper;
private final Sensor mSensor;
private final Sensor mProx;
private boolean mIsEnabled;
private boolean mProxIsCovered;
public ChopChopSensor(CMActionsSettings cmActionsSettings, SensorHelper sensorHelper) {
mCMActionsSettings = cmActionsSettings;
mSensorHelper = sensorHelper;
mSensor = sensorHelper.getChopChopSensor();
mProx = sensorHelper.getProximitySensor();
}
@Override
public synchronized void updateState() {
if (mCMActionsSettings.isChopChopGestureEnabled() && !mIsEnabled) {
Log.d(TAG, "Enabling");
mSensorHelper.registerListener(mSensor, this);
mSensorHelper.registerListener(mProx, mProxListener);
mIsEnabled = true;
} else if (! mCMActionsSettings.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;
}
mCMActionsSettings.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,139 @@
/*
* 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 com.cyanogenmod.settings.device;
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.cyanogenmod.internal.util.FileUtils;
public class Constants {
private static final String TAG = "CMActions";
// 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";
// List of keys
public static final String FP_KEYS = "fp_keys";
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_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_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";
// 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[] sButtonPrefKeys = {
FP_HOME_KEY,
FP_HOME_KEY_OFF,
FP_KEYS,
FP_KEY_HOLD,
FP_KEY_RIGHT,
FP_KEY_LEFT,
FP_HAPTIC_KEY,
};
public static final String[] sButtonScreenOffPrefKeys = {
FP_KEYS_OFF,
FP_KEY_HOLD_OFF,
FP_KEY_RIGHT_OFF,
FP_KEY_LEFT_OFF,
FP_HOME_KEY_OFF,
};
static {
sBooleanNodePreferenceMap.put(FP_HOME_KEY, FP_HOME_NODE);
sBooleanNodePreferenceMap.put(FP_HOME_KEY_OFF, FP_HOME_OFF_NODE);
sBooleanNodePreferenceMap.put(FP_KEYS, FP_KEYS_NODE);
sBooleanNodePreferenceMap.put(FP_KEY_HOLD, FP_KEY_HOLD_NODE);
sBooleanNodePreferenceMap.put(FP_KEY_LEFT, FP_KEY_LEFT_NODE);
sBooleanNodePreferenceMap.put(FP_KEY_RIGHT, FP_KEY_RIGHT_NODE);
sBooleanNodePreferenceMap.put(FP_HAPTIC_KEY, FP_HAPTIC_NODE);
sBooleanNodePreferenceMap.put(FP_KEYS_OFF, FP_KEYS_NODE);
sBooleanNodePreferenceMap.put(FP_KEY_HOLD_OFF, FP_KEY_HOLD_NODE);
sBooleanNodePreferenceMap.put(FP_KEY_LEFT_OFF, FP_KEY_LEFT_NODE);
sBooleanNodePreferenceMap.put(FP_KEY_RIGHT_OFF, FP_KEY_RIGHT_NODE);
sNodeDefaultMap.put(FP_HOME_KEY, false);
sNodeDefaultMap.put(FP_HOME_KEY_OFF, false);
sNodeDefaultMap.put(FP_KEYS, "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_HOLD_OFF, "0");
sNodeDefaultMap.put(FP_KEY_LEFT_OFF, "0");
sNodeDefaultMap.put(FP_KEY_RIGHT_OFF, "0");
sNodeDefaultMap.put(FP_HAPTIC_KEY, false);
}
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";
Log.e(TAG, "Write Pref: " + pref);
if (!pref.equals(FP_KEYS) && !pref.equals(FP_KEY_HOLD) && !pref.equals(FP_KEY_LEFT) && !pref.equals(FP_KEY_RIGHT) &&
!pref.equals(FP_KEYS_OFF) && !pref.equals(FP_KEY_HOLD_OFF) && !pref.equals(FP_KEY_LEFT_OFF) && !pref.equals(FP_KEY_RIGHT_OFF))
value = isPreferenceEnabled(context, pref) ? "1" : "0";
else
value = GetPreference(context, pref);
String node = sBooleanNodePreferenceMap.get(pref);
Log.e(TAG, "Write " + value + " to node " + node);
if (!FileUtils.writeLine(node, value)) {
Log.w(TAG, "Write " + value + " to node " + node +
"failed while restoring saved preference values");
}
}
}

View File

@@ -0,0 +1,73 @@
/*
* 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 com.cyanogenmod.settings.device;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.provider.Settings;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v14.preference.PreferenceFragment;
import android.support.v14.preference.SwitchPreference;
import android.view.MenuItem;
public class DozePreferenceActivity extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActionBar().setDisplayHomeAsUpEnabled(true);
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new DozePreferenceFragment()).commit();
}
public class DozePreferenceFragment extends PreferenceFragment {
private static final String KEY_AMBIENT_DISPLAY_ENABLE = "doze_enabled";
private SwitchPreference mAmbientDisplayPreference;
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.doze_panel);
boolean dozeEnabled = CMActionsSettings.isDozeEnabled(getActivity().getContentResolver());
mAmbientDisplayPreference = (SwitchPreference) findPreference(KEY_AMBIENT_DISPLAY_ENABLE);
// Read from DOZE_ENABLED secure setting
mAmbientDisplayPreference.setChecked(dozeEnabled);
mAmbientDisplayPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean enable = (boolean) newValue;
return enableDoze(enable);
}
});
}
private boolean enableDoze(boolean enable) {
return Settings.Secure.putInt(getContext().getContentResolver(),
Settings.Secure.DOZE_ENABLED, enable ? 1 : 0);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cyanogenmod.settings.device;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class DozePulseAction implements SensorAction, ScreenStateNotifier {
private static final String TAG = "CMActions";
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,123 @@
/*
* 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 com.cyanogenmod.settings.device;
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;
public class FlipToMute implements UpdatedStateNotifier {
private static final String TAG = "CMActions-FlipToMute";
private final NotificationManager mNotificationManager;
private final CMActionsSettings mCMActionsSettings;
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(CMActionsSettings cmActionsSettings, Context context,
SensorHelper sensorHelper) {
mCMActionsSettings = cmActionsSettings;
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 (mCMActionsSettings.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 (!mCMActionsSettings.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,69 @@
/*
* 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 com.cyanogenmod.settings.device;
import android.hardware.Sensor;
import android.hardware.TriggerEvent;
import android.hardware.TriggerEventListener;
import android.util.Log;
public class GlanceSensor implements ScreenStateNotifier {
private static final String TAG = "CMActions-GlanceSensor";
private final CMActionsSettings mCMActionsSettings;
private final SensorHelper mSensorHelper;
private final SensorAction mSensorAction;
private final Sensor mSensor;
private boolean mEnabled;
public GlanceSensor(CMActionsSettings cmActionsSettings, SensorHelper sensorHelper,
SensorAction action) {
mCMActionsSettings = cmActionsSettings;
mSensorHelper = sensorHelper;
mSensorAction = action;
mSensor = sensorHelper.getGlanceSensor();
}
@Override
public void screenTurnedOn() {
if (mEnabled) {
Log.d(TAG, "Disabling");
mSensorHelper.cancelTriggerSensor(mSensor, mGlanceListener);
mEnabled = false;
}
}
@Override
public void screenTurnedOff() {
if (mCMActionsSettings.isPickUpEnabled() && !mEnabled) {
Log.d(TAG, "Enabling");
mSensorHelper.requestTriggerSensor(mSensor, mGlanceListener);
mEnabled = true;
}
}
private TriggerEventListener mGlanceListener = new TriggerEventListener() {
@Override
public void onTrigger(TriggerEvent event) {
Log.d(TAG, "triggered");
mSensorAction.action();
mSensorHelper.requestTriggerSensor(mSensor, mGlanceListener);
}
};
}

View File

@@ -0,0 +1,105 @@
/*
* 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 com.cyanogenmod.settings.device;
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;
public class LiftToSilence extends PhoneStateListener implements SensorEventListener, UpdatedStateNotifier {
private static final String TAG = "CMActions-LiftToSilence";
private final CMActionsSettings mCMActionsSettings;
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(CMActionsSettings cmActionsSettings, Context context,
SensorHelper sensorHelper) {
mCMActionsSettings = cmActionsSettings;
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 (mCMActionsSettings.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,76 @@
/*
* Copyright (c) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cyanogenmod.settings.device;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.util.Log;
public class ProximitySensor implements ScreenStateNotifier, SensorEventListener {
private static final String TAG = "CMActions-ProximitySensor";
private final CMActionsSettings mCMActionsSettings;
private final SensorHelper mSensorHelper;
private final SensorAction mSensorAction;
private final Sensor mSensor;
private boolean mEnabled;
private boolean mSawNear = false;
public ProximitySensor(CMActionsSettings cmActionsSettings, SensorHelper sensorHelper,
SensorAction action) {
mCMActionsSettings = cmActionsSettings;
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 (mCMActionsSettings.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,110 @@
/*
* Copyright (c) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cyanogenmod.settings.device;
import android.content.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 static android.telephony.TelephonyManager.*;
public class ProximitySilencer extends PhoneStateListener implements SensorEventListener, UpdatedStateNotifier {
private static final String TAG = "CMActions-ProximitySilencer";
private static final int SILENCE_DELAY_MS = 500;
private final TelecomManager mTelecomManager;
private final TelephonyManager mTelephonyManager;
private final CMActionsSettings mCMActionsSettings;
private final SensorHelper mSensorHelper;
private final Sensor mSensor;
private boolean mIsRinging;
private long mRingStartedMs;
private boolean mCoveredRinging;
public ProximitySilencer(CMActionsSettings cmActionsSettings, Context context,
SensorHelper sensorHelper) {
mTelecomManager = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
mCMActionsSettings = cmActionsSettings;
mSensorHelper = sensorHelper;
mSensor = sensorHelper.getProximitySensor();
mCoveredRinging = false;
mIsRinging = false;
}
@Override
public void updateState() {
if (mCMActionsSettings.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.length + "]: " + event.values[0] + ", " +
event.values[1] + ", " + event.values[2] + " 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,53 @@
/*
* Copyright (c) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cyanogenmod.settings.device;
import java.util.List;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
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();
for (String pref : Constants.sButtonScreenOffPrefKeys) {
Constants.writePreference(context, pref);
}
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
mNotifier.screenTurnedOn();
for (String pref : Constants.sButtonPrefKeys) {
Constants.writePreference(context, pref);
}
}
}
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright (c) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cyanogenmod.settings.device;
interface ScreenStateNotifier {
public void screenTurnedOn();
public void screenTurnedOff();
}

View File

@@ -0,0 +1,21 @@
/*
* Copyright (c) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cyanogenmod.settings.device;
interface SensorAction {
public void action();
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright (c) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cyanogenmod.settings.device;
import 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 = "CMActions";
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 getGlanceSensor() {
return mSensorManager.getDefaultSensor(Sensor.TYPE_GLANCE_GESTURE, 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,65 @@
/*
* Copyright (c) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cyanogenmod.settings.device;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
public class ServiceWrapper extends android.app.Service {
static final String TAG = "CMActions-ServiceWrapper";
private final IBinder mBinder = new LocalBinder();
private CMActionsService mCmActionsService;
public interface ServiceCallback {
void sendResults(int resultCode, Bundle b);
}
public class LocalBinder extends Binder {
ServiceWrapper getService() {
// Return this instance of the service so clients can call public
// methods
return ServiceWrapper.this;
}
}
@Override
public void onCreate() {
Log.i(TAG, "onCreate");
super.onCreate();
mCmActionsService = new CMActionsService(this);
}
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind");
return null;
}
public void setCallback(ServiceCallback callback) {
}
public void start() {
Log.i(TAG, "start");
}
public void stop() {
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (c) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cyanogenmod.settings.device;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.util.Log;
import java.lang.System;
public class StowSensor implements ScreenStateNotifier, SensorEventListener {
private static final String TAG = "CMActions-StowSensor";
private static final int IN_POCKET_MIN_TIME = 5000;
private final CMActionsSettings mCMActionsSettings;
private final SensorHelper mSensorHelper;
private final SensorAction mSensorAction;
private final Sensor mSensor;
private boolean mEnabled;
private boolean mLastStowed;
private long isStowedTime;
public StowSensor(CMActionsSettings cmActionsSettings, SensorHelper sensorHelper,
SensorAction action) {
mCMActionsSettings = cmActionsSettings;
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 (!mCMActionsSettings.isIrWakeupEnabled() &&
mCMActionsSettings.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,81 @@
/*
* Copyright (c) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cyanogenmod.settings.device;
import android.content.Context;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraAccessException;
import android.os.Vibrator;
import android.util.Log;
public class TorchAction implements SensorAction {
private static final String TAG = "CMActions";
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);
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,31 @@
/*
* 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 com.cyanogenmod.settings.device;
import android.os.Bundle;
import android.preference.PreferenceActivity;
public class TouchscreenGesturePreferenceActivity extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new TouchscreenGesturePreferenceFragment()).commit();
}
}

View File

@@ -0,0 +1,90 @@
/*
* 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 com.cyanogenmod.settings.device;
import android.app.ActionBar;
import android.app.AlertDialog;
import android.app.NotificationManager;
import android.os.Bundle;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.support.v7.preference.PreferenceCategory;
import android.support.v14.preference.PreferenceFragment;
import android.support.v7.preference.Preference;
import android.support.v14.preference.SwitchPreference;
import android.view.Menu;
import android.view.MenuItem;
public class TouchscreenGesturePreferenceFragment extends PreferenceFragment {
private SwitchPreference mFlipPref;
private NotificationManager mNotificationManager;
private boolean mFlipClick = false;
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.gesture_panel);
final ActionBar actionBar = getActivity().getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
mNotificationManager = (NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
mFlipPref = (SwitchPreference) findPreference("gesture_flip_to_mute");
mFlipPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
if (!mNotificationManager.isNotificationPolicyAccessGranted()) {
mFlipPref.setChecked(false);
new AlertDialog.Builder(getContext())
.setTitle(getString(R.string.flip_to_mute_title))
.setMessage(getString(R.string.dnd_access))
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mFlipClick = true;
startActivity(new Intent(
android.provider.Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS));
}
}).show();
}
return true;
}
});
//Users may deny DND access after giving it
if (!mNotificationManager.isNotificationPolicyAccessGranted()) {
mFlipPref.setChecked(false);
}
}
@Override
public void onResume() {
super.onResume();
if (mNotificationManager.isNotificationPolicyAccessGranted() && mFlipClick) {
mFlipPref.setChecked(true);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
getActivity().onBackPressed();
return true;
}
return false;
}
}

View File

@@ -0,0 +1,21 @@
/*
* Copyright (c) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cyanogenmod.settings.device;
interface UpdatedStateNotifier {
public void updateState();
}

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.cyanogenmod.internal.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 = null;
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();
}
}