blob: c5799cc6738b763705b991316e9c68ac7690147a [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 Dupin3d951752018-10-10 12:00:40 -070046import com.android.systemui.plugins.SensorManagerPlugin;
Adrian Roosff2c4562016-11-03 12:13:36 -070047import com.android.systemui.statusbar.phone.DozeParameters;
Adrian Roos6023ccb2017-06-28 16:22:02 +020048import com.android.systemui.util.AlarmTimeout;
Lucas Dupin3d951752018-10-10 12:00:40 -070049import com.android.systemui.util.AsyncSensorManager;
Adrian Roosc1b50322017-02-27 21:07:58 +010050import com.android.systemui.util.wakelock.WakeLock;
Adrian Roosff2c4562016-11-03 12:13:36 -070051
52import java.io.PrintWriter;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070053import java.util.List;
Adrian Roos67cca742017-04-13 16:52:51 -070054import java.util.function.Consumer;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070055
56public class DozeSensors {
57
58 private static final boolean DEBUG = DozeService.DEBUG;
59
60 private static final String TAG = "DozeSensors";
61
62 private final Context mContext;
Adrian Roos6023ccb2017-06-28 16:22:02 +020063 private final AlarmManager mAlarmManager;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070064 private final SensorManager mSensorManager;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070065 private final ContentResolver mResolver;
66 private final TriggerSensor mPickupSensor;
67 private final DozeParameters mDozeParameters;
68 private final AmbientDisplayConfiguration mConfig;
Adrian Roosc1b50322017-02-27 21:07:58 +010069 private final WakeLock mWakeLock;
Adrian Roos67cca742017-04-13 16:52:51 -070070 private final Consumer<Boolean> mProxCallback;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070071 private final Callback mCallback;
Lucas Dupin8a13aa72019-02-22 12:45:21 -080072 @VisibleForTesting
73 protected final TriggerSensor[] mSensors;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070074
75 private final Handler mHandler = new Handler();
Adrian Roos67cca742017-04-13 16:52:51 -070076 private final ProxSensor mProxSensor;
Lucas Dupin8a13aa72019-02-22 12:45:21 -080077 private long mDebounceFrom;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070078
Adrian Roos6023ccb2017-06-28 16:22:02 +020079 public DozeSensors(Context context, AlarmManager alarmManager, SensorManager sensorManager,
Lucas Dupin323f9ff2018-08-27 16:55:56 -070080 DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock,
Lucas Dupinb2d9f482018-11-16 18:55:13 -080081 Callback callback, Consumer<Boolean> proxCallback, AlwaysOnDisplayPolicy policy) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -070082 mContext = context;
Adrian Roos6023ccb2017-06-28 16:22:02 +020083 mAlarmManager = alarmManager;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070084 mSensorManager = sensorManager;
85 mDozeParameters = dozeParameters;
86 mConfig = config;
87 mWakeLock = wakeLock;
Adrian Roos67cca742017-04-13 16:52:51 -070088 mProxCallback = proxCallback;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070089 mResolver = mContext.getContentResolver();
90
Lucas Dupin70bda672018-12-27 15:43:40 -080091 boolean alwaysOn = mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT);
Adrian Roosea8d6ae2016-10-26 10:40:12 -070092 mSensors = new TriggerSensor[] {
93 new TriggerSensor(
94 mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION),
95 null /* setting */,
96 dozeParameters.getPulseOnSigMotion(),
Adrian Roos98d31982017-08-02 20:50:16 +020097 DozeLog.PULSE_REASON_SENSOR_SIGMOTION, false /* touchCoords */,
98 false /* touchscreen */),
Adrian Roosea8d6ae2016-10-26 10:40:12 -070099 mPickupSensor = new TriggerSensor(
100 mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE),
Lucas Dupin4359b552018-08-09 15:07:54 -0700101 Settings.Secure.DOZE_PICK_UP_GESTURE,
102 config.dozePickupSensorAvailable(),
Lucas Dupin3d053532019-01-29 12:35:22 -0800103 DozeLog.REASON_SENSOR_PICKUP, false /* touchCoords */,
Adrian Roos98d31982017-08-02 20:50:16 +0200104 false /* touchscreen */),
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700105 new TriggerSensor(
106 findSensorWithType(config.doubleTapSensorType()),
Lucas Dupin4359b552018-08-09 15:07:54 -0700107 Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700108 true /* configured */,
Lucas Dupin3d053532019-01-29 12:35:22 -0800109 DozeLog.REASON_SENSOR_DOUBLE_TAP,
Adrian Roos98d31982017-08-02 20:50:16 +0200110 dozeParameters.doubleTapReportsTouchCoordinates(),
111 true /* touchscreen */),
Adrian Roosd0963a02017-05-15 14:33:37 -0700112 new TriggerSensor(
Lucas Dupind43bf702019-01-15 13:40:42 -0800113 findSensorWithType(config.tapSensorType()),
114 Settings.Secure.DOZE_TAP_SCREEN_GESTURE,
115 true /* configured */,
Lucas Dupin3d053532019-01-29 12:35:22 -0800116 DozeLog.REASON_SENSOR_TAP,
Lucas Dupind43bf702019-01-15 13:40:42 -0800117 false /* reports touch coordinates */,
118 true /* touchscreen */),
119 new TriggerSensor(
Adrian Roosd0963a02017-05-15 14:33:37 -0700120 findSensorWithType(config.longPressSensorType()),
121 Settings.Secure.DOZE_PULSE_ON_LONG_PRESS,
122 false /* settingDef */,
123 true /* configured */,
124 DozeLog.PULSE_REASON_SENSOR_LONG_PRESS,
Adrian Roos98d31982017-08-02 20:50:16 +0200125 true /* reports touch coordinates */,
126 true /* touchscreen */),
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800127 new PluginSensor(
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800128 new SensorManagerPlugin.Sensor(TYPE_WAKE_DISPLAY),
129 Settings.Secure.DOZE_WAKE_SCREEN_GESTURE,
Lucas Dupin70bda672018-12-27 15:43:40 -0800130 mConfig.wakeScreenGestureAvailable() && alwaysOn,
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800131 DozeLog.REASON_SENSOR_WAKE_UP,
132 false /* reports touch coordinates */,
133 false /* touchscreen */),
Lucas Dupinde64ee02018-12-21 14:45:12 -0800134 new PluginSensor(
135 new SensorManagerPlugin.Sensor(TYPE_WAKE_LOCK_SCREEN),
Lucas Dupine3218c12019-01-18 16:48:41 -0800136 Settings.Secure.DOZE_WAKE_SCREEN_GESTURE,
Lucas Dupine076c6d2019-02-13 13:53:10 -0800137 mConfig.wakeScreenGestureAvailable() && alwaysOn,
Lucas Dupinde64ee02018-12-21 14:45:12 -0800138 DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN,
139 false /* reports touch coordinates */,
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800140 false /* touchscreen */, mConfig.getWakeLockScreenDebounce()),
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700141 };
Adrian Roos67cca742017-04-13 16:52:51 -0700142
jackqdyulei8443dd02017-08-24 16:14:34 -0700143 mProxSensor = new ProxSensor(policy);
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700144 mCallback = callback;
145 }
146
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800147 /**
148 * Temporarily disable some sensors to avoid turning on the device while the user is
149 * turning it off.
150 */
151 public void requestTemporaryDisable() {
152 mDebounceFrom = SystemClock.uptimeMillis();
153 }
154
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700155 private Sensor findSensorWithType(String type) {
Adrian Roos2981eb02017-05-26 18:40:09 -0700156 return findSensorWithType(mSensorManager, type);
157 }
158
159 static Sensor findSensorWithType(SensorManager sensorManager, String type) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700160 if (TextUtils.isEmpty(type)) {
161 return null;
162 }
Adrian Roos2981eb02017-05-26 18:40:09 -0700163 List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL);
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700164 for (Sensor s : sensorList) {
165 if (type.equals(s.getStringType())) {
166 return s;
167 }
168 }
169 return null;
170 }
171
Adrian Roosd6ec13132016-10-27 11:50:47 -0700172 public void setListening(boolean listen) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700173 for (TriggerSensor s : mSensors) {
174 s.setListening(listen);
175 if (listen) {
176 s.registerSettingsObserver(mSettingsObserver);
177 }
178 }
179 if (!listen) {
180 mResolver.unregisterContentObserver(mSettingsObserver);
181 }
182 }
183
Adrian Roos98d31982017-08-02 20:50:16 +0200184 /** Set the listening state of only the sensors that require the touchscreen. */
185 public void setTouchscreenSensorsListening(boolean listening) {
186 for (TriggerSensor sensor : mSensors) {
187 if (sensor.mRequiresTouchscreen) {
188 sensor.setListening(listening);
189 }
190 }
191 }
192
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700193 public void reregisterAllSensors() {
194 for (TriggerSensor s : mSensors) {
195 s.setListening(false);
196 }
197 for (TriggerSensor s : mSensors) {
198 s.setListening(true);
199 }
200 }
201
202 public void onUserSwitched() {
203 for (TriggerSensor s : mSensors) {
204 s.updateListener();
205 }
206 }
207
Adrian Roos67cca742017-04-13 16:52:51 -0700208 public void setProxListening(boolean listen) {
Adrian Roos6023ccb2017-06-28 16:22:02 +0200209 mProxSensor.setRequested(listen);
Adrian Roos67cca742017-04-13 16:52:51 -0700210 }
211
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700212 private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
213 @Override
214 public void onChange(boolean selfChange, Uri uri, int userId) {
215 if (userId != ActivityManager.getCurrentUser()) {
216 return;
217 }
218 for (TriggerSensor s : mSensors) {
219 s.updateListener();
220 }
221 }
222 };
223
224 public void setDisableSensorsInterferingWithProximity(boolean disable) {
225 mPickupSensor.setDisabled(disable);
226 }
227
lpeter8a5f4702019-01-18 16:53:07 +0800228 /** Ignore the setting value of only the sensors that require the touchscreen. */
229 public void ignoreTouchScreenSensorsSettingInterferingWithDocking(boolean ignore) {
230 for (TriggerSensor sensor : mSensors) {
231 if (sensor.mRequiresTouchscreen) {
232 sensor.ignoreSetting(ignore);
233 }
234 }
235 }
236
Adrian Roosff2c4562016-11-03 12:13:36 -0700237 /** Dump current state */
238 public void dump(PrintWriter pw) {
239 for (TriggerSensor s : mSensors) {
240 pw.print("Sensor: "); pw.println(s.toString());
241 }
Adrian Roos2ca9cd72017-07-03 15:14:37 +0200242 pw.print("ProxSensor: "); pw.println(mProxSensor.toString());
Adrian Roosff2c4562016-11-03 12:13:36 -0700243 }
244
Adrian Roos70da03a2017-07-24 16:42:57 +0200245 /**
246 * @return true if prox is currently far, false if near or null if unknown.
247 */
248 public Boolean isProximityCurrentlyFar() {
249 return mProxSensor.mCurrentlyFar;
250 }
251
Adrian Roos67cca742017-04-13 16:52:51 -0700252 private class ProxSensor implements SensorEventListener {
253
Adrian Roos6023ccb2017-06-28 16:22:02 +0200254 boolean mRequested;
Adrian Roos67cca742017-04-13 16:52:51 -0700255 boolean mRegistered;
256 Boolean mCurrentlyFar;
Adrian Roos6023ccb2017-06-28 16:22:02 +0200257 long mLastNear;
258 final AlarmTimeout mCooldownTimer;
jackqdyulei8443dd02017-08-24 16:14:34 -0700259 final AlwaysOnDisplayPolicy mPolicy;
Adrian Roos67cca742017-04-13 16:52:51 -0700260
Adrian Roos6023ccb2017-06-28 16:22:02 +0200261
jackqdyulei8443dd02017-08-24 16:14:34 -0700262 public ProxSensor(AlwaysOnDisplayPolicy policy) {
263 mPolicy = policy;
Adrian Roos6023ccb2017-06-28 16:22:02 +0200264 mCooldownTimer = new AlarmTimeout(mAlarmManager, this::updateRegistered,
265 "prox_cooldown", mHandler);
266 }
267
268 void setRequested(boolean requested) {
269 if (mRequested == requested) {
Adrian Roos67cca742017-04-13 16:52:51 -0700270 // Send an update even if we don't re-register.
271 mHandler.post(() -> {
272 if (mCurrentlyFar != null) {
273 mProxCallback.accept(mCurrentlyFar);
274 }
275 });
276 return;
277 }
Adrian Roos6023ccb2017-06-28 16:22:02 +0200278 mRequested = requested;
279 updateRegistered();
280 }
281
282 private void updateRegistered() {
283 setRegistered(mRequested && !mCooldownTimer.isScheduled());
284 }
285
286 private void setRegistered(boolean register) {
287 if (mRegistered == register) {
288 return;
289 }
Adrian Roos67cca742017-04-13 16:52:51 -0700290 if (register) {
291 mRegistered = mSensorManager.registerListener(this,
292 mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY),
293 SensorManager.SENSOR_DELAY_NORMAL, mHandler);
294 } else {
295 mSensorManager.unregisterListener(this);
296 mRegistered = false;
297 mCurrentlyFar = null;
298 }
299 }
300
301 @Override
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800302 public void onSensorChanged(android.hardware.SensorEvent event) {
Lucas Dupin58543842018-02-15 14:00:54 -0800303 if (DEBUG) Log.d(TAG, "onSensorChanged " + event);
304
Adrian Roos67cca742017-04-13 16:52:51 -0700305 mCurrentlyFar = event.values[0] >= event.sensor.getMaximumRange();
306 mProxCallback.accept(mCurrentlyFar);
Adrian Roos6023ccb2017-06-28 16:22:02 +0200307
308 long now = SystemClock.elapsedRealtime();
Adrian Roos8f72b3c2017-07-07 12:20:21 +0200309 if (mCurrentlyFar == null) {
310 // Sensor has been unregistered by the proxCallback. Do nothing.
311 } else if (!mCurrentlyFar) {
Adrian Roos6023ccb2017-06-28 16:22:02 +0200312 mLastNear = now;
jackqdyulei8443dd02017-08-24 16:14:34 -0700313 } else if (mCurrentlyFar && now - mLastNear < mPolicy.proxCooldownTriggerMs) {
Adrian Roos6023ccb2017-06-28 16:22:02 +0200314 // If the last near was very recent, we might be using more power for prox
315 // wakeups than we're saving from turning of the screen. Instead, turn it off
316 // for a while.
jackqdyulei8443dd02017-08-24 16:14:34 -0700317 mCooldownTimer.schedule(mPolicy.proxCooldownPeriodMs,
318 AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
Adrian Roos6023ccb2017-06-28 16:22:02 +0200319 updateRegistered();
320 }
Adrian Roos67cca742017-04-13 16:52:51 -0700321 }
322
323 @Override
324 public void onAccuracyChanged(Sensor sensor, int accuracy) {
325 }
Adrian Roos2ca9cd72017-07-03 15:14:37 +0200326
327 @Override
328 public String toString() {
329 return String.format("{registered=%s, requested=%s, coolingDown=%s, currentlyFar=%s}",
330 mRegistered, mRequested, mCooldownTimer.isScheduled(), mCurrentlyFar);
331 }
Adrian Roos67cca742017-04-13 16:52:51 -0700332 }
333
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800334 @VisibleForTesting
335 class TriggerSensor extends TriggerEventListener {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700336 final Sensor mSensor;
337 final boolean mConfigured;
338 final int mPulseReason;
339 final String mSetting;
Adrian Roos25c7a582017-06-02 12:50:38 -0700340 final boolean mReportsTouchCoordinates;
Adrian Roosd0963a02017-05-15 14:33:37 -0700341 final boolean mSettingDefault;
Adrian Roos98d31982017-08-02 20:50:16 +0200342 final boolean mRequiresTouchscreen;
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700343
Lucas Dupin323f9ff2018-08-27 16:55:56 -0700344 protected boolean mRequested;
345 protected boolean mRegistered;
346 protected boolean mDisabled;
lpeter8a5f4702019-01-18 16:53:07 +0800347 protected boolean mIgnoresSetting;
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700348
Adrian Roos25c7a582017-06-02 12:50:38 -0700349 public TriggerSensor(Sensor sensor, String setting, boolean configured, int pulseReason,
Adrian Roos98d31982017-08-02 20:50:16 +0200350 boolean reportsTouchCoordinates, boolean requiresTouchscreen) {
Adrian Roosd0963a02017-05-15 14:33:37 -0700351 this(sensor, setting, true /* settingDef */, configured, pulseReason,
Adrian Roos98d31982017-08-02 20:50:16 +0200352 reportsTouchCoordinates, requiresTouchscreen);
Adrian Roosd0963a02017-05-15 14:33:37 -0700353 }
354
355 public TriggerSensor(Sensor sensor, String setting, boolean settingDef,
Adrian Roos98d31982017-08-02 20:50:16 +0200356 boolean configured, int pulseReason, boolean reportsTouchCoordinates,
357 boolean requiresTouchscreen) {
lpeter8a5f4702019-01-18 16:53:07 +0800358 this(sensor, setting, settingDef, configured, pulseReason, reportsTouchCoordinates,
359 requiresTouchscreen, false /* ignoresSetting */);
360 }
361
362 private TriggerSensor(Sensor sensor, String setting, boolean settingDef,
363 boolean configured, int pulseReason, boolean reportsTouchCoordinates,
364 boolean requiresTouchscreen, boolean ignoresSetting) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700365 mSensor = sensor;
366 mSetting = setting;
Adrian Roosd0963a02017-05-15 14:33:37 -0700367 mSettingDefault = settingDef;
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700368 mConfigured = configured;
369 mPulseReason = pulseReason;
Adrian Roos25c7a582017-06-02 12:50:38 -0700370 mReportsTouchCoordinates = reportsTouchCoordinates;
Adrian Roos98d31982017-08-02 20:50:16 +0200371 mRequiresTouchscreen = requiresTouchscreen;
lpeter8a5f4702019-01-18 16:53:07 +0800372 mIgnoresSetting = ignoresSetting;
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700373 }
374
375 public void setListening(boolean listen) {
376 if (mRequested == listen) return;
377 mRequested = listen;
378 updateListener();
379 }
380
381 public void setDisabled(boolean disabled) {
382 if (mDisabled == disabled) return;
383 mDisabled = disabled;
384 updateListener();
385 }
386
lpeter8a5f4702019-01-18 16:53:07 +0800387 public void ignoreSetting(boolean ignored) {
388 if (mIgnoresSetting == ignored) return;
389 mIgnoresSetting = ignored;
390 updateListener();
391 }
392
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700393 public void updateListener() {
394 if (!mConfigured || mSensor == null) return;
lpeter8a5f4702019-01-18 16:53:07 +0800395 if (mRequested && !mDisabled && (enabledBySetting() || mIgnoresSetting)
396 && !mRegistered) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700397 mRegistered = mSensorManager.requestTriggerSensor(this, mSensor);
398 if (DEBUG) Log.d(TAG, "requestTriggerSensor " + mRegistered);
399 } else if (mRegistered) {
400 final boolean rt = mSensorManager.cancelTriggerSensor(this, mSensor);
401 if (DEBUG) Log.d(TAG, "cancelTriggerSensor " + rt);
402 mRegistered = false;
403 }
404 }
405
Lucas Dupin323f9ff2018-08-27 16:55:56 -0700406 protected boolean enabledBySetting() {
Jerry Chang5d3eb4472018-12-21 11:49:06 +0800407 if (!mConfig.enabled(UserHandle.USER_CURRENT)) {
408 return false;
409 } else if (TextUtils.isEmpty(mSetting)) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700410 return true;
411 }
Adrian Roosd0963a02017-05-15 14:33:37 -0700412 return Settings.Secure.getIntForUser(mResolver, mSetting, mSettingDefault ? 1 : 0,
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700413 UserHandle.USER_CURRENT) != 0;
414 }
415
416 @Override
417 public String toString() {
418 return new StringBuilder("{mRegistered=").append(mRegistered)
419 .append(", mRequested=").append(mRequested)
420 .append(", mDisabled=").append(mDisabled)
421 .append(", mConfigured=").append(mConfigured)
lpeter8a5f4702019-01-18 16:53:07 +0800422 .append(", mIgnoresSetting=").append(mIgnoresSetting)
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700423 .append(", mSensor=").append(mSensor).append("}").toString();
424 }
425
426 @Override
427 @AnyThread
428 public void onTrigger(TriggerEvent event) {
Adrian Roos2ca9cd72017-07-03 15:14:37 +0200429 DozeLog.traceSensor(mContext, mPulseReason);
Adrian Roos79bacbb2016-10-26 11:00:12 -0700430 mHandler.post(mWakeLock.wrap(() -> {
Adrian Roosd6ec13132016-10-27 11:50:47 -0700431 if (DEBUG) Log.d(TAG, "onTrigger: " + triggerEventToString(event));
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700432 boolean sensorPerformsProxCheck = false;
Lucas Dupin3d951752018-10-10 12:00:40 -0700433 if (mSensor != null && mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700434 int subType = (int) event.values[0];
435 MetricsLogger.action(
Adrian Roos79bacbb2016-10-26 11:00:12 -0700436 mContext, MetricsProto.MetricsEvent.ACTION_AMBIENT_GESTURE,
437 subType);
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700438 sensorPerformsProxCheck =
439 mDozeParameters.getPickupSubtypePerformsProxCheck(subType);
440 }
441
442 mRegistered = false;
Adrian Roos25c7a582017-06-02 12:50:38 -0700443 float screenX = -1;
444 float screenY = -1;
445 if (mReportsTouchCoordinates && event.values.length >= 2) {
446 screenX = event.values[0];
447 screenY = event.values[1];
448 }
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800449 mCallback.onSensorPulse(mPulseReason, sensorPerformsProxCheck, screenX, screenY,
450 event.values);
Lucas Dupin65104382018-12-04 11:53:42 -0800451 if (!mRegistered) {
452 updateListener(); // reregister, this sensor only fires once
453 }
Adrian Roos79bacbb2016-10-26 11:00:12 -0700454 }));
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700455 }
456
457 public void registerSettingsObserver(ContentObserver settingsObserver) {
458 if (mConfigured && !TextUtils.isEmpty(mSetting)) {
459 mResolver.registerContentObserver(
460 Settings.Secure.getUriFor(mSetting), false /* descendants */,
461 mSettingsObserver, UserHandle.USER_ALL);
462 }
463 }
464
Lucas Dupin323f9ff2018-08-27 16:55:56 -0700465 protected String triggerEventToString(TriggerEvent event) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700466 if (event == null) return null;
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800467 final StringBuilder sb = new StringBuilder("SensorEvent[")
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700468 .append(event.timestamp).append(',')
469 .append(event.sensor.getName());
470 if (event.values != null) {
471 for (int i = 0; i < event.values.length; i++) {
472 sb.append(',').append(event.values[i]);
473 }
474 }
475 return sb.append(']').toString();
476 }
477 }
478
Lucas Dupin3d951752018-10-10 12:00:40 -0700479 /**
Kevin Chynf7c39032018-10-11 00:44:39 -0700480 * A Sensor that is injected via plugin.
Lucas Dupin3d951752018-10-10 12:00:40 -0700481 */
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800482 @VisibleForTesting
483 class PluginSensor extends TriggerSensor implements SensorManagerPlugin.SensorEventListener {
Lucas Dupin3d951752018-10-10 12:00:40 -0700484
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800485 final SensorManagerPlugin.Sensor mPluginSensor;
486 private long mDebounce;
Lucas Dupin3d951752018-10-10 12:00:40 -0700487
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800488 PluginSensor(SensorManagerPlugin.Sensor sensor, String setting, boolean configured,
Lucas Dupin3d951752018-10-10 12:00:40 -0700489 int pulseReason, boolean reportsTouchCoordinates, boolean requiresTouchscreen) {
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800490 this(sensor, setting, configured, pulseReason, reportsTouchCoordinates,
491 requiresTouchscreen, 0L /* debounce */);
492 }
493
494 PluginSensor(SensorManagerPlugin.Sensor sensor, String setting, boolean configured,
495 int pulseReason, boolean reportsTouchCoordinates, boolean requiresTouchscreen,
496 long debounce) {
Lucas Dupin3d951752018-10-10 12:00:40 -0700497 super(null, setting, configured, pulseReason, reportsTouchCoordinates,
498 requiresTouchscreen);
499 mPluginSensor = sensor;
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800500 mDebounce = debounce;
Lucas Dupin3d951752018-10-10 12:00:40 -0700501 }
502
503 @Override
504 public void updateListener() {
505 if (!mConfigured) return;
506 AsyncSensorManager asyncSensorManager = (AsyncSensorManager) mSensorManager;
lpeter8a5f4702019-01-18 16:53:07 +0800507 if (mRequested && !mDisabled && (enabledBySetting() || mIgnoresSetting)
508 && !mRegistered) {
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800509 asyncSensorManager.registerPluginListener(mPluginSensor, this);
Lucas Dupin3d951752018-10-10 12:00:40 -0700510 mRegistered = true;
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800511 if (DEBUG) Log.d(TAG, "registerPluginListener");
Lucas Dupin3d951752018-10-10 12:00:40 -0700512 } else if (mRegistered) {
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800513 asyncSensorManager.unregisterPluginListener(mPluginSensor, this);
Lucas Dupin3d951752018-10-10 12:00:40 -0700514 mRegistered = false;
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800515 if (DEBUG) Log.d(TAG, "unregisterPluginListener");
Lucas Dupin3d951752018-10-10 12:00:40 -0700516 }
517 }
518
519 @Override
520 public String toString() {
521 return new StringBuilder("{mRegistered=").append(mRegistered)
522 .append(", mRequested=").append(mRequested)
523 .append(", mDisabled=").append(mDisabled)
524 .append(", mConfigured=").append(mConfigured)
lpeter8a5f4702019-01-18 16:53:07 +0800525 .append(", mIgnoresSetting=").append(mIgnoresSetting)
Lucas Dupin3d951752018-10-10 12:00:40 -0700526 .append(", mSensor=").append(mPluginSensor).append("}").toString();
527 }
528
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800529 private String triggerEventToString(SensorManagerPlugin.SensorEvent event) {
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800530 if (event == null) return null;
531 final StringBuilder sb = new StringBuilder("PluginTriggerEvent[")
532 .append(event.getSensor()).append(',')
533 .append(event.getVendorType());
534 if (event.getValues() != null) {
535 for (int i = 0; i < event.getValues().length; i++) {
536 sb.append(',').append(event.getValues()[i]);
537 }
538 }
539 return sb.append(']').toString();
Lucas Dupin323f9ff2018-08-27 16:55:56 -0700540 }
Lucas Dupin8a13aa72019-02-22 12:45:21 -0800541
542 @Override
543 public void onSensorChanged(SensorManagerPlugin.SensorEvent event) {
544 DozeLog.traceSensor(mContext, mPulseReason);
545 mHandler.post(mWakeLock.wrap(() -> {
546 final long now = SystemClock.uptimeMillis();
547 if (now < mDebounceFrom + mDebounce) {
548 if (DEBUG) Log.d(TAG, "onSensorEvent dropped: " + triggerEventToString(event));
549 return;
550 }
551 if (DEBUG) Log.d(TAG, "onSensorEvent: " + triggerEventToString(event));
552 mCallback.onSensorPulse(mPulseReason, true /* sensorPerformsProxCheck */, -1, -1,
553 event.getValues());
554 }));
555 }
Lucas Dupin323f9ff2018-08-27 16:55:56 -0700556 }
557
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700558 public interface Callback {
Adrian Roosd6ec13132016-10-27 11:50:47 -0700559
560 /**
561 * Called when a sensor requests a pulse
Lucas Dupin3d053532019-01-29 12:35:22 -0800562 * @param pulseReason Requesting sensor, e.g. {@link DozeLog#REASON_SENSOR_PICKUP}
Adrian Roosd6ec13132016-10-27 11:50:47 -0700563 * @param sensorPerformedProxCheck true if the sensor already checked for FAR proximity.
Adrian Roos25c7a582017-06-02 12:50:38 -0700564 * @param screenX the location on the screen where the sensor fired or -1
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800565 * if the sensor doesn't support reporting screen locations.
Adrian Roos25c7a582017-06-02 12:50:38 -0700566 * @param screenY the location on the screen where the sensor fired or -1
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800567 * @param rawValues raw values array from the event.
Adrian Roosd6ec13132016-10-27 11:50:47 -0700568 */
Adrian Roos25c7a582017-06-02 12:50:38 -0700569 void onSensorPulse(int pulseReason, boolean sensorPerformedProxCheck,
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800570 float screenX, float screenY, float[] rawValues);
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700571 }
572}