blob: 31f4991a82b50d3555ec89fcd7bd5e286c2604b3 [file] [log] [blame]
Adrian Roos7a8ae8a2017-08-02 16:26:50 +02001/*
2 * Copyright (C) 2017 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
14 * limitations under the License.
15 */
16
17package com.android.systemui.util;
18
Kevin Chynac56f742018-10-09 16:20:25 -070019import android.content.Context;
Adrian Roos7a8ae8a2017-08-02 16:26:50 +020020import android.hardware.HardwareBuffer;
21import android.hardware.Sensor;
22import android.hardware.SensorAdditionalInfo;
23import android.hardware.SensorDirectChannel;
24import android.hardware.SensorEventListener;
25import android.hardware.SensorManager;
26import android.hardware.TriggerEventListener;
27import android.os.Handler;
28import android.os.HandlerThread;
29import android.os.MemoryFile;
30import android.util.Log;
31
Adrian Roosb1f77242017-08-04 12:35:24 +020032import com.android.internal.annotations.VisibleForTesting;
Adrian Roos7a8ae8a2017-08-02 16:26:50 +020033import com.android.internal.util.Preconditions;
Kevin Chynac56f742018-10-09 16:20:25 -070034import com.android.systemui.plugins.PluginListener;
35import com.android.systemui.plugins.SensorManagerPlugin;
36import com.android.systemui.shared.plugins.PluginManager;
Adrian Roos7a8ae8a2017-08-02 16:26:50 +020037
Kevin Chynac56f742018-10-09 16:20:25 -070038import java.util.ArrayList;
Adrian Roos7a8ae8a2017-08-02 16:26:50 +020039import java.util.List;
40
Jason Monk196d6392018-12-20 13:25:34 -050041import javax.inject.Inject;
42import javax.inject.Singleton;
43
Adrian Roos7a8ae8a2017-08-02 16:26:50 +020044/**
45 * Wrapper around sensor manager that hides potential sources of latency.
46 *
47 * Offloads fetching (non-dynamic) sensors and (un)registering listeners onto a background thread
48 * without blocking. Note that this means registering listeners now always appears successful even
49 * if it is not.
50 */
Jason Monk196d6392018-12-20 13:25:34 -050051@Singleton
Kevin Chynac56f742018-10-09 16:20:25 -070052public class AsyncSensorManager extends SensorManager
53 implements PluginListener<SensorManagerPlugin> {
Adrian Roos7a8ae8a2017-08-02 16:26:50 +020054
55 private static final String TAG = "AsyncSensorManager";
56
57 private final SensorManager mInner;
58 private final List<Sensor> mSensorCache;
59 private final HandlerThread mHandlerThread = new HandlerThread("async_sensor");
Adrian Roosb1f77242017-08-04 12:35:24 +020060 @VisibleForTesting final Handler mHandler;
Kevin Chynac56f742018-10-09 16:20:25 -070061 private final List<SensorManagerPlugin> mPlugins;
Adrian Roos7a8ae8a2017-08-02 16:26:50 +020062
Jason Monk196d6392018-12-20 13:25:34 -050063 @Inject
64 public AsyncSensorManager(Context context, PluginManager pluginManager) {
65 this(context.getSystemService(SensorManager.class), pluginManager);
66 }
67
68 @VisibleForTesting
69 AsyncSensorManager(SensorManager sensorManager, PluginManager pluginManager) {
70 mInner = sensorManager;
Adrian Roos7a8ae8a2017-08-02 16:26:50 +020071 mHandlerThread.start();
72 mHandler = new Handler(mHandlerThread.getLooper());
73 mSensorCache = mInner.getSensorList(Sensor.TYPE_ALL);
Kevin Chynac56f742018-10-09 16:20:25 -070074 mPlugins = new ArrayList<>();
75 pluginManager.addPluginListener(this, SensorManagerPlugin.class, true /* allowMultiple */);
Adrian Roos7a8ae8a2017-08-02 16:26:50 +020076 }
77
78 @Override
79 protected List<Sensor> getFullSensorList() {
80 return mSensorCache;
81 }
82
83 @Override
84 protected List<Sensor> getFullDynamicSensorList() {
Kevin Chynac56f742018-10-09 16:20:25 -070085 return mInner.getSensorList(Sensor.TYPE_ALL);
Adrian Roos7a8ae8a2017-08-02 16:26:50 +020086 }
87
88 @Override
Lucas Dupin1ae6cf92018-12-14 18:06:38 -080089 protected boolean registerListenerImpl(SensorEventListener listener,
90 Sensor sensor, int delayUs, Handler handler, int maxReportLatencyUs,
91 int reservedFlags) {
Adrian Roos7a8ae8a2017-08-02 16:26:50 +020092 mHandler.post(() -> {
93 if (!mInner.registerListener(listener, sensor, delayUs, maxReportLatencyUs, handler)) {
94 Log.e(TAG, "Registering " + listener + " for " + sensor + " failed.");
95 }
96 });
97 return true;
98 }
99
100 @Override
101 protected boolean flushImpl(SensorEventListener listener) {
102 return mInner.flush(listener);
103 }
104
105 @Override
106 protected SensorDirectChannel createDirectChannelImpl(MemoryFile memoryFile,
107 HardwareBuffer hardwareBuffer) {
108 throw new UnsupportedOperationException("not implemented");
109 }
110
111 @Override
112 protected void destroyDirectChannelImpl(SensorDirectChannel channel) {
113 throw new UnsupportedOperationException("not implemented");
114 }
115
116 @Override
117 protected int configureDirectChannelImpl(SensorDirectChannel channel, Sensor s, int rate) {
118 throw new UnsupportedOperationException("not implemented");
119 }
120
121 @Override
122 protected void registerDynamicSensorCallbackImpl(DynamicSensorCallback callback,
123 Handler handler) {
124 mHandler.post(() -> mInner.registerDynamicSensorCallback(callback, handler));
125 }
126
127 @Override
128 protected void unregisterDynamicSensorCallbackImpl(DynamicSensorCallback callback) {
129 mHandler.post(() -> mInner.unregisterDynamicSensorCallback(callback));
130 }
131
132 @Override
133 protected boolean requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor) {
134 mHandler.post(() -> {
135 if (!mInner.requestTriggerSensor(listener, sensor)) {
136 Log.e(TAG, "Requesting " + listener + " for " + sensor + " failed.");
137 }
138 });
139 return true;
140 }
141
142 @Override
143 protected boolean cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor,
144 boolean disable) {
145 Preconditions.checkArgument(disable);
146
147 mHandler.post(() -> {
148 if (!mInner.cancelTriggerSensor(listener, sensor)) {
149 Log.e(TAG, "Canceling " + listener + " for " + sensor + " failed.");
150 }
151 });
152 return true;
153 }
154
Kevin Chynac56f742018-10-09 16:20:25 -0700155 /**
156 * Requests for all sensors that match the given type from all plugins.
157 * @param sensor
158 * @param listener
159 */
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800160 public void registerPluginListener(SensorManagerPlugin.Sensor sensor,
161 SensorManagerPlugin.SensorEventListener listener) {
Kevin Chynac56f742018-10-09 16:20:25 -0700162 if (mPlugins.isEmpty()) {
163 Log.w(TAG, "No plugins registered");
164 }
165 mHandler.post(() -> {
166 for (int i = 0; i < mPlugins.size(); i++) {
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800167 mPlugins.get(i).registerListener(sensor, listener);
Kevin Chynac56f742018-10-09 16:20:25 -0700168 }
169 });
170 }
171
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800172 /**
173 * Unregisters all sensors that match the give type for all plugins.
174 * @param sensor
175 * @param listener
176 */
177 public void unregisterPluginListener(SensorManagerPlugin.Sensor sensor,
178 SensorManagerPlugin.SensorEventListener listener) {
Kevin Chynac56f742018-10-09 16:20:25 -0700179 mHandler.post(() -> {
180 for (int i = 0; i < mPlugins.size(); i++) {
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800181 mPlugins.get(i).unregisterListener(sensor, listener);
Kevin Chynac56f742018-10-09 16:20:25 -0700182 }
183 });
184 }
185
Adrian Roos7a8ae8a2017-08-02 16:26:50 +0200186 @Override
187 protected boolean initDataInjectionImpl(boolean enable) {
188 throw new UnsupportedOperationException("not implemented");
189 }
190
191 @Override
192 protected boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy,
193 long timestamp) {
194 throw new UnsupportedOperationException("not implemented");
195 }
196
197 @Override
198 protected boolean setOperationParameterImpl(SensorAdditionalInfo parameter) {
199 mHandler.post(() -> mInner.setOperationParameter(parameter));
200 return true;
201 }
202
203 @Override
Lucas Dupin1ae6cf92018-12-14 18:06:38 -0800204 protected void unregisterListenerImpl(SensorEventListener listener,
205 Sensor sensor) {
Adrian Roosb1f77242017-08-04 12:35:24 +0200206 mHandler.post(() -> {
207 if (sensor == null) {
208 mInner.unregisterListener(listener);
209 } else {
210 mInner.unregisterListener(listener, sensor);
211 }
212 });
Adrian Roos7a8ae8a2017-08-02 16:26:50 +0200213 }
Kevin Chynac56f742018-10-09 16:20:25 -0700214
215 @Override
216 public void onPluginConnected(SensorManagerPlugin plugin, Context pluginContext) {
217 mPlugins.add(plugin);
218 }
219
220 @Override
221 public void onPluginDisconnected(SensorManagerPlugin plugin) {
222 mPlugins.remove(plugin);
223 }
Adrian Roos7a8ae8a2017-08-02 16:26:50 +0200224}