blob: 092eb46cad5e9a818bb0099750902e83b1e6fe9a [file] [log] [blame]
Adrian Roosea8d6ae2016-10-26 10:40:12 -07001/*
2 * Copyright (C) 2016 The Android Open Source 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
Adrian Roosff2c4562016-11-03 12:13:36 -070014 * limitations under the License.
Adrian Roosea8d6ae2016-10-26 10:40:12 -070015 */
16
17package com.android.systemui.doze;
18
Lucas Dupinb2d9f482018-11-16 18:55:13 -080019import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_DISPLAY;
Lucas Dupinde64ee02018-12-21 14:45:12 -080020import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_LOCK_SCREEN;
Lucas Dupin3d951752018-10-10 12:00:40 -070021
Adrian Roosea8d6ae2016-10-26 10:40:12 -070022import android.annotation.AnyThread;
23import android.app.ActivityManager;
Adrian Roos6023ccb2017-06-28 16:22:02 +020024import android.app.AlarmManager;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070025import android.content.ContentResolver;
26import android.content.Context;
27import android.database.ContentObserver;
28import android.hardware.Sensor;
Adrian Roos67cca742017-04-13 16:52:51 -070029import android.hardware.SensorEventListener;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070030import android.hardware.SensorManager;
31import android.hardware.TriggerEvent;
32import android.hardware.TriggerEventListener;
Issei Suzukica19e6e2019-02-26 12:39:11 +010033import android.hardware.display.AmbientDisplayConfiguration;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070034import android.net.Uri;
35import android.os.Handler;
Adrian Roos6023ccb2017-06-28 16:22:02 +020036import android.os.SystemClock;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070037import android.os.UserHandle;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070038import android.provider.Settings;
39import android.text.TextUtils;
40import android.util.Log;
41
Lucas Dupin8a13aa72019-02-22 12:45:21 -080042import androidx.annotation.VisibleForTesting;
43
Adrian Roosff2c4562016-11-03 12:13:36 -070044import com.android.internal.logging.MetricsLogger;
Tamas Berghammer383db5eb2016-06-22 15:21:38 +010045import com.android.internal.logging.nano.MetricsProto;
Lucas Dupinf61c1042019-07-19 12:16:25 -070046import com.android.systemui.R;
Lucas Dupin3d951752018-10-10 12:00:40 -070047import com.android.systemui.plugins.SensorManagerPlugin;
Adrian Roosff2c4562016-11-03 12:13:36 -070048import com.android.systemui.statusbar.phone.DozeParameters;
Adrian Roos6023ccb2017-06-28 16:22:02 +020049import com.android.systemui.util.AlarmTimeout;
Lucas Dupin3d951752018-10-10 12:00:40 -070050import com.android.systemui.util.AsyncSensorManager;
Adrian Roosc1b50322017-02-27 21:07:58 +010051import com.android.systemui.util.wakelock.WakeLock;
Adrian Roosff2c4562016-11-03 12:13:36 -070052
53import java.io.PrintWriter;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070054import java.util.List;
Adrian Roos67cca742017-04-13 16:52:51 -070055import java.util.function.Consumer;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070056
57public class DozeSensors {
58
59 private static final boolean DEBUG = DozeService.DEBUG;
60
61 private static final String TAG = "DozeSensors";
62
63 private final Context mContext;
Adrian Roos6023ccb2017-06-28 16:22:02 +020064 private final AlarmManager mAlarmManager;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070065 private final SensorManager mSensorManager;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070066 private final ContentResolver mResolver;
67 private final TriggerSensor mPickupSensor;
68 private final DozeParameters mDozeParameters;
69 private final AmbientDisplayConfiguration mConfig;
Adrian Roosc1b50322017-02-27 21:07:58 +010070 private final WakeLock mWakeLock;
Adrian Roos67cca742017-04-13 16:52:51 -070071 private final Consumer<Boolean> mProxCallback;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070072 private final Callback mCallback;
Lucas Dupin8a13aa72019-02-22 12:45:21 -080073 @VisibleForTesting
lpeteraca97632019-06-11 11:13:54 +080074 protected TriggerSensor[] mSensors;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070075
76 private final Handler mHandler = new Handler();
Adrian Roos67cca742017-04-13 16:52:51 -070077 private final ProxSensor mProxSensor;
Lucas Dupin8a13aa72019-02-22 12:45:21 -080078 private long mDebounceFrom;
lpeteraca97632019-06-11 11:13:54 +080079 private boolean mSettingRegistered;
Lucas Dupinfac2e8e2019-06-27 16:10:19 -070080 private boolean mListening;
81 private boolean mPaused;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070082
Adrian Roos6023ccb2017-06-28 16:22:02 +020083 public DozeSensors(Context context, AlarmManager alarmManager, SensorManager sensorManager,
Lucas Dupin323f9ff2018-08-27 16:55:56 -070084 DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock,
Lucas Dupinb2d9f482018-11-16 18:55:13 -080085 Callback callback, Consumer<Boolean> proxCallback, AlwaysOnDisplayPolicy policy) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -070086 mContext = context;
Adrian Roos6023ccb2017-06-28 16:22:02 +020087 mAlarmManager = alarmManager;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070088 mSensorManager = sensorManager;
89 mDozeParameters = dozeParameters;
90 mConfig = config;
91 mWakeLock = wakeLock;
Adrian Roos67cca742017-04-13 16:52:51 -070092 mProxCallback = proxCallback;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070093 mResolver = mContext.getContentResolver();
94
Lucas Dupin70bda672018-12-27 15:43:40 -080095 boolean alwaysOn = mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT);
Adrian Roosea8d6ae2016-10-26 10:40:12 -070096 mSensors = new TriggerSensor[] {
97 new TriggerSensor(
98 mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION),
99 null /* setting */,
100 dozeParameters.getPulseOnSigMotion(),
Adrian Roos98d31982017-08-02 20:50:16 +0200101 DozeLog.PULSE_REASON_SENSOR_SIGMOTION, false /* touchCoords */,
102 false /* touchscreen */),
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700103 mPickupSensor = new TriggerSensor(
104 mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE),
Lucas Dupin4359b552018-08-09 15:07:54 -0700105 Settings.Secure.DOZE_PICK_UP_GESTURE,
Lucas Dupinfac2e8e2019-06-27 16:10:19 -0700106 true /* settingDef */,
Lucas Dupin4359b552018-08-09 15:07:54 -0700107 config.dozePickupSensorAvailable(),
Lucas Dupin3d053532019-01-29 12:35:22 -0800108 DozeLog.REASON_SENSOR_PICKUP, false /* touchCoords */,
Lucas Dupinfac2e8e2019-06-27 16:10:19 -0700109 false /* touchscreen */,
110 false /* ignoresSetting */,
111 mDozeParameters.getPickupPerformsProxCheck()),
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700112 new TriggerSensor(
113 findSensorWithType(config.doubleTapSensorType()),
Lucas Dupin4359b552018-08-09 15:07:54 -0700114 Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700115 true /* configured */,
Lucas Dupin3d053532019-01-29 12:35:22 -0800116 DozeLog.REASON_SENSOR_DOUBLE_TAP,
Adrian Roos98d31982017-08-02 20:50:16 +0200117 dozeParameters.doubleTapReportsTouchCoordinates(),
118 true /* touchscreen */),
Adrian Roosd0963a02017-05-15 14:33:37 -0700119 new TriggerSensor(
Lucas Dupind43bf702019-01-15 13:40:42 -0800120 findSensorWithType(config.tapSensorType()),
121 Settings.Secure.DOZE_TAP_SCREEN_GESTURE,
122 true /* configured */,
Lucas Dupin3d053532019-01-29 12:35:22 -0800123 DozeLog.REASON_SENSOR_TAP,
Lucas Dupind43bf702019-01-15 13:40:42 -0800124 false /* reports touch coordinates */,
125 true /* touchscreen */),
126 new TriggerSensor(
Adrian Roosd0963a02017-05-15 14:33:37 -0700127 findSensorWithType(config.longPressSensorType()),
128 Settings.Secure.DOZE_PULSE_ON_LONG_PRESS,
129 false /* settingDef */,
130 true /* configured */,
131 DozeLog.PULSE_REASON_SENSOR_LONG_PRESS,
Adrian Roos98d31982017-08-02 20:50:16 +0200132 true /* reports touch coordinates */,
133 true /* touchscreen */),
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800134 new PluginSensor(
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800135 new SensorManagerPlugin.Sensor(TYPE_WAKE_DISPLAY),
Lucas Dupin7c7b8c22019-06-12 15:23:17 -0700136 Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE,
Lucas Dupin70bda672018-12-27 15:43:40 -0800137 mConfig.wakeScreenGestureAvailable() && alwaysOn,
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800138 DozeLog.REASON_SENSOR_WAKE_UP,
139 false /* reports touch coordinates */,
140 false /* touchscreen */),
Lucas Dupinde64ee02018-12-21 14:45:12 -0800141 new PluginSensor(
142 new SensorManagerPlugin.Sensor(TYPE_WAKE_LOCK_SCREEN),
Lucas Dupin7c7b8c22019-06-12 15:23:17 -0700143 Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE,
144 mConfig.wakeScreenGestureAvailable(),
Lucas Dupinde64ee02018-12-21 14:45:12 -0800145 DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN,
146 false /* reports touch coordinates */,
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800147 false /* touchscreen */, mConfig.getWakeLockScreenDebounce()),
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700148 };
Adrian Roos67cca742017-04-13 16:52:51 -0700149
jackqdyulei8443dd02017-08-24 16:14:34 -0700150 mProxSensor = new ProxSensor(policy);
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700151 mCallback = callback;
152 }
153
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800154 /**
155 * Temporarily disable some sensors to avoid turning on the device while the user is
156 * turning it off.
157 */
158 public void requestTemporaryDisable() {
159 mDebounceFrom = SystemClock.uptimeMillis();
160 }
161
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700162 private Sensor findSensorWithType(String type) {
Adrian Roos2981eb02017-05-26 18:40:09 -0700163 return findSensorWithType(mSensorManager, type);
164 }
165
166 static Sensor findSensorWithType(SensorManager sensorManager, String type) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700167 if (TextUtils.isEmpty(type)) {
168 return null;
169 }
Adrian Roos2981eb02017-05-26 18:40:09 -0700170 List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL);
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700171 for (Sensor s : sensorList) {
172 if (type.equals(s.getStringType())) {
173 return s;
174 }
175 }
176 return null;
177 }
178
Lucas Dupinfac2e8e2019-06-27 16:10:19 -0700179 /**
180 * If sensors should be registered and sending signals.
181 */
Adrian Roosd6ec13132016-10-27 11:50:47 -0700182 public void setListening(boolean listen) {
Lucas Dupinfac2e8e2019-06-27 16:10:19 -0700183 if (mListening == listen) {
184 return;
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700185 }
Lucas Dupinfac2e8e2019-06-27 16:10:19 -0700186 mListening = listen;
187 updateListening();
188 }
189
190 /**
191 * Unregister sensors, when listening, unless they are prox gated.
192 * @see #setListening(boolean)
193 */
194 public void setPaused(boolean paused) {
195 if (mPaused == paused) {
196 return;
197 }
198 mPaused = paused;
199 updateListening();
200 }
201
Lucas Dupin3174c662019-07-15 15:49:54 -0700202 /**
203 * Registers/unregisters sensors based on internal state.
204 */
205 public void updateListening() {
Lucas Dupinfac2e8e2019-06-27 16:10:19 -0700206 boolean anyListening = false;
207 for (TriggerSensor s : mSensors) {
208 // We don't want to be listening while we're PAUSED (prox sensor is covered)
209 // except when the sensor is already gated by prox.
210 boolean listen = mListening && (!mPaused || s.performsProxCheck());
211 s.setListening(listen);
212 if (listen) {
213 anyListening = true;
214 }
215 }
216
217 if (!anyListening) {
218 mResolver.unregisterContentObserver(mSettingsObserver);
219 } else if (!mSettingRegistered) {
220 for (TriggerSensor s : mSensors) {
221 s.registerSettingsObserver(mSettingsObserver);
222 }
223 }
224 mSettingRegistered = anyListening;
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700225 }
226
Adrian Roos98d31982017-08-02 20:50:16 +0200227 /** Set the listening state of only the sensors that require the touchscreen. */
228 public void setTouchscreenSensorsListening(boolean listening) {
229 for (TriggerSensor sensor : mSensors) {
230 if (sensor.mRequiresTouchscreen) {
231 sensor.setListening(listening);
232 }
233 }
234 }
235
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700236 public void onUserSwitched() {
237 for (TriggerSensor s : mSensors) {
Lucas Dupin3174c662019-07-15 15:49:54 -0700238 s.updateListening();
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700239 }
240 }
241
Adrian Roos67cca742017-04-13 16:52:51 -0700242 public void setProxListening(boolean listen) {
Adrian Roos6023ccb2017-06-28 16:22:02 +0200243 mProxSensor.setRequested(listen);
Adrian Roos67cca742017-04-13 16:52:51 -0700244 }
245
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700246 private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
247 @Override
248 public void onChange(boolean selfChange, Uri uri, int userId) {
249 if (userId != ActivityManager.getCurrentUser()) {
250 return;
251 }
252 for (TriggerSensor s : mSensors) {
Lucas Dupin3174c662019-07-15 15:49:54 -0700253 s.updateListening();
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700254 }
255 }
256 };
257
258 public void setDisableSensorsInterferingWithProximity(boolean disable) {
259 mPickupSensor.setDisabled(disable);
260 }
261
lpeter8a5f4702019-01-18 16:53:07 +0800262 /** Ignore the setting value of only the sensors that require the touchscreen. */
263 public void ignoreTouchScreenSensorsSettingInterferingWithDocking(boolean ignore) {
264 for (TriggerSensor sensor : mSensors) {
265 if (sensor.mRequiresTouchscreen) {
266 sensor.ignoreSetting(ignore);
267 }
268 }
269 }
270
Adrian Roosff2c4562016-11-03 12:13:36 -0700271 /** Dump current state */
272 public void dump(PrintWriter pw) {
273 for (TriggerSensor s : mSensors) {
Lucas Dupindc13fe42019-04-10 16:07:50 -0700274 pw.print(" Sensor: "); pw.println(s.toString());
Adrian Roosff2c4562016-11-03 12:13:36 -0700275 }
Lucas Dupindc13fe42019-04-10 16:07:50 -0700276 pw.print(" ProxSensor: "); pw.println(mProxSensor.toString());
Adrian Roosff2c4562016-11-03 12:13:36 -0700277 }
278
Adrian Roos70da03a2017-07-24 16:42:57 +0200279 /**
280 * @return true if prox is currently far, false if near or null if unknown.
281 */
282 public Boolean isProximityCurrentlyFar() {
283 return mProxSensor.mCurrentlyFar;
284 }
285
Adrian Roos67cca742017-04-13 16:52:51 -0700286 private class ProxSensor implements SensorEventListener {
287
Adrian Roos6023ccb2017-06-28 16:22:02 +0200288 boolean mRequested;
Adrian Roos67cca742017-04-13 16:52:51 -0700289 boolean mRegistered;
290 Boolean mCurrentlyFar;
Adrian Roos6023ccb2017-06-28 16:22:02 +0200291 long mLastNear;
292 final AlarmTimeout mCooldownTimer;
jackqdyulei8443dd02017-08-24 16:14:34 -0700293 final AlwaysOnDisplayPolicy mPolicy;
Lucas Dupinf61c1042019-07-19 12:16:25 -0700294 final Sensor mSensor;
Lucas Dupincf06eb32019-08-12 14:14:08 -0700295 final boolean mUsingBrightnessSensor;
Adrian Roos6023ccb2017-06-28 16:22:02 +0200296
jackqdyulei8443dd02017-08-24 16:14:34 -0700297 public ProxSensor(AlwaysOnDisplayPolicy policy) {
298 mPolicy = policy;
Adrian Roos6023ccb2017-06-28 16:22:02 +0200299 mCooldownTimer = new AlarmTimeout(mAlarmManager, this::updateRegistered,
300 "prox_cooldown", mHandler);
Lucas Dupinf61c1042019-07-19 12:16:25 -0700301
302 // The default prox sensor can be noisy, so let's use a prox gated brightness sensor
303 // if available.
304 Sensor sensor = DozeSensors.findSensorWithType(mSensorManager,
305 mContext.getString(R.string.doze_brightness_sensor_type));
Lucas Dupincf06eb32019-08-12 14:14:08 -0700306 mUsingBrightnessSensor = sensor != null;
Lucas Dupinf61c1042019-07-19 12:16:25 -0700307 if (sensor == null) {
308 sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
309 }
310 mSensor = sensor;
Adrian Roos6023ccb2017-06-28 16:22:02 +0200311 }
312
313 void setRequested(boolean requested) {
314 if (mRequested == requested) {
Adrian Roos67cca742017-04-13 16:52:51 -0700315 // Send an update even if we don't re-register.
316 mHandler.post(() -> {
317 if (mCurrentlyFar != null) {
318 mProxCallback.accept(mCurrentlyFar);
319 }
320 });
321 return;
322 }
Adrian Roos6023ccb2017-06-28 16:22:02 +0200323 mRequested = requested;
324 updateRegistered();
325 }
326
327 private void updateRegistered() {
328 setRegistered(mRequested && !mCooldownTimer.isScheduled());
329 }
330
331 private void setRegistered(boolean register) {
332 if (mRegistered == register) {
333 return;
334 }
Adrian Roos67cca742017-04-13 16:52:51 -0700335 if (register) {
Lucas Dupincf06eb32019-08-12 14:14:08 -0700336 mRegistered = mSensorManager.registerListener(this, mSensor,
Adrian Roos67cca742017-04-13 16:52:51 -0700337 SensorManager.SENSOR_DELAY_NORMAL, mHandler);
338 } else {
339 mSensorManager.unregisterListener(this);
340 mRegistered = false;
341 mCurrentlyFar = null;
342 }
343 }
344
345 @Override
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800346 public void onSensorChanged(android.hardware.SensorEvent event) {
Lucas Dupin58543842018-02-15 14:00:54 -0800347 if (DEBUG) Log.d(TAG, "onSensorChanged " + event);
348
Lucas Dupincf06eb32019-08-12 14:14:08 -0700349 if (mUsingBrightnessSensor) {
350 // The custom brightness sensor is gated by the proximity sensor and will return 0
351 // whenever prox is covered.
352 mCurrentlyFar = event.values[0] > 0;
353 } else {
354 mCurrentlyFar = event.values[0] >= event.sensor.getMaximumRange();
355 }
Adrian Roos67cca742017-04-13 16:52:51 -0700356 mProxCallback.accept(mCurrentlyFar);
Adrian Roos6023ccb2017-06-28 16:22:02 +0200357
358 long now = SystemClock.elapsedRealtime();
Adrian Roos8f72b3c2017-07-07 12:20:21 +0200359 if (mCurrentlyFar == null) {
360 // Sensor has been unregistered by the proxCallback. Do nothing.
361 } else if (!mCurrentlyFar) {
Adrian Roos6023ccb2017-06-28 16:22:02 +0200362 mLastNear = now;
jackqdyulei8443dd02017-08-24 16:14:34 -0700363 } else if (mCurrentlyFar && now - mLastNear < mPolicy.proxCooldownTriggerMs) {
Adrian Roos6023ccb2017-06-28 16:22:02 +0200364 // If the last near was very recent, we might be using more power for prox
365 // wakeups than we're saving from turning of the screen. Instead, turn it off
366 // for a while.
jackqdyulei8443dd02017-08-24 16:14:34 -0700367 mCooldownTimer.schedule(mPolicy.proxCooldownPeriodMs,
368 AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
Adrian Roos6023ccb2017-06-28 16:22:02 +0200369 updateRegistered();
370 }
Adrian Roos67cca742017-04-13 16:52:51 -0700371 }
372
373 @Override
374 public void onAccuracyChanged(Sensor sensor, int accuracy) {
375 }
Adrian Roos2ca9cd72017-07-03 15:14:37 +0200376
377 @Override
378 public String toString() {
Lucas Dupinf61c1042019-07-19 12:16:25 -0700379 return String.format("{registered=%s, requested=%s, coolingDown=%s, currentlyFar=%s,"
380 + " sensor=%s}", mRegistered, mRequested, mCooldownTimer.isScheduled(),
381 mCurrentlyFar, mSensor);
Adrian Roos2ca9cd72017-07-03 15:14:37 +0200382 }
Adrian Roos67cca742017-04-13 16:52:51 -0700383 }
384
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800385 @VisibleForTesting
386 class TriggerSensor extends TriggerEventListener {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700387 final Sensor mSensor;
388 final boolean mConfigured;
389 final int mPulseReason;
Lucas Dupinfac2e8e2019-06-27 16:10:19 -0700390 private final String mSetting;
391 private final boolean mReportsTouchCoordinates;
392 private final boolean mSettingDefault;
393 private final boolean mRequiresTouchscreen;
394 private final boolean mSensorPerformsProxCheck;
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700395
Lucas Dupin323f9ff2018-08-27 16:55:56 -0700396 protected boolean mRequested;
397 protected boolean mRegistered;
398 protected boolean mDisabled;
lpeter8a5f4702019-01-18 16:53:07 +0800399 protected boolean mIgnoresSetting;
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700400
Adrian Roos25c7a582017-06-02 12:50:38 -0700401 public TriggerSensor(Sensor sensor, String setting, boolean configured, int pulseReason,
Adrian Roos98d31982017-08-02 20:50:16 +0200402 boolean reportsTouchCoordinates, boolean requiresTouchscreen) {
Adrian Roosd0963a02017-05-15 14:33:37 -0700403 this(sensor, setting, true /* settingDef */, configured, pulseReason,
Adrian Roos98d31982017-08-02 20:50:16 +0200404 reportsTouchCoordinates, requiresTouchscreen);
Adrian Roosd0963a02017-05-15 14:33:37 -0700405 }
406
407 public TriggerSensor(Sensor sensor, String setting, boolean settingDef,
Adrian Roos98d31982017-08-02 20:50:16 +0200408 boolean configured, int pulseReason, boolean reportsTouchCoordinates,
409 boolean requiresTouchscreen) {
lpeter8a5f4702019-01-18 16:53:07 +0800410 this(sensor, setting, settingDef, configured, pulseReason, reportsTouchCoordinates,
Lucas Dupinfac2e8e2019-06-27 16:10:19 -0700411 requiresTouchscreen, false /* ignoresSetting */,
412 false /* sensorPerformsProxCheck */);
lpeter8a5f4702019-01-18 16:53:07 +0800413 }
414
415 private TriggerSensor(Sensor sensor, String setting, boolean settingDef,
416 boolean configured, int pulseReason, boolean reportsTouchCoordinates,
Lucas Dupinfac2e8e2019-06-27 16:10:19 -0700417 boolean requiresTouchscreen, boolean ignoresSetting,
418 boolean sensorPerformsProxCheck) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700419 mSensor = sensor;
420 mSetting = setting;
Adrian Roosd0963a02017-05-15 14:33:37 -0700421 mSettingDefault = settingDef;
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700422 mConfigured = configured;
423 mPulseReason = pulseReason;
Adrian Roos25c7a582017-06-02 12:50:38 -0700424 mReportsTouchCoordinates = reportsTouchCoordinates;
Adrian Roos98d31982017-08-02 20:50:16 +0200425 mRequiresTouchscreen = requiresTouchscreen;
lpeter8a5f4702019-01-18 16:53:07 +0800426 mIgnoresSetting = ignoresSetting;
Lucas Dupinfac2e8e2019-06-27 16:10:19 -0700427 mSensorPerformsProxCheck = sensorPerformsProxCheck;
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700428 }
429
430 public void setListening(boolean listen) {
431 if (mRequested == listen) return;
432 mRequested = listen;
Lucas Dupin3174c662019-07-15 15:49:54 -0700433 updateListening();
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700434 }
435
436 public void setDisabled(boolean disabled) {
437 if (mDisabled == disabled) return;
438 mDisabled = disabled;
Lucas Dupin3174c662019-07-15 15:49:54 -0700439 updateListening();
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700440 }
441
lpeter8a5f4702019-01-18 16:53:07 +0800442 public void ignoreSetting(boolean ignored) {
443 if (mIgnoresSetting == ignored) return;
444 mIgnoresSetting = ignored;
Lucas Dupin3174c662019-07-15 15:49:54 -0700445 updateListening();
lpeter8a5f4702019-01-18 16:53:07 +0800446 }
447
Lucas Dupin3174c662019-07-15 15:49:54 -0700448 public void updateListening() {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700449 if (!mConfigured || mSensor == null) return;
lpeter8a5f4702019-01-18 16:53:07 +0800450 if (mRequested && !mDisabled && (enabledBySetting() || mIgnoresSetting)
451 && !mRegistered) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700452 mRegistered = mSensorManager.requestTriggerSensor(this, mSensor);
453 if (DEBUG) Log.d(TAG, "requestTriggerSensor " + mRegistered);
454 } else if (mRegistered) {
455 final boolean rt = mSensorManager.cancelTriggerSensor(this, mSensor);
456 if (DEBUG) Log.d(TAG, "cancelTriggerSensor " + rt);
457 mRegistered = false;
458 }
459 }
460
Lucas Dupin323f9ff2018-08-27 16:55:56 -0700461 protected boolean enabledBySetting() {
Jerry Chang5d3eb4472018-12-21 11:49:06 +0800462 if (!mConfig.enabled(UserHandle.USER_CURRENT)) {
463 return false;
464 } else if (TextUtils.isEmpty(mSetting)) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700465 return true;
466 }
Adrian Roosd0963a02017-05-15 14:33:37 -0700467 return Settings.Secure.getIntForUser(mResolver, mSetting, mSettingDefault ? 1 : 0,
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700468 UserHandle.USER_CURRENT) != 0;
469 }
470
471 @Override
472 public String toString() {
473 return new StringBuilder("{mRegistered=").append(mRegistered)
474 .append(", mRequested=").append(mRequested)
475 .append(", mDisabled=").append(mDisabled)
476 .append(", mConfigured=").append(mConfigured)
lpeter8a5f4702019-01-18 16:53:07 +0800477 .append(", mIgnoresSetting=").append(mIgnoresSetting)
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700478 .append(", mSensor=").append(mSensor).append("}").toString();
479 }
480
481 @Override
482 @AnyThread
483 public void onTrigger(TriggerEvent event) {
Adrian Roos2ca9cd72017-07-03 15:14:37 +0200484 DozeLog.traceSensor(mContext, mPulseReason);
Adrian Roos79bacbb2016-10-26 11:00:12 -0700485 mHandler.post(mWakeLock.wrap(() -> {
Adrian Roosd6ec13132016-10-27 11:50:47 -0700486 if (DEBUG) Log.d(TAG, "onTrigger: " + triggerEventToString(event));
Lucas Dupin3d951752018-10-10 12:00:40 -0700487 if (mSensor != null && mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700488 int subType = (int) event.values[0];
489 MetricsLogger.action(
Adrian Roos79bacbb2016-10-26 11:00:12 -0700490 mContext, MetricsProto.MetricsEvent.ACTION_AMBIENT_GESTURE,
491 subType);
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700492 }
493
494 mRegistered = false;
Adrian Roos25c7a582017-06-02 12:50:38 -0700495 float screenX = -1;
496 float screenY = -1;
497 if (mReportsTouchCoordinates && event.values.length >= 2) {
498 screenX = event.values[0];
499 screenY = event.values[1];
500 }
Lucas Dupinfac2e8e2019-06-27 16:10:19 -0700501 mCallback.onSensorPulse(mPulseReason, mSensorPerformsProxCheck, screenX, screenY,
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800502 event.values);
Lucas Dupin65104382018-12-04 11:53:42 -0800503 if (!mRegistered) {
Lucas Dupin3174c662019-07-15 15:49:54 -0700504 updateListening(); // reregister, this sensor only fires once
Lucas Dupin65104382018-12-04 11:53:42 -0800505 }
Adrian Roos79bacbb2016-10-26 11:00:12 -0700506 }));
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700507 }
508
Lucas Dupinfac2e8e2019-06-27 16:10:19 -0700509 /**
510 * If the sensor itself performs proximity checks, to avoid pocket dialing.
511 * Gated sensors don't need to be stopped when the {@link DozeMachine} is
512 * {@link DozeMachine.State#DOZE_AOD_PAUSED}.
513 */
514 public boolean performsProxCheck() {
515 return mSensorPerformsProxCheck;
516 }
517
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700518 public void registerSettingsObserver(ContentObserver settingsObserver) {
519 if (mConfigured && !TextUtils.isEmpty(mSetting)) {
520 mResolver.registerContentObserver(
521 Settings.Secure.getUriFor(mSetting), false /* descendants */,
522 mSettingsObserver, UserHandle.USER_ALL);
523 }
524 }
525
Lucas Dupin323f9ff2018-08-27 16:55:56 -0700526 protected String triggerEventToString(TriggerEvent event) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700527 if (event == null) return null;
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800528 final StringBuilder sb = new StringBuilder("SensorEvent[")
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700529 .append(event.timestamp).append(',')
530 .append(event.sensor.getName());
531 if (event.values != null) {
532 for (int i = 0; i < event.values.length; i++) {
533 sb.append(',').append(event.values[i]);
534 }
535 }
536 return sb.append(']').toString();
537 }
538 }
539
Lucas Dupin3d951752018-10-10 12:00:40 -0700540 /**
Kevin Chynf7c39032018-10-11 00:44:39 -0700541 * A Sensor that is injected via plugin.
Lucas Dupin3d951752018-10-10 12:00:40 -0700542 */
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800543 @VisibleForTesting
544 class PluginSensor extends TriggerSensor implements SensorManagerPlugin.SensorEventListener {
Lucas Dupin3d951752018-10-10 12:00:40 -0700545
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800546 final SensorManagerPlugin.Sensor mPluginSensor;
547 private long mDebounce;
Lucas Dupin3d951752018-10-10 12:00:40 -0700548
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800549 PluginSensor(SensorManagerPlugin.Sensor sensor, String setting, boolean configured,
Lucas Dupin3d951752018-10-10 12:00:40 -0700550 int pulseReason, boolean reportsTouchCoordinates, boolean requiresTouchscreen) {
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800551 this(sensor, setting, configured, pulseReason, reportsTouchCoordinates,
552 requiresTouchscreen, 0L /* debounce */);
553 }
554
555 PluginSensor(SensorManagerPlugin.Sensor sensor, String setting, boolean configured,
556 int pulseReason, boolean reportsTouchCoordinates, boolean requiresTouchscreen,
557 long debounce) {
Lucas Dupin3d951752018-10-10 12:00:40 -0700558 super(null, setting, configured, pulseReason, reportsTouchCoordinates,
559 requiresTouchscreen);
560 mPluginSensor = sensor;
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800561 mDebounce = debounce;
Lucas Dupin3d951752018-10-10 12:00:40 -0700562 }
563
564 @Override
Lucas Dupin3174c662019-07-15 15:49:54 -0700565 public void updateListening() {
Lucas Dupin3d951752018-10-10 12:00:40 -0700566 if (!mConfigured) return;
567 AsyncSensorManager asyncSensorManager = (AsyncSensorManager) mSensorManager;
lpeter8a5f4702019-01-18 16:53:07 +0800568 if (mRequested && !mDisabled && (enabledBySetting() || mIgnoresSetting)
569 && !mRegistered) {
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800570 asyncSensorManager.registerPluginListener(mPluginSensor, this);
Lucas Dupin3d951752018-10-10 12:00:40 -0700571 mRegistered = true;
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800572 if (DEBUG) Log.d(TAG, "registerPluginListener");
Lucas Dupin3d951752018-10-10 12:00:40 -0700573 } else if (mRegistered) {
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800574 asyncSensorManager.unregisterPluginListener(mPluginSensor, this);
Lucas Dupin3d951752018-10-10 12:00:40 -0700575 mRegistered = false;
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800576 if (DEBUG) Log.d(TAG, "unregisterPluginListener");
Lucas Dupin3d951752018-10-10 12:00:40 -0700577 }
578 }
579
580 @Override
581 public String toString() {
582 return new StringBuilder("{mRegistered=").append(mRegistered)
583 .append(", mRequested=").append(mRequested)
584 .append(", mDisabled=").append(mDisabled)
585 .append(", mConfigured=").append(mConfigured)
lpeter8a5f4702019-01-18 16:53:07 +0800586 .append(", mIgnoresSetting=").append(mIgnoresSetting)
Lucas Dupin3d951752018-10-10 12:00:40 -0700587 .append(", mSensor=").append(mPluginSensor).append("}").toString();
588 }
589
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800590 private String triggerEventToString(SensorManagerPlugin.SensorEvent event) {
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800591 if (event == null) return null;
592 final StringBuilder sb = new StringBuilder("PluginTriggerEvent[")
593 .append(event.getSensor()).append(',')
594 .append(event.getVendorType());
595 if (event.getValues() != null) {
596 for (int i = 0; i < event.getValues().length; i++) {
597 sb.append(',').append(event.getValues()[i]);
598 }
599 }
600 return sb.append(']').toString();
Lucas Dupin323f9ff2018-08-27 16:55:56 -0700601 }
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800602
603 @Override
604 public void onSensorChanged(SensorManagerPlugin.SensorEvent event) {
605 DozeLog.traceSensor(mContext, mPulseReason);
606 mHandler.post(mWakeLock.wrap(() -> {
607 final long now = SystemClock.uptimeMillis();
608 if (now < mDebounceFrom + mDebounce) {
Lucas Dupinbca7ec72019-05-30 10:24:54 -0700609 Log.d(TAG, "onSensorEvent dropped: " + triggerEventToString(event));
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800610 return;
611 }
612 if (DEBUG) Log.d(TAG, "onSensorEvent: " + triggerEventToString(event));
613 mCallback.onSensorPulse(mPulseReason, true /* sensorPerformsProxCheck */, -1, -1,
614 event.getValues());
615 }));
616 }
Lucas Dupin323f9ff2018-08-27 16:55:56 -0700617 }
618
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700619 public interface Callback {
Adrian Roosd6ec13132016-10-27 11:50:47 -0700620
621 /**
622 * Called when a sensor requests a pulse
Lucas Dupin3d053532019-01-29 12:35:22 -0800623 * @param pulseReason Requesting sensor, e.g. {@link DozeLog#REASON_SENSOR_PICKUP}
Adrian Roosd6ec13132016-10-27 11:50:47 -0700624 * @param sensorPerformedProxCheck true if the sensor already checked for FAR proximity.
Adrian Roos25c7a582017-06-02 12:50:38 -0700625 * @param screenX the location on the screen where the sensor fired or -1
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800626 * if the sensor doesn't support reporting screen locations.
Adrian Roos25c7a582017-06-02 12:50:38 -0700627 * @param screenY the location on the screen where the sensor fired or -1
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800628 * @param rawValues raw values array from the event.
Adrian Roosd6ec13132016-10-27 11:50:47 -0700629 */
Adrian Roos25c7a582017-06-02 12:50:38 -0700630 void onSensorPulse(int pulseReason, boolean sensorPerformedProxCheck,
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800631 float screenX, float screenY, float[] rawValues);
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700632 }
633}