blob: 974913b290b125d4b4fad50c7aeaf7c8f970718c [file] [log] [blame]
Peng Xufb1c9412016-03-29 21:50:43 -07001/*
Jeff Brown25157e42012-04-16 12:13:05 -07002 * Copyright (C) 2012 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 android.hardware;
18
Artur Satayev26958002019-12-10 17:47:52 +000019import android.compat.annotation.UnsupportedAppUsage;
Peng Xua35b5532016-01-20 00:05:45 -080020import android.content.BroadcastReceiver;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -070021import android.content.Context;
Peng Xua35b5532016-01-20 00:05:45 -080022import android.content.Intent;
23import android.content.IntentFilter;
Jeff Brown25157e42012-04-16 12:13:05 -070024import android.os.Handler;
Mathias Agopiandb772d82013-01-31 19:31:12 -080025import android.os.Looper;
Peng Xufa2672b2016-12-07 03:54:44 -080026import android.os.MemoryFile;
Mathias Agopiandb772d82013-01-31 19:31:12 -080027import android.os.MessageQueue;
Jaikumar Ganesh2e900892013-04-11 10:40:33 -070028import android.util.Log;
Jeff Brown25157e42012-04-16 12:13:05 -070029import android.util.SparseArray;
30import android.util.SparseBooleanArray;
31import android.util.SparseIntArray;
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -080032
Peng Xu4a4baef2016-03-16 16:56:39 -070033import com.android.internal.annotations.GuardedBy;
34
Peng Xu62f2c872017-09-22 11:50:33 -070035import dalvik.system.CloseGuard;
36
Peng Xu7d96fa02017-03-04 16:15:45 -080037import java.io.IOException;
Peng Xu3c8c6a42017-04-06 18:37:56 -070038import java.io.UncheckedIOException;
Jeff Brown3b4049e2015-04-17 15:22:27 -070039import java.lang.ref.WeakReference;
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -080040import java.util.ArrayList;
41import java.util.HashMap;
42import java.util.List;
Peng Xua35b5532016-01-20 00:05:45 -080043import java.util.Map;
Jeff Brown25157e42012-04-16 12:13:05 -070044
Jeff Brown25157e42012-04-16 12:13:05 -070045/**
46 * Sensor manager implementation that communicates with the built-in
47 * system sensors.
48 *
49 * @hide
50 */
51public class SystemSensorManager extends SensorManager {
Peng Xua35b5532016-01-20 00:05:45 -080052 //TODO: disable extra logging before release
songjinshib5322b22017-03-15 16:16:05 +080053 private static final boolean DEBUG_DYNAMIC_SENSOR = true;
54 private static final int MIN_DIRECT_CHANNEL_BUFFER_SIZE = 104;
55 private static final int MAX_LISTENER_COUNT = 128;
Peng Xua35b5532016-01-20 00:05:45 -080056
Mathias Agopiandb772d82013-01-31 19:31:12 -080057 private static native void nativeClassInit();
Svet Ganovb9d71a62015-04-30 10:38:13 -070058 private static native long nativeCreate(String opPackageName);
Aravind Akella516e40e2015-07-01 16:54:24 -070059 private static native boolean nativeGetSensorAtIndex(long nativeInstance,
60 Sensor sensor, int index);
Peng Xua35b5532016-01-20 00:05:45 -080061 private static native void nativeGetDynamicSensors(long nativeInstance, List<Sensor> list);
Aravind Akellad123b512015-06-29 12:35:51 -070062 private static native boolean nativeIsDataInjectionEnabled(long nativeInstance);
Jeff Brown25157e42012-04-16 12:13:05 -070063
Peng Xufa2672b2016-12-07 03:54:44 -080064 private static native int nativeCreateDirectChannel(
Peng Xu7d96fa02017-03-04 16:15:45 -080065 long nativeInstance, long size, int channelType, int fd, HardwareBuffer buffer);
Peng Xufa2672b2016-12-07 03:54:44 -080066 private static native void nativeDestroyDirectChannel(
67 long nativeInstance, int channelHandle);
68 private static native int nativeConfigDirectChannel(
69 long nativeInstance, int channelHandle, int sensorHandle, int rate);
70
Peng Xu1cfde252017-01-19 17:10:09 -080071 private static native int nativeSetOperationParameter(
Alexey Polyudov29ad6b32017-05-23 19:54:26 -070072 long nativeInstance, int handle, int type, float[] floatValues, int[] intValues);
Peng Xu1cfde252017-01-19 17:10:09 -080073
Peng Xuaa957272016-03-15 18:16:45 -070074 private static final Object sLock = new Object();
Peng Xu4a4baef2016-03-16 16:56:39 -070075 @GuardedBy("sLock")
76 private static boolean sNativeClassInited = false;
77 @GuardedBy("sLock")
Peng Xuaa957272016-03-15 18:16:45 -070078 private static InjectEventQueue sInjectEventQueue = null;
Svet Ganovb9d71a62015-04-30 10:38:13 -070079
80 private final ArrayList<Sensor> mFullSensorsList = new ArrayList<>();
Peng Xua35b5532016-01-20 00:05:45 -080081 private List<Sensor> mFullDynamicSensorsList = new ArrayList<>();
82 private boolean mDynamicSensorListDirty = true;
83
84 private final HashMap<Integer, Sensor> mHandleToSensor = new HashMap<>();
Svet Ganovb9d71a62015-04-30 10:38:13 -070085
Mathias Agopiandb772d82013-01-31 19:31:12 -080086 // Listener list
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -080087 private final HashMap<SensorEventListener, SensorEventQueue> mSensorListeners =
88 new HashMap<SensorEventListener, SensorEventQueue>();
89 private final HashMap<TriggerEventListener, TriggerEventQueue> mTriggerListeners =
90 new HashMap<TriggerEventListener, TriggerEventQueue>();
Jeff Brown25157e42012-04-16 12:13:05 -070091
Peng Xua35b5532016-01-20 00:05:45 -080092 // Dynamic Sensor callbacks
Peng Xufb1c9412016-03-29 21:50:43 -070093 private HashMap<DynamicSensorCallback, Handler>
Peng Xua35b5532016-01-20 00:05:45 -080094 mDynamicSensorCallbacks = new HashMap<>();
95 private BroadcastReceiver mDynamicSensorBroadcastReceiver;
96
Jeff Brown4481d9c2012-04-16 16:14:44 -070097 // Looper associated with the context in which this instance was created.
Mathias Agopiandb772d82013-01-31 19:31:12 -080098 private final Looper mMainLooper;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -070099 private final int mTargetSdkLevel;
Svet Ganovb9d71a62015-04-30 10:38:13 -0700100 private final Context mContext;
Svet Ganovb9d71a62015-04-30 10:38:13 -0700101 private final long mNativeInstance;
Jeff Brown25157e42012-04-16 12:13:05 -0700102
Mathias Agopiandb772d82013-01-31 19:31:12 -0800103 /** {@hide} */
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700104 public SystemSensorManager(Context context, Looper mainLooper) {
Peng Xu62f2c872017-09-22 11:50:33 -0700105 synchronized (sLock) {
Peng Xu4a4baef2016-03-16 16:56:39 -0700106 if (!sNativeClassInited) {
107 sNativeClassInited = true;
Peng Xuaa957272016-03-15 18:16:45 -0700108 nativeClassInit();
109 }
110 }
111
Jeff Brown25157e42012-04-16 12:13:05 -0700112 mMainLooper = mainLooper;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700113 mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
Svet Ganovb9d71a62015-04-30 10:38:13 -0700114 mContext = context;
115 mNativeInstance = nativeCreate(context.getOpPackageName());
116
Peng Xuaa957272016-03-15 18:16:45 -0700117 // initialize the sensor list
Peng Xu62f2c872017-09-22 11:50:33 -0700118 for (int index = 0;; ++index) {
Peng Xuaa957272016-03-15 18:16:45 -0700119 Sensor sensor = new Sensor();
120 if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
121 mFullSensorsList.add(sensor);
122 mHandleToSensor.put(sensor.getHandle(), sensor);
Aravind Akella516e40e2015-07-01 16:54:24 -0700123 }
Jeff Brown25157e42012-04-16 12:13:05 -0700124 }
125
Mathias Agopiandb772d82013-01-31 19:31:12 -0800126
Jeff Brown25157e42012-04-16 12:13:05 -0700127 /** @hide */
128 @Override
129 protected List<Sensor> getFullSensorList() {
Svet Ganovb9d71a62015-04-30 10:38:13 -0700130 return mFullSensorsList;
Jeff Brown25157e42012-04-16 12:13:05 -0700131 }
132
Peng Xua35b5532016-01-20 00:05:45 -0800133 /** @hide */
134 @Override
135 protected List<Sensor> getFullDynamicSensorList() {
136 // only set up broadcast receiver if the application tries to find dynamic sensors or
Peng Xufb1c9412016-03-29 21:50:43 -0700137 // explicitly register a DynamicSensorCallback
Peng Xua35b5532016-01-20 00:05:45 -0800138 setupDynamicSensorBroadcastReceiver();
139 updateDynamicSensorList();
140 return mFullDynamicSensorsList;
141 }
Jeff Brown25157e42012-04-16 12:13:05 -0700142
143 /** @hide */
Jeff Brown4481d9c2012-04-16 16:14:44 -0700144 @Override
Jeff Brown25157e42012-04-16 12:13:05 -0700145 protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700146 int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {
147 if (listener == null || sensor == null) {
148 Log.e(TAG, "sensor or listener is null");
149 return false;
150 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700151 // Trigger Sensors should use the requestTriggerSensor call.
Aravind Akella27900352014-06-03 19:20:42 -0700152 if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700153 Log.e(TAG, "Trigger Sensors should use the requestTriggerSensor.");
154 return false;
155 }
156 if (maxBatchReportLatencyUs < 0 || delayUs < 0) {
157 Log.e(TAG, "maxBatchReportLatencyUs and delayUs should be non-negative");
158 return false;
159 }
songjinshib5322b22017-03-15 16:16:05 +0800160 if (mSensorListeners.size() >= MAX_LISTENER_COUNT) {
Peng Xu62f2c872017-09-22 11:50:33 -0700161 throw new IllegalStateException("register failed, "
162 + "the sensor listeners size has exceeded the maximum limit "
163 + MAX_LISTENER_COUNT);
songjinshib5322b22017-03-15 16:16:05 +0800164 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700165
Mathias Agopiandb772d82013-01-31 19:31:12 -0800166 // Invariants to preserve:
167 // - one Looper per SensorEventListener
168 // - one Looper per SensorEventQueue
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800169 // We map SensorEventListener to a SensorEventQueue, which holds the looper
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800170 synchronized (mSensorListeners) {
171 SensorEventQueue queue = mSensorListeners.get(listener);
172 if (queue == null) {
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700173 Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
Peng Xu62f2c872017-09-22 11:50:33 -0700174 final String fullClassName =
175 listener.getClass().getEnclosingClass() != null
176 ? listener.getClass().getEnclosingClass().getName()
177 : listener.getClass().getName();
Aravind Akella11fce8e2015-07-09 14:11:45 -0700178 queue = new SensorEventQueue(listener, looper, this, fullClassName);
Aravind Akella88445992015-02-26 17:05:28 -0800179 if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs)) {
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700180 queue.dispose();
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800181 return false;
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700182 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800183 mSensorListeners.put(listener, queue);
184 return true;
185 } else {
Aravind Akella88445992015-02-26 17:05:28 -0800186 return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs);
Jeff Brown25157e42012-04-16 12:13:05 -0700187 }
188 }
Jeff Brown25157e42012-04-16 12:13:05 -0700189 }
190
191 /** @hide */
192 @Override
193 protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800194 // Trigger Sensors should use the cancelTriggerSensor call.
Aravind Akella27900352014-06-03 19:20:42 -0700195 if (sensor != null && sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800196 return;
197 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800198
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800199 synchronized (mSensorListeners) {
200 SensorEventQueue queue = mSensorListeners.get(listener);
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700201 if (queue != null) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800202 boolean result;
203 if (sensor == null) {
204 result = queue.removeAllSensors();
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700205 } else {
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700206 result = queue.removeSensor(sensor, true);
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700207 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800208 if (result && !queue.hasSensors()) {
209 mSensorListeners.remove(listener);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800210 queue.dispose();
Jeff Brown25157e42012-04-16 12:13:05 -0700211 }
212 }
213 }
214 }
215
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800216 /** @hide */
217 @Override
218 protected boolean requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor) {
219 if (sensor == null) throw new IllegalArgumentException("sensor cannot be null");
Jeff Brown25157e42012-04-16 12:13:05 -0700220
Aravind Akella11fce8e2015-07-09 14:11:45 -0700221 if (listener == null) throw new IllegalArgumentException("listener cannot be null");
222
Aravind Akella27900352014-06-03 19:20:42 -0700223 if (sensor.getReportingMode() != Sensor.REPORTING_MODE_ONE_SHOT) return false;
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800224
songjinshib5322b22017-03-15 16:16:05 +0800225 if (mTriggerListeners.size() >= MAX_LISTENER_COUNT) {
Peng Xu62f2c872017-09-22 11:50:33 -0700226 throw new IllegalStateException("request failed, "
227 + "the trigger listeners size has exceeded the maximum limit "
228 + MAX_LISTENER_COUNT);
songjinshib5322b22017-03-15 16:16:05 +0800229 }
230
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800231 synchronized (mTriggerListeners) {
232 TriggerEventQueue queue = mTriggerListeners.get(listener);
233 if (queue == null) {
Peng Xu62f2c872017-09-22 11:50:33 -0700234 final String fullClassName =
235 listener.getClass().getEnclosingClass() != null
236 ? listener.getClass().getEnclosingClass().getName()
237 : listener.getClass().getName();
Aravind Akella11fce8e2015-07-09 14:11:45 -0700238 queue = new TriggerEventQueue(listener, mMainLooper, this, fullClassName);
Aravind Akella88445992015-02-26 17:05:28 -0800239 if (!queue.addSensor(sensor, 0, 0)) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800240 queue.dispose();
241 return false;
242 }
243 mTriggerListeners.put(listener, queue);
244 return true;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800245 } else {
Aravind Akella88445992015-02-26 17:05:28 -0800246 return queue.addSensor(sensor, 0, 0);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800247 }
248 }
249 }
Jeff Brown25157e42012-04-16 12:13:05 -0700250
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800251 /** @hide */
252 @Override
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700253 protected boolean cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor,
254 boolean disable) {
Aravind Akella27900352014-06-03 19:20:42 -0700255 if (sensor != null && sensor.getReportingMode() != Sensor.REPORTING_MODE_ONE_SHOT) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800256 return false;
257 }
258 synchronized (mTriggerListeners) {
259 TriggerEventQueue queue = mTriggerListeners.get(listener);
260 if (queue != null) {
261 boolean result;
262 if (sensor == null) {
263 result = queue.removeAllSensors();
264 } else {
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700265 result = queue.removeSensor(sensor, disable);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800266 }
267 if (result && !queue.hasSensors()) {
268 mTriggerListeners.remove(listener);
269 queue.dispose();
270 }
271 return result;
272 }
273 return false;
274 }
275 }
276
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700277 protected boolean flushImpl(SensorEventListener listener) {
278 if (listener == null) throw new IllegalArgumentException("listener cannot be null");
Aravind Akellab4c76b12013-06-27 12:04:16 -0700279
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700280 synchronized (mSensorListeners) {
281 SensorEventQueue queue = mSensorListeners.get(listener);
282 if (queue == null) {
283 return false;
284 } else {
285 return (queue.flush() == 0);
286 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700287 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700288 }
289
Aravind Akellad123b512015-06-29 12:35:51 -0700290 protected boolean initDataInjectionImpl(boolean enable) {
Peng Xuaa957272016-03-15 18:16:45 -0700291 synchronized (sLock) {
Aravind Akellad123b512015-06-29 12:35:51 -0700292 if (enable) {
293 boolean isDataInjectionModeEnabled = nativeIsDataInjectionEnabled(mNativeInstance);
294 // The HAL does not support injection OR SensorService hasn't been set in DI mode.
295 if (!isDataInjectionModeEnabled) {
296 Log.e(TAG, "Data Injection mode not enabled");
297 return false;
298 }
Aravind Akellad123b512015-06-29 12:35:51 -0700299 // Initialize a client for data_injection.
Peng Xuaa957272016-03-15 18:16:45 -0700300 if (sInjectEventQueue == null) {
Peng Xud9d4e1b2017-04-23 15:23:07 -0700301 try {
302 sInjectEventQueue = new InjectEventQueue(
303 mMainLooper, this, mContext.getPackageName());
304 } catch (RuntimeException e) {
305 Log.e(TAG, "Cannot create InjectEventQueue: " + e);
306 }
Aravind Akellad123b512015-06-29 12:35:51 -0700307 }
Peng Xud9d4e1b2017-04-23 15:23:07 -0700308 return sInjectEventQueue != null;
Aravind Akellad123b512015-06-29 12:35:51 -0700309 } else {
310 // If data injection is being disabled clean up the native resources.
Peng Xuaa957272016-03-15 18:16:45 -0700311 if (sInjectEventQueue != null) {
312 sInjectEventQueue.dispose();
313 sInjectEventQueue = null;
Aravind Akellad123b512015-06-29 12:35:51 -0700314 }
Peng Xud9d4e1b2017-04-23 15:23:07 -0700315 return true;
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700316 }
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700317 }
318 }
319
320 protected boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy,
321 long timestamp) {
Peng Xuaa957272016-03-15 18:16:45 -0700322 synchronized (sLock) {
323 if (sInjectEventQueue == null) {
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700324 Log.e(TAG, "Data injection mode not activated before calling injectSensorData");
325 return false;
326 }
Peng Xuaa957272016-03-15 18:16:45 -0700327 int ret = sInjectEventQueue.injectSensorData(sensor.getHandle(), values, accuracy,
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700328 timestamp);
329 // If there are any errors in data injection clean up the native resources.
330 if (ret != 0) {
Peng Xuaa957272016-03-15 18:16:45 -0700331 sInjectEventQueue.dispose();
332 sInjectEventQueue = null;
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700333 }
334 return ret == 0;
335 }
336 }
337
Peng Xua35b5532016-01-20 00:05:45 -0800338 private void cleanupSensorConnection(Sensor sensor) {
339 mHandleToSensor.remove(sensor.getHandle());
340
341 if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
Peng Xu62f2c872017-09-22 11:50:33 -0700342 synchronized (mTriggerListeners) {
Daniel Moore1ff9e7a2017-02-16 08:57:03 -0600343 HashMap<TriggerEventListener, TriggerEventQueue> triggerListeners =
Peng Xu62f2c872017-09-22 11:50:33 -0700344 new HashMap<TriggerEventListener, TriggerEventQueue>(mTriggerListeners);
Daniel Moore1ff9e7a2017-02-16 08:57:03 -0600345
Peng Xu62f2c872017-09-22 11:50:33 -0700346 for (TriggerEventListener l : triggerListeners.keySet()) {
347 if (DEBUG_DYNAMIC_SENSOR) {
348 Log.i(TAG, "removed trigger listener" + l.toString()
349 + " due to sensor disconnection");
Peng Xua35b5532016-01-20 00:05:45 -0800350 }
351 cancelTriggerSensorImpl(l, sensor, true);
352 }
353 }
354 } else {
Peng Xu62f2c872017-09-22 11:50:33 -0700355 synchronized (mSensorListeners) {
Daniel Moore1ff9e7a2017-02-16 08:57:03 -0600356 HashMap<SensorEventListener, SensorEventQueue> sensorListeners =
Peng Xu62f2c872017-09-22 11:50:33 -0700357 new HashMap<SensorEventListener, SensorEventQueue>(mSensorListeners);
Daniel Moore1ff9e7a2017-02-16 08:57:03 -0600358
359 for (SensorEventListener l: sensorListeners.keySet()) {
Peng Xu62f2c872017-09-22 11:50:33 -0700360 if (DEBUG_DYNAMIC_SENSOR) {
361 Log.i(TAG, "removed event listener" + l.toString()
362 + " due to sensor disconnection");
Peng Xua35b5532016-01-20 00:05:45 -0800363 }
364 unregisterListenerImpl(l, sensor);
365 }
366 }
367 }
368 }
369
370 private void updateDynamicSensorList() {
Peng Xu62f2c872017-09-22 11:50:33 -0700371 synchronized (mFullDynamicSensorsList) {
Peng Xua35b5532016-01-20 00:05:45 -0800372 if (mDynamicSensorListDirty) {
373 List<Sensor> list = new ArrayList<>();
374 nativeGetDynamicSensors(mNativeInstance, list);
375
376 final List<Sensor> updatedList = new ArrayList<>();
377 final List<Sensor> addedList = new ArrayList<>();
378 final List<Sensor> removedList = new ArrayList<>();
379
380 boolean changed = diffSortedSensorList(
381 mFullDynamicSensorsList, list, updatedList, addedList, removedList);
382
383 if (changed) {
384 if (DEBUG_DYNAMIC_SENSOR) {
385 Log.i(TAG, "DYNS dynamic sensor list cached should be updated");
386 }
387 mFullDynamicSensorsList = updatedList;
388
389 for (Sensor s: addedList) {
390 mHandleToSensor.put(s.getHandle(), s);
391 }
392
393 Handler mainHandler = new Handler(mContext.getMainLooper());
394
Peng Xufb1c9412016-03-29 21:50:43 -0700395 for (Map.Entry<DynamicSensorCallback, Handler> entry :
Peng Xua35b5532016-01-20 00:05:45 -0800396 mDynamicSensorCallbacks.entrySet()) {
Peng Xufb1c9412016-03-29 21:50:43 -0700397 final DynamicSensorCallback callback = entry.getKey();
Peng Xua35b5532016-01-20 00:05:45 -0800398 Handler handler =
399 entry.getValue() == null ? mainHandler : entry.getValue();
400
401 handler.post(new Runnable() {
402 @Override
403 public void run() {
404 for (Sensor s: addedList) {
405 callback.onDynamicSensorConnected(s);
406 }
407 for (Sensor s: removedList) {
408 callback.onDynamicSensorDisconnected(s);
409 }
410 }
411 });
412 }
413
414 for (Sensor s: removedList) {
415 cleanupSensorConnection(s);
416 }
417 }
418
419 mDynamicSensorListDirty = false;
420 }
421 }
422 }
423
424 private void setupDynamicSensorBroadcastReceiver() {
425 if (mDynamicSensorBroadcastReceiver == null) {
426 mDynamicSensorBroadcastReceiver = new BroadcastReceiver() {
427 @Override
428 public void onReceive(Context context, Intent intent) {
429 if (intent.getAction() == Intent.ACTION_DYNAMIC_SENSOR_CHANGED) {
430 if (DEBUG_DYNAMIC_SENSOR) {
431 Log.i(TAG, "DYNS received DYNAMIC_SENSOR_CHANED broadcast");
432 }
433 // Dynamic sensors probably changed
434 mDynamicSensorListDirty = true;
435 updateDynamicSensorList();
436 }
437 }
438 };
439
440 IntentFilter filter = new IntentFilter("dynamic_sensor_change");
441 filter.addAction(Intent.ACTION_DYNAMIC_SENSOR_CHANGED);
442 mContext.registerReceiver(mDynamicSensorBroadcastReceiver, filter);
443 }
444 }
445
446 private void teardownDynamicSensorBroadcastReceiver() {
447 mDynamicSensorCallbacks.clear();
448 mContext.unregisterReceiver(mDynamicSensorBroadcastReceiver);
449 mDynamicSensorBroadcastReceiver = null;
450 }
451
452 /** @hide */
453 protected void registerDynamicSensorCallbackImpl(
Peng Xufb1c9412016-03-29 21:50:43 -0700454 DynamicSensorCallback callback, Handler handler) {
Peng Xua35b5532016-01-20 00:05:45 -0800455 if (DEBUG_DYNAMIC_SENSOR) {
456 Log.i(TAG, "DYNS Register dynamic sensor callback");
457 }
458
459 if (callback == null) {
460 throw new IllegalArgumentException("callback cannot be null");
461 }
462 if (mDynamicSensorCallbacks.containsKey(callback)) {
463 // has been already registered, ignore
464 return;
465 }
466
467 setupDynamicSensorBroadcastReceiver();
468 mDynamicSensorCallbacks.put(callback, handler);
469 }
470
471 /** @hide */
472 protected void unregisterDynamicSensorCallbackImpl(
Peng Xufb1c9412016-03-29 21:50:43 -0700473 DynamicSensorCallback callback) {
Peng Xua35b5532016-01-20 00:05:45 -0800474 if (DEBUG_DYNAMIC_SENSOR) {
475 Log.i(TAG, "Removing dynamic sensor listerner");
476 }
477 mDynamicSensorCallbacks.remove(callback);
478 }
479
480 /*
481 * Find the difference of two List<Sensor> assuming List are sorted by handle of sensor,
482 * assuming the input list is already sorted by handle. Inputs are ol and nl; outputs are
483 * updated, added and removed. Any of the output lists can be null in case the result is not
484 * interested.
485 */
486 private static boolean diffSortedSensorList(
487 List<Sensor> oldList, List<Sensor> newList, List<Sensor> updated,
488 List<Sensor> added, List<Sensor> removed) {
489
490 boolean changed = false;
491
492 int i = 0, j = 0;
493 while (true) {
Peng Xu62f2c872017-09-22 11:50:33 -0700494 if (j < oldList.size() && (i >= newList.size()
495 || newList.get(i).getHandle() > oldList.get(j).getHandle())) {
Peng Xua35b5532016-01-20 00:05:45 -0800496 changed = true;
497 if (removed != null) {
498 removed.add(oldList.get(j));
499 }
500 ++j;
Peng Xu62f2c872017-09-22 11:50:33 -0700501 } else if (i < newList.size() && (j >= oldList.size()
502 || newList.get(i).getHandle() < oldList.get(j).getHandle())) {
Peng Xua35b5532016-01-20 00:05:45 -0800503 changed = true;
504 if (added != null) {
505 added.add(newList.get(i));
506 }
507 if (updated != null) {
508 updated.add(newList.get(i));
509 }
510 ++i;
Peng Xu62f2c872017-09-22 11:50:33 -0700511 } else if (i < newList.size() && j < oldList.size()
512 && newList.get(i).getHandle() == oldList.get(j).getHandle()) {
Peng Xua35b5532016-01-20 00:05:45 -0800513 if (updated != null) {
514 updated.add(oldList.get(j));
515 }
516 ++i;
517 ++j;
518 } else {
519 break;
520 }
521 }
522 return changed;
523 }
524
Peng Xufa2672b2016-12-07 03:54:44 -0800525 /** @hide */
526 protected int configureDirectChannelImpl(
527 SensorDirectChannel channel, Sensor sensor, int rate) {
Peng Xu3c8c6a42017-04-06 18:37:56 -0700528 if (!channel.isOpen()) {
529 throw new IllegalStateException("channel is closed");
Peng Xufa2672b2016-12-07 03:54:44 -0800530 }
531
532 if (rate < SensorDirectChannel.RATE_STOP
533 || rate > SensorDirectChannel.RATE_VERY_FAST) {
534 throw new IllegalArgumentException("rate parameter invalid");
535 }
536
537 if (sensor == null && rate != SensorDirectChannel.RATE_STOP) {
538 // the stop all sensors case
539 throw new IllegalArgumentException(
540 "when sensor is null, rate can only be DIRECT_RATE_STOP");
541 }
542
543 int sensorHandle = (sensor == null) ? -1 : sensor.getHandle();
544
545 int ret = nativeConfigDirectChannel(
546 mNativeInstance, channel.getNativeHandle(), sensorHandle, rate);
547
548 if (rate == SensorDirectChannel.RATE_STOP) {
549 return (ret == 0) ? 1 : 0;
550 } else {
551 return (ret > 0) ? ret : 0;
552 }
553 }
554
555 /** @hide */
Peng Xu7d96fa02017-03-04 16:15:45 -0800556 protected SensorDirectChannel createDirectChannelImpl(
557 MemoryFile memoryFile, HardwareBuffer hardwareBuffer) {
Peng Xu3c8c6a42017-04-06 18:37:56 -0700558 int id;
559 int type;
Peng Xu7d96fa02017-03-04 16:15:45 -0800560 long size;
561 if (memoryFile != null) {
562 int fd;
563 try {
564 fd = memoryFile.getFileDescriptor().getInt$();
565 } catch (IOException e) {
566 throw new IllegalArgumentException("MemoryFile object is not valid");
Peng Xufa2672b2016-12-07 03:54:44 -0800567 }
Peng Xu7d96fa02017-03-04 16:15:45 -0800568
569 if (memoryFile.length() < MIN_DIRECT_CHANNEL_BUFFER_SIZE) {
570 throw new IllegalArgumentException(
571 "Size of MemoryFile has to be greater than "
572 + MIN_DIRECT_CHANNEL_BUFFER_SIZE);
573 }
574
575 size = memoryFile.length();
Peng Xu3c8c6a42017-04-06 18:37:56 -0700576 id = nativeCreateDirectChannel(
577 mNativeInstance, size, SensorDirectChannel.TYPE_MEMORY_FILE, fd, null);
578 if (id <= 0) {
579 throw new UncheckedIOException(
580 new IOException("create MemoryFile direct channel failed " + id));
Peng Xufa2672b2016-12-07 03:54:44 -0800581 }
Peng Xu3c8c6a42017-04-06 18:37:56 -0700582 type = SensorDirectChannel.TYPE_MEMORY_FILE;
Peng Xu7d96fa02017-03-04 16:15:45 -0800583 } else if (hardwareBuffer != null) {
584 if (hardwareBuffer.getFormat() != HardwareBuffer.BLOB) {
585 throw new IllegalArgumentException("Format of HardwareBuffer must be BLOB");
586 }
587 if (hardwareBuffer.getHeight() != 1) {
588 throw new IllegalArgumentException("Height of HardwareBuffer must be 1");
589 }
590 if (hardwareBuffer.getWidth() < MIN_DIRECT_CHANNEL_BUFFER_SIZE) {
591 throw new IllegalArgumentException(
592 "Width if HaradwareBuffer must be greater than "
593 + MIN_DIRECT_CHANNEL_BUFFER_SIZE);
594 }
Mathias Agopian910ab132017-04-20 16:36:15 -0700595 if ((hardwareBuffer.getUsage() & HardwareBuffer.USAGE_SENSOR_DIRECT_DATA) == 0) {
Peng Xu7d96fa02017-03-04 16:15:45 -0800596 throw new IllegalArgumentException(
Mathias Agopian910ab132017-04-20 16:36:15 -0700597 "HardwareBuffer must set usage flag USAGE_SENSOR_DIRECT_DATA");
Peng Xu7d96fa02017-03-04 16:15:45 -0800598 }
599 size = hardwareBuffer.getWidth();
Peng Xu3c8c6a42017-04-06 18:37:56 -0700600 id = nativeCreateDirectChannel(
Peng Xu7d96fa02017-03-04 16:15:45 -0800601 mNativeInstance, size, SensorDirectChannel.TYPE_HARDWARE_BUFFER,
602 -1, hardwareBuffer);
Peng Xu3c8c6a42017-04-06 18:37:56 -0700603 if (id <= 0) {
604 throw new UncheckedIOException(
605 new IOException("create HardwareBuffer direct channel failed " + id));
Peng Xu7d96fa02017-03-04 16:15:45 -0800606 }
Peng Xu3c8c6a42017-04-06 18:37:56 -0700607 type = SensorDirectChannel.TYPE_HARDWARE_BUFFER;
Peng Xufa2672b2016-12-07 03:54:44 -0800608 } else {
Peng Xu3c8c6a42017-04-06 18:37:56 -0700609 throw new NullPointerException("shared memory object cannot be null");
Peng Xufa2672b2016-12-07 03:54:44 -0800610 }
Peng Xu3c8c6a42017-04-06 18:37:56 -0700611 return new SensorDirectChannel(this, id, type, size);
Peng Xufa2672b2016-12-07 03:54:44 -0800612 }
613
614 /** @hide */
615 protected void destroyDirectChannelImpl(SensorDirectChannel channel) {
616 if (channel != null) {
617 nativeDestroyDirectChannel(mNativeInstance, channel.getNativeHandle());
618 }
619 }
620
Mathias Agopiandb772d82013-01-31 19:31:12 -0800621 /*
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800622 * BaseEventQueue is the communication channel with the sensor service,
623 * SensorEventQueue, TriggerEventQueue are subclases and there is one-to-one mapping between
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700624 * the queues and the listeners. InjectEventQueue is also a sub-class which is a special case
625 * where data is being injected into the sensor HAL through the sensor service. It is not
626 * associated with any listener and there is one InjectEventQueue associated with a
627 * SensorManager instance.
Mathias Agopiandb772d82013-01-31 19:31:12 -0800628 */
Peng Xu62f2c872017-09-22 11:50:33 -0700629 private abstract static class BaseEventQueue {
Svet Ganovb9d71a62015-04-30 10:38:13 -0700630 private static native long nativeInitBaseEventQueue(long nativeManager,
Peng Xua2958352016-01-26 18:42:17 -0800631 WeakReference<BaseEventQueue> eventQWeak, MessageQueue msgQ,
Svet Ganovb9d71a62015-04-30 10:38:13 -0700632 String packageName, int mode, String opPackageName);
Ashok Bhat4838e332014-01-03 14:37:19 +0000633 private static native int nativeEnableSensor(long eventQ, int handle, int rateUs,
Aravind Akella88445992015-02-26 17:05:28 -0800634 int maxBatchReportLatencyUs);
Ashok Bhat4838e332014-01-03 14:37:19 +0000635 private static native int nativeDisableSensor(long eventQ, int handle);
636 private static native void nativeDestroySensorEventQueue(long eventQ);
637 private static native int nativeFlushSensor(long eventQ);
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700638 private static native int nativeInjectSensorData(long eventQ, int handle,
Peng Xu62f2c872017-09-22 11:50:33 -0700639 float[] values, int accuracy, long timestamp);
Svet Ganovb9d71a62015-04-30 10:38:13 -0700640
Peng Xu62f2c872017-09-22 11:50:33 -0700641 private long mNativeSensorEventQueue;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800642 private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800643 protected final SparseIntArray mSensorAccuracies = new SparseIntArray();
Mathias Agopiandb772d82013-01-31 19:31:12 -0800644 private final CloseGuard mCloseGuard = CloseGuard.get();
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700645 protected final SystemSensorManager mManager;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800646
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700647 protected static final int OPERATING_MODE_NORMAL = 0;
648 protected static final int OPERATING_MODE_DATA_INJECTION = 1;
649
Aravind Akella11fce8e2015-07-09 14:11:45 -0700650 BaseEventQueue(Looper looper, SystemSensorManager manager, int mode, String packageName) {
651 if (packageName == null) packageName = "";
Peng Xu62f2c872017-09-22 11:50:33 -0700652 mNativeSensorEventQueue = nativeInitBaseEventQueue(manager.mNativeInstance,
Peng Xua2958352016-01-26 18:42:17 -0800653 new WeakReference<>(this), looper.getQueue(),
Aravind Akella11fce8e2015-07-09 14:11:45 -0700654 packageName, mode, manager.mContext.getOpPackageName());
Mathias Agopiandb772d82013-01-31 19:31:12 -0800655 mCloseGuard.open("dispose");
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700656 mManager = manager;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800657 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800658
Mathias Agopiandb772d82013-01-31 19:31:12 -0800659 public void dispose() {
660 dispose(false);
661 }
662
Aravind Akellab4c76b12013-06-27 12:04:16 -0700663 public boolean addSensor(
Aravind Akella88445992015-02-26 17:05:28 -0800664 Sensor sensor, int delayUs, int maxBatchReportLatencyUs) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800665 // Check if already present.
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700666 int handle = sensor.getHandle();
667 if (mActiveSensors.get(handle)) return false;
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800668
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700669 // Get ready to receive events before calling enable.
670 mActiveSensors.put(handle, true);
671 addSensorEvent(sensor);
Aravind Akella88445992015-02-26 17:05:28 -0800672 if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs) != 0) {
Aravind Akellab4c76b12013-06-27 12:04:16 -0700673 // Try continuous mode if batching fails.
Peng Xu62f2c872017-09-22 11:50:33 -0700674 if (maxBatchReportLatencyUs == 0
675 || maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0) != 0) {
676 removeSensor(sensor, false);
677 return false;
Aravind Akellab4c76b12013-06-27 12:04:16 -0700678 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800679 }
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700680 return true;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800681 }
682
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800683 public boolean removeAllSensors() {
Peng Xu62f2c872017-09-22 11:50:33 -0700684 for (int i = 0; i < mActiveSensors.size(); i++) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800685 if (mActiveSensors.valueAt(i) == true) {
686 int handle = mActiveSensors.keyAt(i);
Svet Ganovb9d71a62015-04-30 10:38:13 -0700687 Sensor sensor = mManager.mHandleToSensor.get(handle);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800688 if (sensor != null) {
689 disableSensor(sensor);
690 mActiveSensors.put(handle, false);
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700691 removeSensorEvent(sensor);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800692 } else {
Peng Xua35b5532016-01-20 00:05:45 -0800693 // sensor just disconnected -- just ignore.
Mathias Agopiandb772d82013-01-31 19:31:12 -0800694 }
695 }
696 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800697 return true;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800698 }
699
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700700 public boolean removeSensor(Sensor sensor, boolean disable) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800701 final int handle = sensor.getHandle();
702 if (mActiveSensors.get(handle)) {
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700703 if (disable) disableSensor(sensor);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800704 mActiveSensors.put(sensor.getHandle(), false);
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700705 removeSensorEvent(sensor);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800706 return true;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800707 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800708 return false;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800709 }
710
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700711 public int flush() {
Peng Xu62f2c872017-09-22 11:50:33 -0700712 if (mNativeSensorEventQueue == 0) throw new NullPointerException();
713 return nativeFlushSensor(mNativeSensorEventQueue);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700714 }
715
Mathias Agopiandb772d82013-01-31 19:31:12 -0800716 public boolean hasSensors() {
717 // no more sensors are set
718 return mActiveSensors.indexOfValue(true) >= 0;
719 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800720
Mathias Agopiandb772d82013-01-31 19:31:12 -0800721 @Override
722 protected void finalize() throws Throwable {
723 try {
724 dispose(true);
725 } finally {
726 super.finalize();
727 }
728 }
729
730 private void dispose(boolean finalized) {
731 if (mCloseGuard != null) {
732 if (finalized) {
733 mCloseGuard.warnIfOpen();
734 }
735 mCloseGuard.close();
736 }
Peng Xu62f2c872017-09-22 11:50:33 -0700737 if (mNativeSensorEventQueue != 0) {
738 nativeDestroySensorEventQueue(mNativeSensorEventQueue);
739 mNativeSensorEventQueue = 0;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800740 }
741 }
742
Aravind Akellab4c76b12013-06-27 12:04:16 -0700743 private int enableSensor(
Aravind Akella88445992015-02-26 17:05:28 -0800744 Sensor sensor, int rateUs, int maxBatchReportLatencyUs) {
Peng Xu62f2c872017-09-22 11:50:33 -0700745 if (mNativeSensorEventQueue == 0) throw new NullPointerException();
Mathias Agopiandb772d82013-01-31 19:31:12 -0800746 if (sensor == null) throw new NullPointerException();
Peng Xu62f2c872017-09-22 11:50:33 -0700747 return nativeEnableSensor(mNativeSensorEventQueue, sensor.getHandle(), rateUs,
Aravind Akella88445992015-02-26 17:05:28 -0800748 maxBatchReportLatencyUs);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800749 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700750
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700751 protected int injectSensorDataBase(int handle, float[] values, int accuracy,
752 long timestamp) {
Peng Xu62f2c872017-09-22 11:50:33 -0700753 return nativeInjectSensorData(
754 mNativeSensorEventQueue, handle, values, accuracy, timestamp);
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700755 }
756
Mathias Agopiandb772d82013-01-31 19:31:12 -0800757 private int disableSensor(Sensor sensor) {
Peng Xu62f2c872017-09-22 11:50:33 -0700758 if (mNativeSensorEventQueue == 0) throw new NullPointerException();
Mathias Agopiandb772d82013-01-31 19:31:12 -0800759 if (sensor == null) throw new NullPointerException();
Peng Xu62f2c872017-09-22 11:50:33 -0700760 return nativeDisableSensor(mNativeSensorEventQueue, sensor.getHandle());
Mathias Agopiandb772d82013-01-31 19:31:12 -0800761 }
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100762 @UnsupportedAppUsage
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800763 protected abstract void dispatchSensorEvent(int handle, float[] values, int accuracy,
764 long timestamp);
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100765 @UnsupportedAppUsage
Aravind Akellab4c76b12013-06-27 12:04:16 -0700766 protected abstract void dispatchFlushCompleteEvent(int handle);
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700767
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100768 @UnsupportedAppUsage
Peng Xua2958352016-01-26 18:42:17 -0800769 protected void dispatchAdditionalInfoEvent(
770 int handle, int type, int serial, float[] floatValues, int[] intValues) {
771 // default implementation is do nothing
772 }
773
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700774 protected abstract void addSensorEvent(Sensor sensor);
775 protected abstract void removeSensorEvent(Sensor sensor);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800776 }
777
778 static final class SensorEventQueue extends BaseEventQueue {
779 private final SensorEventListener mListener;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700780 private final SparseArray<SensorEvent> mSensorsEvents = new SparseArray<SensorEvent>();
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800781
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700782 public SensorEventQueue(SensorEventListener listener, Looper looper,
Aravind Akella11fce8e2015-07-09 14:11:45 -0700783 SystemSensorManager manager, String packageName) {
784 super(looper, manager, OPERATING_MODE_NORMAL, packageName);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800785 mListener = listener;
786 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800787
Aravind Akella31d14ce2013-10-22 20:04:22 -0700788 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700789 public void addSensorEvent(Sensor sensor) {
790 SensorEvent t = new SensorEvent(Sensor.getMaxLengthValuesArray(sensor,
791 mManager.mTargetSdkLevel));
Aravind Akella31d14ce2013-10-22 20:04:22 -0700792 synchronized (mSensorsEvents) {
793 mSensorsEvents.put(sensor.getHandle(), t);
794 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700795 }
796
Aravind Akella31d14ce2013-10-22 20:04:22 -0700797 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700798 public void removeSensorEvent(Sensor sensor) {
Aravind Akella31d14ce2013-10-22 20:04:22 -0700799 synchronized (mSensorsEvents) {
800 mSensorsEvents.delete(sensor.getHandle());
801 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700802 }
803
Mathias Agopiandb772d82013-01-31 19:31:12 -0800804 // Called from native code.
805 @SuppressWarnings("unused")
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800806 @Override
807 protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,
808 long timestamp) {
Svet Ganovb9d71a62015-04-30 10:38:13 -0700809 final Sensor sensor = mManager.mHandleToSensor.get(handle);
Peng Xua35b5532016-01-20 00:05:45 -0800810 if (sensor == null) {
811 // sensor disconnected
812 return;
813 }
814
Aravind Akella31d14ce2013-10-22 20:04:22 -0700815 SensorEvent t = null;
816 synchronized (mSensorsEvents) {
817 t = mSensorsEvents.get(handle);
818 }
819
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700820 if (t == null) {
Aravind Akella31d14ce2013-10-22 20:04:22 -0700821 // This may happen if the client has unregistered and there are pending events in
822 // the queue waiting to be delivered. Ignore.
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700823 return;
824 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700825 // Copy from the values array.
826 System.arraycopy(values, 0, t.values, 0, t.values.length);
827 t.timestamp = timestamp;
828 t.accuracy = inAccuracy;
829 t.sensor = sensor;
Etienne Le Grandaf805102014-05-16 12:21:41 -0700830
831 // call onAccuracyChanged() only if the value changes
832 final int accuracy = mSensorAccuracies.get(handle);
833 if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
834 mSensorAccuracies.put(handle, t.accuracy);
835 mListener.onAccuracyChanged(t.sensor, t.accuracy);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800836 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700837 mListener.onSensorChanged(t);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800838 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700839
Peng Xua2958352016-01-26 18:42:17 -0800840 // Called from native code.
Aravind Akellab4c76b12013-06-27 12:04:16 -0700841 @SuppressWarnings("unused")
Peng Xua2958352016-01-26 18:42:17 -0800842 @Override
Aravind Akellab4c76b12013-06-27 12:04:16 -0700843 protected void dispatchFlushCompleteEvent(int handle) {
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700844 if (mListener instanceof SensorEventListener2) {
Svet Ganovb9d71a62015-04-30 10:38:13 -0700845 final Sensor sensor = mManager.mHandleToSensor.get(handle);
Peng Xua35b5532016-01-20 00:05:45 -0800846 if (sensor == null) {
847 // sensor disconnected
848 return;
849 }
Peng Xu62f2c872017-09-22 11:50:33 -0700850 ((SensorEventListener2) mListener).onFlushCompleted(sensor);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700851 }
852 return;
853 }
Peng Xua2958352016-01-26 18:42:17 -0800854
855 // Called from native code.
856 @SuppressWarnings("unused")
857 @Override
858 protected void dispatchAdditionalInfoEvent(
859 int handle, int type, int serial, float[] floatValues, int[] intValues) {
860 if (mListener instanceof SensorEventCallback) {
861 final Sensor sensor = mManager.mHandleToSensor.get(handle);
862 if (sensor == null) {
863 // sensor disconnected
864 return;
865 }
866 SensorAdditionalInfo info =
867 new SensorAdditionalInfo(sensor, type, serial, intValues, floatValues);
Peng Xu62f2c872017-09-22 11:50:33 -0700868 ((SensorEventCallback) mListener).onSensorAdditionalInfo(info);
Peng Xua2958352016-01-26 18:42:17 -0800869 }
870 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800871 }
872
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800873 static final class TriggerEventQueue extends BaseEventQueue {
874 private final TriggerEventListener mListener;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700875 private final SparseArray<TriggerEvent> mTriggerEvents = new SparseArray<TriggerEvent>();
Mathias Agopiandb772d82013-01-31 19:31:12 -0800876
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800877 public TriggerEventQueue(TriggerEventListener listener, Looper looper,
Aravind Akella11fce8e2015-07-09 14:11:45 -0700878 SystemSensorManager manager, String packageName) {
879 super(looper, manager, OPERATING_MODE_NORMAL, packageName);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800880 mListener = listener;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700881 }
882
Aravind Akella31d14ce2013-10-22 20:04:22 -0700883 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700884 public void addSensorEvent(Sensor sensor) {
885 TriggerEvent t = new TriggerEvent(Sensor.getMaxLengthValuesArray(sensor,
886 mManager.mTargetSdkLevel));
Aravind Akella31d14ce2013-10-22 20:04:22 -0700887 synchronized (mTriggerEvents) {
888 mTriggerEvents.put(sensor.getHandle(), t);
889 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700890 }
891
Aravind Akella31d14ce2013-10-22 20:04:22 -0700892 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700893 public void removeSensorEvent(Sensor sensor) {
Aravind Akella31d14ce2013-10-22 20:04:22 -0700894 synchronized (mTriggerEvents) {
895 mTriggerEvents.delete(sensor.getHandle());
896 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800897 }
898
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800899 // Called from native code.
900 @SuppressWarnings("unused")
901 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700902 protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
903 long timestamp) {
Svet Ganovb9d71a62015-04-30 10:38:13 -0700904 final Sensor sensor = mManager.mHandleToSensor.get(handle);
Peng Xua35b5532016-01-20 00:05:45 -0800905 if (sensor == null) {
906 // sensor disconnected
907 return;
908 }
Aravind Akella31d14ce2013-10-22 20:04:22 -0700909 TriggerEvent t = null;
910 synchronized (mTriggerEvents) {
911 t = mTriggerEvents.get(handle);
912 }
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700913 if (t == null) {
914 Log.e(TAG, "Error: Trigger Event is null for Sensor: " + sensor);
915 return;
916 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800917
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700918 // Copy from the values array.
919 System.arraycopy(values, 0, t.values, 0, t.values.length);
920 t.timestamp = timestamp;
921 t.sensor = sensor;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800922
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700923 // A trigger sensor is auto disabled. So just clean up and don't call native
924 // disable.
925 mManager.cancelTriggerSensorImpl(mListener, sensor, false);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800926
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700927 mListener.onTrigger(t);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800928 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700929
930 @SuppressWarnings("unused")
931 protected void dispatchFlushCompleteEvent(int handle) {
932 }
933 }
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700934
Svet Ganovb9d71a62015-04-30 10:38:13 -0700935 final class InjectEventQueue extends BaseEventQueue {
Aravind Akella11fce8e2015-07-09 14:11:45 -0700936 public InjectEventQueue(Looper looper, SystemSensorManager manager, String packageName) {
937 super(looper, manager, OPERATING_MODE_DATA_INJECTION, packageName);
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700938 }
939
Peng Xu62f2c872017-09-22 11:50:33 -0700940 int injectSensorData(int handle, float[] values, int accuracy, long timestamp) {
941 return injectSensorDataBase(handle, values, accuracy, timestamp);
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700942 }
943
944 @SuppressWarnings("unused")
945 protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
946 long timestamp) {
947 }
948
949 @SuppressWarnings("unused")
950 protected void dispatchFlushCompleteEvent(int handle) {
951
952 }
953
954 @SuppressWarnings("unused")
955 protected void addSensorEvent(Sensor sensor) {
956
957 }
958
959 @SuppressWarnings("unused")
960 protected void removeSensorEvent(Sensor sensor) {
961
962 }
963 }
Peng Xu1cfde252017-01-19 17:10:09 -0800964
965 protected boolean setOperationParameterImpl(SensorAdditionalInfo parameter) {
Alexey Polyudov29ad6b32017-05-23 19:54:26 -0700966 int handle = -1;
967 if (parameter.sensor != null) handle = parameter.sensor.getHandle();
Peng Xu1cfde252017-01-19 17:10:09 -0800968 return nativeSetOperationParameter(
Peng Xu62f2c872017-09-22 11:50:33 -0700969 mNativeInstance, handle,
970 parameter.type, parameter.floatValues, parameter.intValues) == 0;
Peng Xu1cfde252017-01-19 17:10:09 -0800971 }
Jeff Brown25157e42012-04-16 12:13:05 -0700972}