blob: c2676d0994811b55599dae180e0b85aef5ab6b4e [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 Dupin3d951752018-10-10 12:00:40 -070020
Adrian Roosea8d6ae2016-10-26 10:40:12 -070021import android.annotation.AnyThread;
22import android.app.ActivityManager;
Adrian Roos6023ccb2017-06-28 16:22:02 +020023import android.app.AlarmManager;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070024import android.content.ContentResolver;
25import android.content.Context;
26import android.database.ContentObserver;
27import android.hardware.Sensor;
Adrian Roos67cca742017-04-13 16:52:51 -070028import android.hardware.SensorEventListener;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070029import android.hardware.SensorManager;
30import android.hardware.TriggerEvent;
31import android.hardware.TriggerEventListener;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070032import android.net.Uri;
33import android.os.Handler;
Adrian Roos6023ccb2017-06-28 16:22:02 +020034import android.os.SystemClock;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070035import android.os.UserHandle;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070036import android.provider.Settings;
37import android.text.TextUtils;
38import android.util.Log;
39
Adrian Roosff2c4562016-11-03 12:13:36 -070040import com.android.internal.hardware.AmbientDisplayConfiguration;
41import com.android.internal.logging.MetricsLogger;
Tamas Berghammer383db5eb2016-06-22 15:21:38 +010042import com.android.internal.logging.nano.MetricsProto;
Lucas Dupin3d951752018-10-10 12:00:40 -070043import com.android.systemui.plugins.SensorManagerPlugin;
Adrian Roosff2c4562016-11-03 12:13:36 -070044import com.android.systemui.statusbar.phone.DozeParameters;
Adrian Roos6023ccb2017-06-28 16:22:02 +020045import com.android.systemui.util.AlarmTimeout;
Lucas Dupin3d951752018-10-10 12:00:40 -070046import com.android.systemui.util.AsyncSensorManager;
Adrian Roosc1b50322017-02-27 21:07:58 +010047import com.android.systemui.util.wakelock.WakeLock;
Adrian Roosff2c4562016-11-03 12:13:36 -070048
49import java.io.PrintWriter;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070050import java.util.List;
Adrian Roos67cca742017-04-13 16:52:51 -070051import java.util.function.Consumer;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070052
53public class DozeSensors {
54
55 private static final boolean DEBUG = DozeService.DEBUG;
56
57 private static final String TAG = "DozeSensors";
58
59 private final Context mContext;
Adrian Roos6023ccb2017-06-28 16:22:02 +020060 private final AlarmManager mAlarmManager;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070061 private final SensorManager mSensorManager;
62 private final TriggerSensor[] mSensors;
63 private final ContentResolver mResolver;
64 private final TriggerSensor mPickupSensor;
65 private final DozeParameters mDozeParameters;
66 private final AmbientDisplayConfiguration mConfig;
Adrian Roosc1b50322017-02-27 21:07:58 +010067 private final WakeLock mWakeLock;
Adrian Roos67cca742017-04-13 16:52:51 -070068 private final Consumer<Boolean> mProxCallback;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070069 private final Callback mCallback;
70
71 private final Handler mHandler = new Handler();
Adrian Roos67cca742017-04-13 16:52:51 -070072 private final ProxSensor mProxSensor;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070073
74
Adrian Roos6023ccb2017-06-28 16:22:02 +020075 public DozeSensors(Context context, AlarmManager alarmManager, SensorManager sensorManager,
Lucas Dupin323f9ff2018-08-27 16:55:56 -070076 DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock,
Lucas Dupinb2d9f482018-11-16 18:55:13 -080077 Callback callback, Consumer<Boolean> proxCallback, AlwaysOnDisplayPolicy policy) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -070078 mContext = context;
Adrian Roos6023ccb2017-06-28 16:22:02 +020079 mAlarmManager = alarmManager;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070080 mSensorManager = sensorManager;
81 mDozeParameters = dozeParameters;
82 mConfig = config;
83 mWakeLock = wakeLock;
Adrian Roos67cca742017-04-13 16:52:51 -070084 mProxCallback = proxCallback;
Adrian Roosea8d6ae2016-10-26 10:40:12 -070085 mResolver = mContext.getContentResolver();
86
87 mSensors = new TriggerSensor[] {
88 new TriggerSensor(
89 mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION),
90 null /* setting */,
91 dozeParameters.getPulseOnSigMotion(),
Adrian Roos98d31982017-08-02 20:50:16 +020092 DozeLog.PULSE_REASON_SENSOR_SIGMOTION, false /* touchCoords */,
93 false /* touchscreen */),
Adrian Roosea8d6ae2016-10-26 10:40:12 -070094 mPickupSensor = new TriggerSensor(
95 mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE),
Lucas Dupin4359b552018-08-09 15:07:54 -070096 Settings.Secure.DOZE_PICK_UP_GESTURE,
97 config.dozePickupSensorAvailable(),
Adrian Roos98d31982017-08-02 20:50:16 +020098 DozeLog.PULSE_REASON_SENSOR_PICKUP, false /* touchCoords */,
99 false /* touchscreen */),
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700100 new TriggerSensor(
101 findSensorWithType(config.doubleTapSensorType()),
Lucas Dupin4359b552018-08-09 15:07:54 -0700102 Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700103 true /* configured */,
Adrian Roos25c7a582017-06-02 12:50:38 -0700104 DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP,
Adrian Roos98d31982017-08-02 20:50:16 +0200105 dozeParameters.doubleTapReportsTouchCoordinates(),
106 true /* touchscreen */),
Adrian Roosd0963a02017-05-15 14:33:37 -0700107 new TriggerSensor(
108 findSensorWithType(config.longPressSensorType()),
109 Settings.Secure.DOZE_PULSE_ON_LONG_PRESS,
110 false /* settingDef */,
111 true /* configured */,
112 DozeLog.PULSE_REASON_SENSOR_LONG_PRESS,
Adrian Roos98d31982017-08-02 20:50:16 +0200113 true /* reports touch coordinates */,
114 true /* touchscreen */),
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800115 new PluginSensor(
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800116 new SensorManagerPlugin.Sensor(TYPE_WAKE_DISPLAY),
117 Settings.Secure.DOZE_WAKE_SCREEN_GESTURE,
118 true /* configured */,
119 DozeLog.REASON_SENSOR_WAKE_UP,
120 false /* reports touch coordinates */,
121 false /* touchscreen */),
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700122 };
Adrian Roos67cca742017-04-13 16:52:51 -0700123
jackqdyulei8443dd02017-08-24 16:14:34 -0700124 mProxSensor = new ProxSensor(policy);
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700125 mCallback = callback;
126 }
127
128 private Sensor findSensorWithType(String type) {
Adrian Roos2981eb02017-05-26 18:40:09 -0700129 return findSensorWithType(mSensorManager, type);
130 }
131
132 static Sensor findSensorWithType(SensorManager sensorManager, String type) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700133 if (TextUtils.isEmpty(type)) {
134 return null;
135 }
Adrian Roos2981eb02017-05-26 18:40:09 -0700136 List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL);
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700137 for (Sensor s : sensorList) {
138 if (type.equals(s.getStringType())) {
139 return s;
140 }
141 }
142 return null;
143 }
144
Adrian Roosd6ec13132016-10-27 11:50:47 -0700145 public void setListening(boolean listen) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700146 for (TriggerSensor s : mSensors) {
147 s.setListening(listen);
148 if (listen) {
149 s.registerSettingsObserver(mSettingsObserver);
150 }
151 }
152 if (!listen) {
153 mResolver.unregisterContentObserver(mSettingsObserver);
154 }
155 }
156
Adrian Roos98d31982017-08-02 20:50:16 +0200157 /** Set the listening state of only the sensors that require the touchscreen. */
158 public void setTouchscreenSensorsListening(boolean listening) {
159 for (TriggerSensor sensor : mSensors) {
160 if (sensor.mRequiresTouchscreen) {
161 sensor.setListening(listening);
162 }
163 }
164 }
165
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700166 public void reregisterAllSensors() {
167 for (TriggerSensor s : mSensors) {
168 s.setListening(false);
169 }
170 for (TriggerSensor s : mSensors) {
171 s.setListening(true);
172 }
173 }
174
175 public void onUserSwitched() {
176 for (TriggerSensor s : mSensors) {
177 s.updateListener();
178 }
179 }
180
Adrian Roos67cca742017-04-13 16:52:51 -0700181 public void setProxListening(boolean listen) {
Adrian Roos6023ccb2017-06-28 16:22:02 +0200182 mProxSensor.setRequested(listen);
Adrian Roos67cca742017-04-13 16:52:51 -0700183 }
184
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700185 private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
186 @Override
187 public void onChange(boolean selfChange, Uri uri, int userId) {
188 if (userId != ActivityManager.getCurrentUser()) {
189 return;
190 }
191 for (TriggerSensor s : mSensors) {
192 s.updateListener();
193 }
194 }
195 };
196
197 public void setDisableSensorsInterferingWithProximity(boolean disable) {
198 mPickupSensor.setDisabled(disable);
199 }
200
Adrian Roosff2c4562016-11-03 12:13:36 -0700201 /** Dump current state */
202 public void dump(PrintWriter pw) {
203 for (TriggerSensor s : mSensors) {
204 pw.print("Sensor: "); pw.println(s.toString());
205 }
Adrian Roos2ca9cd72017-07-03 15:14:37 +0200206 pw.print("ProxSensor: "); pw.println(mProxSensor.toString());
Adrian Roosff2c4562016-11-03 12:13:36 -0700207 }
208
Adrian Roos70da03a2017-07-24 16:42:57 +0200209 /**
210 * @return true if prox is currently far, false if near or null if unknown.
211 */
212 public Boolean isProximityCurrentlyFar() {
213 return mProxSensor.mCurrentlyFar;
214 }
215
Adrian Roos67cca742017-04-13 16:52:51 -0700216 private class ProxSensor implements SensorEventListener {
217
Adrian Roos6023ccb2017-06-28 16:22:02 +0200218 boolean mRequested;
Adrian Roos67cca742017-04-13 16:52:51 -0700219 boolean mRegistered;
220 Boolean mCurrentlyFar;
Adrian Roos6023ccb2017-06-28 16:22:02 +0200221 long mLastNear;
222 final AlarmTimeout mCooldownTimer;
jackqdyulei8443dd02017-08-24 16:14:34 -0700223 final AlwaysOnDisplayPolicy mPolicy;
Adrian Roos67cca742017-04-13 16:52:51 -0700224
Adrian Roos6023ccb2017-06-28 16:22:02 +0200225
jackqdyulei8443dd02017-08-24 16:14:34 -0700226 public ProxSensor(AlwaysOnDisplayPolicy policy) {
227 mPolicy = policy;
Adrian Roos6023ccb2017-06-28 16:22:02 +0200228 mCooldownTimer = new AlarmTimeout(mAlarmManager, this::updateRegistered,
229 "prox_cooldown", mHandler);
230 }
231
232 void setRequested(boolean requested) {
233 if (mRequested == requested) {
Adrian Roos67cca742017-04-13 16:52:51 -0700234 // Send an update even if we don't re-register.
235 mHandler.post(() -> {
236 if (mCurrentlyFar != null) {
237 mProxCallback.accept(mCurrentlyFar);
238 }
239 });
240 return;
241 }
Adrian Roos6023ccb2017-06-28 16:22:02 +0200242 mRequested = requested;
243 updateRegistered();
244 }
245
246 private void updateRegistered() {
247 setRegistered(mRequested && !mCooldownTimer.isScheduled());
248 }
249
250 private void setRegistered(boolean register) {
251 if (mRegistered == register) {
252 return;
253 }
Adrian Roos67cca742017-04-13 16:52:51 -0700254 if (register) {
255 mRegistered = mSensorManager.registerListener(this,
256 mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY),
257 SensorManager.SENSOR_DELAY_NORMAL, mHandler);
258 } else {
259 mSensorManager.unregisterListener(this);
260 mRegistered = false;
261 mCurrentlyFar = null;
262 }
263 }
264
265 @Override
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800266 public void onSensorChanged(android.hardware.SensorEvent event) {
Lucas Dupin58543842018-02-15 14:00:54 -0800267 if (DEBUG) Log.d(TAG, "onSensorChanged " + event);
268
Adrian Roos67cca742017-04-13 16:52:51 -0700269 mCurrentlyFar = event.values[0] >= event.sensor.getMaximumRange();
270 mProxCallback.accept(mCurrentlyFar);
Adrian Roos6023ccb2017-06-28 16:22:02 +0200271
272 long now = SystemClock.elapsedRealtime();
Adrian Roos8f72b3c2017-07-07 12:20:21 +0200273 if (mCurrentlyFar == null) {
274 // Sensor has been unregistered by the proxCallback. Do nothing.
275 } else if (!mCurrentlyFar) {
Adrian Roos6023ccb2017-06-28 16:22:02 +0200276 mLastNear = now;
jackqdyulei8443dd02017-08-24 16:14:34 -0700277 } else if (mCurrentlyFar && now - mLastNear < mPolicy.proxCooldownTriggerMs) {
Adrian Roos6023ccb2017-06-28 16:22:02 +0200278 // If the last near was very recent, we might be using more power for prox
279 // wakeups than we're saving from turning of the screen. Instead, turn it off
280 // for a while.
jackqdyulei8443dd02017-08-24 16:14:34 -0700281 mCooldownTimer.schedule(mPolicy.proxCooldownPeriodMs,
282 AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
Adrian Roos6023ccb2017-06-28 16:22:02 +0200283 updateRegistered();
284 }
Adrian Roos67cca742017-04-13 16:52:51 -0700285 }
286
287 @Override
288 public void onAccuracyChanged(Sensor sensor, int accuracy) {
289 }
Adrian Roos2ca9cd72017-07-03 15:14:37 +0200290
291 @Override
292 public String toString() {
293 return String.format("{registered=%s, requested=%s, coolingDown=%s, currentlyFar=%s}",
294 mRegistered, mRequested, mCooldownTimer.isScheduled(), mCurrentlyFar);
295 }
Adrian Roos67cca742017-04-13 16:52:51 -0700296 }
297
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700298 private class TriggerSensor extends TriggerEventListener {
299 final Sensor mSensor;
300 final boolean mConfigured;
301 final int mPulseReason;
302 final String mSetting;
Adrian Roos25c7a582017-06-02 12:50:38 -0700303 final boolean mReportsTouchCoordinates;
Adrian Roosd0963a02017-05-15 14:33:37 -0700304 final boolean mSettingDefault;
Adrian Roos98d31982017-08-02 20:50:16 +0200305 final boolean mRequiresTouchscreen;
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700306
Lucas Dupin323f9ff2018-08-27 16:55:56 -0700307 protected boolean mRequested;
308 protected boolean mRegistered;
309 protected boolean mDisabled;
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700310
Adrian Roos25c7a582017-06-02 12:50:38 -0700311 public TriggerSensor(Sensor sensor, String setting, boolean configured, int pulseReason,
Adrian Roos98d31982017-08-02 20:50:16 +0200312 boolean reportsTouchCoordinates, boolean requiresTouchscreen) {
Adrian Roosd0963a02017-05-15 14:33:37 -0700313 this(sensor, setting, true /* settingDef */, configured, pulseReason,
Adrian Roos98d31982017-08-02 20:50:16 +0200314 reportsTouchCoordinates, requiresTouchscreen);
Adrian Roosd0963a02017-05-15 14:33:37 -0700315 }
316
317 public TriggerSensor(Sensor sensor, String setting, boolean settingDef,
Adrian Roos98d31982017-08-02 20:50:16 +0200318 boolean configured, int pulseReason, boolean reportsTouchCoordinates,
319 boolean requiresTouchscreen) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700320 mSensor = sensor;
321 mSetting = setting;
Adrian Roosd0963a02017-05-15 14:33:37 -0700322 mSettingDefault = settingDef;
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700323 mConfigured = configured;
324 mPulseReason = pulseReason;
Adrian Roos25c7a582017-06-02 12:50:38 -0700325 mReportsTouchCoordinates = reportsTouchCoordinates;
Adrian Roos98d31982017-08-02 20:50:16 +0200326 mRequiresTouchscreen = requiresTouchscreen;
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700327 }
328
329 public void setListening(boolean listen) {
330 if (mRequested == listen) return;
331 mRequested = listen;
332 updateListener();
333 }
334
335 public void setDisabled(boolean disabled) {
336 if (mDisabled == disabled) return;
337 mDisabled = disabled;
338 updateListener();
339 }
340
341 public void updateListener() {
342 if (!mConfigured || mSensor == null) return;
343 if (mRequested && !mDisabled && enabledBySetting() && !mRegistered) {
344 mRegistered = mSensorManager.requestTriggerSensor(this, mSensor);
345 if (DEBUG) Log.d(TAG, "requestTriggerSensor " + mRegistered);
346 } else if (mRegistered) {
347 final boolean rt = mSensorManager.cancelTriggerSensor(this, mSensor);
348 if (DEBUG) Log.d(TAG, "cancelTriggerSensor " + rt);
349 mRegistered = false;
350 }
351 }
352
Lucas Dupin323f9ff2018-08-27 16:55:56 -0700353 protected boolean enabledBySetting() {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700354 if (TextUtils.isEmpty(mSetting)) {
355 return true;
356 }
Adrian Roosd0963a02017-05-15 14:33:37 -0700357 return Settings.Secure.getIntForUser(mResolver, mSetting, mSettingDefault ? 1 : 0,
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700358 UserHandle.USER_CURRENT) != 0;
359 }
360
361 @Override
362 public String toString() {
363 return new StringBuilder("{mRegistered=").append(mRegistered)
364 .append(", mRequested=").append(mRequested)
365 .append(", mDisabled=").append(mDisabled)
366 .append(", mConfigured=").append(mConfigured)
367 .append(", mSensor=").append(mSensor).append("}").toString();
368 }
369
370 @Override
371 @AnyThread
372 public void onTrigger(TriggerEvent event) {
Adrian Roos2ca9cd72017-07-03 15:14:37 +0200373 DozeLog.traceSensor(mContext, mPulseReason);
Adrian Roos79bacbb2016-10-26 11:00:12 -0700374 mHandler.post(mWakeLock.wrap(() -> {
Adrian Roosd6ec13132016-10-27 11:50:47 -0700375 if (DEBUG) Log.d(TAG, "onTrigger: " + triggerEventToString(event));
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700376 boolean sensorPerformsProxCheck = false;
Lucas Dupin3d951752018-10-10 12:00:40 -0700377 if (mSensor != null && mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700378 int subType = (int) event.values[0];
379 MetricsLogger.action(
Adrian Roos79bacbb2016-10-26 11:00:12 -0700380 mContext, MetricsProto.MetricsEvent.ACTION_AMBIENT_GESTURE,
381 subType);
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700382 sensorPerformsProxCheck =
383 mDozeParameters.getPickupSubtypePerformsProxCheck(subType);
384 }
385
386 mRegistered = false;
Adrian Roos25c7a582017-06-02 12:50:38 -0700387 float screenX = -1;
388 float screenY = -1;
389 if (mReportsTouchCoordinates && event.values.length >= 2) {
390 screenX = event.values[0];
391 screenY = event.values[1];
392 }
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800393 mCallback.onSensorPulse(mPulseReason, sensorPerformsProxCheck, screenX, screenY,
394 event.values);
Lucas Dupin65104382018-12-04 11:53:42 -0800395 if (!mRegistered) {
396 updateListener(); // reregister, this sensor only fires once
397 }
Adrian Roos79bacbb2016-10-26 11:00:12 -0700398 }));
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700399 }
400
401 public void registerSettingsObserver(ContentObserver settingsObserver) {
402 if (mConfigured && !TextUtils.isEmpty(mSetting)) {
403 mResolver.registerContentObserver(
404 Settings.Secure.getUriFor(mSetting), false /* descendants */,
405 mSettingsObserver, UserHandle.USER_ALL);
406 }
407 }
408
Lucas Dupin323f9ff2018-08-27 16:55:56 -0700409 protected String triggerEventToString(TriggerEvent event) {
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700410 if (event == null) return null;
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800411 final StringBuilder sb = new StringBuilder("SensorEvent[")
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700412 .append(event.timestamp).append(',')
413 .append(event.sensor.getName());
414 if (event.values != null) {
415 for (int i = 0; i < event.values.length; i++) {
416 sb.append(',').append(event.values[i]);
417 }
418 }
419 return sb.append(']').toString();
420 }
421 }
422
Lucas Dupin3d951752018-10-10 12:00:40 -0700423 /**
Kevin Chynf7c39032018-10-11 00:44:39 -0700424 * A Sensor that is injected via plugin.
Lucas Dupin3d951752018-10-10 12:00:40 -0700425 */
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800426 private class PluginSensor extends TriggerSensor {
Lucas Dupin3d951752018-10-10 12:00:40 -0700427
428 private final SensorManagerPlugin.Sensor mPluginSensor;
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800429 private final SensorManagerPlugin.SensorEventListener mTriggerEventListener = (event) -> {
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800430 DozeLog.traceSensor(mContext, mPulseReason);
431 mHandler.post(mWakeLock.wrap(() -> {
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800432 if (DEBUG) Log.d(TAG, "onSensorEvent: " + triggerEventToString(event));
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800433 mCallback.onSensorPulse(mPulseReason, true /* sensorPerformsProxCheck */, -1, -1,
434 event.getValues());
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800435 }));
Lucas Dupin3d951752018-10-10 12:00:40 -0700436 };
437
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800438 PluginSensor(SensorManagerPlugin.Sensor sensor, String setting, boolean configured,
Lucas Dupin3d951752018-10-10 12:00:40 -0700439 int pulseReason, boolean reportsTouchCoordinates, boolean requiresTouchscreen) {
440 super(null, setting, configured, pulseReason, reportsTouchCoordinates,
441 requiresTouchscreen);
442 mPluginSensor = sensor;
443 }
444
445 @Override
446 public void updateListener() {
447 if (!mConfigured) return;
448 AsyncSensorManager asyncSensorManager = (AsyncSensorManager) mSensorManager;
449 if (mRequested && !mDisabled && enabledBySetting() && !mRegistered) {
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800450 asyncSensorManager.registerPluginListener(mPluginSensor, mTriggerEventListener);
Lucas Dupin3d951752018-10-10 12:00:40 -0700451 mRegistered = true;
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800452 if (DEBUG) Log.d(TAG, "registerPluginListener");
Lucas Dupin3d951752018-10-10 12:00:40 -0700453 } else if (mRegistered) {
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800454 asyncSensorManager.unregisterPluginListener(mPluginSensor, mTriggerEventListener);
Lucas Dupin3d951752018-10-10 12:00:40 -0700455 mRegistered = false;
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800456 if (DEBUG) Log.d(TAG, "unregisterPluginListener");
Lucas Dupin3d951752018-10-10 12:00:40 -0700457 }
458 }
459
460 @Override
461 public String toString() {
462 return new StringBuilder("{mRegistered=").append(mRegistered)
463 .append(", mRequested=").append(mRequested)
464 .append(", mDisabled=").append(mDisabled)
465 .append(", mConfigured=").append(mConfigured)
466 .append(", mSensor=").append(mPluginSensor).append("}").toString();
467 }
468
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800469 private String triggerEventToString(SensorManagerPlugin.SensorEvent event) {
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800470 if (event == null) return null;
471 final StringBuilder sb = new StringBuilder("PluginTriggerEvent[")
472 .append(event.getSensor()).append(',')
473 .append(event.getVendorType());
474 if (event.getValues() != null) {
475 for (int i = 0; i < event.getValues().length; i++) {
476 sb.append(',').append(event.getValues()[i]);
477 }
478 }
479 return sb.append(']').toString();
Lucas Dupin323f9ff2018-08-27 16:55:56 -0700480 }
Lucas Dupin323f9ff2018-08-27 16:55:56 -0700481 }
482
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700483 public interface Callback {
Adrian Roosd6ec13132016-10-27 11:50:47 -0700484
485 /**
486 * Called when a sensor requests a pulse
487 * @param pulseReason Requesting sensor, e.g. {@link DozeLog#PULSE_REASON_SENSOR_PICKUP}
488 * @param sensorPerformedProxCheck true if the sensor already checked for FAR proximity.
Adrian Roos25c7a582017-06-02 12:50:38 -0700489 * @param screenX the location on the screen where the sensor fired or -1
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800490 * if the sensor doesn't support reporting screen locations.
Adrian Roos25c7a582017-06-02 12:50:38 -0700491 * @param screenY the location on the screen where the sensor fired or -1
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800492 * @param rawValues raw values array from the event.
Adrian Roosd6ec13132016-10-27 11:50:47 -0700493 */
Adrian Roos25c7a582017-06-02 12:50:38 -0700494 void onSensorPulse(int pulseReason, boolean sensorPerformedProxCheck,
Lucas Dupinb2d9f482018-11-16 18:55:13 -0800495 float screenX, float screenY, float[] rawValues);
Adrian Roosea8d6ae2016-10-26 10:40:12 -0700496 }
497}