df65ca3c |
1 | /* |
2 | * Copyright (c) 2015 The CyanogenMod Project |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | package org.lineageos.settings.doze; |
18 | |
19 | import android.app.Service; |
20 | import android.content.BroadcastReceiver; |
21 | import android.content.Context; |
22 | import android.content.Intent; |
23 | import android.content.IntentFilter; |
24 | import android.content.SharedPreferences; |
25 | import android.hardware.Sensor; |
26 | import android.hardware.SensorEvent; |
27 | import android.hardware.SensorEventListener; |
28 | import android.hardware.SensorManager; |
29 | import android.os.IBinder; |
30 | import android.os.PowerManager; |
31 | import android.os.UserHandle; |
32 | import android.preference.PreferenceManager; |
33 | import android.provider.Settings; |
34 | import android.util.Log; |
35 | |
36 | import java.lang.System; |
37 | import java.util.ArrayList; |
38 | import java.util.concurrent.TimeUnit; |
39 | import java.util.List; |
40 | |
41 | public class SamsungDozeService extends Service { |
42 | private static final String TAG = "SamsungDozeService"; |
43 | private static final boolean DEBUG = false; |
44 | |
45 | private static final String DOZE_INTENT = "com.android.systemui.doze.pulse"; |
46 | |
47 | private static final String GESTURE_HAND_WAVE_KEY = "gesture_hand_wave"; |
48 | private static final String GESTURE_POCKET_KEY = "gesture_pocket"; |
49 | private static final String PROXIMITY_WAKE_KEY = "proximity_wake_enable"; |
50 | |
51 | private static final int POCKET_DELTA_NS = 1000 * 1000 * 1000; |
52 | |
53 | private Context mContext; |
54 | private SamsungProximitySensor mSensor; |
55 | private PowerManager mPowerManager; |
56 | |
57 | private boolean mHandwaveGestureEnabled = false; |
58 | private boolean mPocketGestureEnabled = false; |
59 | private boolean mProximityWakeEnabled = false; |
60 | |
61 | class SamsungProximitySensor implements SensorEventListener { |
62 | private SensorManager mSensorManager; |
63 | private Sensor mSensor; |
64 | |
65 | private boolean mSawNear = false; |
66 | private long mInPocketTime = 0; |
67 | |
68 | public SamsungProximitySensor(Context context) { |
69 | mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE); |
70 | mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); |
71 | } |
72 | |
73 | @Override |
74 | public void onSensorChanged(SensorEvent event) { |
75 | boolean isNear = event.values[0] < mSensor.getMaximumRange(); |
76 | if (mSawNear && !isNear) { |
77 | if (shouldPulse(event.timestamp)) { |
78 | launchDozePulse(); |
79 | } |
80 | } else { |
81 | mInPocketTime = event.timestamp; |
82 | } |
83 | mSawNear = isNear; |
84 | } |
85 | |
86 | @Override |
87 | public void onAccuracyChanged(Sensor sensor, int accuracy) { |
88 | /* Empty */ |
89 | } |
90 | |
91 | private boolean shouldPulse(long timestamp) { |
92 | long delta = timestamp - mInPocketTime; |
93 | |
94 | if (mHandwaveGestureEnabled && mPocketGestureEnabled) { |
95 | return true; |
96 | } else if (mProximityWakeEnabled && (delta < POCKET_DELTA_NS)) { |
97 | mPowerManager.wakeUp(TimeUnit.NANOSECONDS.toMillis(System.nanoTime())); |
98 | return false; |
99 | } else if (mHandwaveGestureEnabled && !mPocketGestureEnabled) { |
100 | return delta < POCKET_DELTA_NS; |
101 | } else if (!mHandwaveGestureEnabled && mPocketGestureEnabled) { |
102 | return delta >= POCKET_DELTA_NS; |
103 | } |
104 | return false; |
105 | } |
106 | |
107 | public void testAndEnable() { |
108 | if ((isDozeEnabled() && (mHandwaveGestureEnabled || mPocketGestureEnabled)) || |
109 | mProximityWakeEnabled) { |
110 | mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL); |
111 | } |
112 | } |
113 | |
114 | public void disable() { |
115 | mSensorManager.unregisterListener(this, mSensor); |
116 | } |
117 | } |
118 | |
119 | @Override |
120 | public void onCreate() { |
121 | if (DEBUG) Log.d(TAG, "SamsungDozeService Started"); |
122 | mContext = this; |
123 | mPowerManager = (PowerManager)getSystemService(Context.POWER_SERVICE); |
124 | mSensor = new SamsungProximitySensor(mContext); |
125 | SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(mContext); |
126 | loadPreferences(sharedPrefs); |
127 | sharedPrefs.registerOnSharedPreferenceChangeListener(mPrefListener); |
128 | if (!isInteractive()) { |
129 | mSensor.testAndEnable(); |
130 | } |
131 | } |
132 | |
133 | @Override |
134 | public int onStartCommand(Intent intent, int flags, int startId) { |
135 | if (DEBUG) Log.d(TAG, "Starting service"); |
136 | IntentFilter screenStateFilter = new IntentFilter(Intent.ACTION_SCREEN_ON); |
137 | screenStateFilter.addAction(Intent.ACTION_SCREEN_OFF); |
138 | mContext.registerReceiver(mScreenStateReceiver, screenStateFilter); |
139 | return START_STICKY; |
140 | } |
141 | |
142 | @Override |
143 | public IBinder onBind(Intent intent) { |
144 | return null; |
145 | } |
146 | |
147 | private void launchDozePulse() { |
148 | mContext.sendBroadcastAsUser(new Intent(DOZE_INTENT), |
149 | new UserHandle(UserHandle.USER_CURRENT)); |
150 | } |
151 | |
152 | private boolean isInteractive() { |
153 | return mPowerManager.isInteractive(); |
154 | } |
155 | |
156 | private boolean isDozeEnabled() { |
157 | return Settings.Secure.getInt(mContext.getContentResolver(), |
158 | Settings.Secure.DOZE_ENABLED, 1) != 0; |
159 | } |
160 | |
161 | private void onDisplayOn() { |
162 | if (DEBUG) Log.d(TAG, "Display on"); |
163 | mSensor.disable(); |
164 | } |
165 | |
166 | private void onDisplayOff() { |
167 | if (DEBUG) Log.d(TAG, "Display off"); |
168 | mSensor.testAndEnable(); |
169 | } |
170 | |
171 | private void loadPreferences(SharedPreferences sharedPreferences) { |
172 | mHandwaveGestureEnabled = sharedPreferences.getBoolean(GESTURE_HAND_WAVE_KEY, false); |
173 | mPocketGestureEnabled = sharedPreferences.getBoolean(GESTURE_POCKET_KEY, false); |
174 | mProximityWakeEnabled = sharedPreferences.getBoolean(PROXIMITY_WAKE_KEY, false); |
175 | } |
176 | |
177 | private BroadcastReceiver mScreenStateReceiver = new BroadcastReceiver() { |
178 | @Override |
179 | public void onReceive(Context context, Intent intent) { |
180 | if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { |
181 | onDisplayOff(); |
182 | } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { |
183 | onDisplayOn(); |
184 | } |
185 | } |
186 | }; |
187 | |
188 | private SharedPreferences.OnSharedPreferenceChangeListener mPrefListener = |
189 | new SharedPreferences.OnSharedPreferenceChangeListener() { |
190 | @Override |
191 | public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { |
192 | if (GESTURE_HAND_WAVE_KEY.equals(key)) { |
193 | mHandwaveGestureEnabled = sharedPreferences.getBoolean(GESTURE_HAND_WAVE_KEY, false); |
194 | } else if (GESTURE_POCKET_KEY.equals(key)) { |
195 | mPocketGestureEnabled = sharedPreferences.getBoolean(GESTURE_POCKET_KEY, false); |
196 | } else if (PROXIMITY_WAKE_KEY.equals(key)) { |
197 | mProximityWakeEnabled = sharedPreferences.getBoolean(PROXIMITY_WAKE_KEY, false); |
198 | } |
199 | } |
200 | }; |
201 | } |