blob: 11037fd69604ba4ae81628b3f76f5ff86776e35a [file] [log] [blame]
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -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
Aravind Akella18ebf732b2015-04-20 17:39:51 -070019import android.Manifest;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -070020import android.content.Context;
Aravind Akella18ebf732b2015-04-20 17:39:51 -070021import android.content.pm.PackageManager;
Jeff Brown25157e42012-04-16 12:13:05 -070022import android.os.Handler;
Mathias Agopiandb772d82013-01-31 19:31:12 -080023import android.os.Looper;
24import android.os.MessageQueue;
Jaikumar Ganesh2e900892013-04-11 10:40:33 -070025import android.util.Log;
Jeff Brown25157e42012-04-16 12:13:05 -070026import android.util.SparseArray;
27import android.util.SparseBooleanArray;
28import android.util.SparseIntArray;
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -080029import dalvik.system.CloseGuard;
30
Jeff Brown3b4049e2015-04-17 15:22:27 -070031import java.lang.ref.WeakReference;
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -080032import java.util.ArrayList;
33import java.util.HashMap;
34import java.util.List;
Jeff Brown25157e42012-04-16 12:13:05 -070035
Jeff Brown25157e42012-04-16 12:13:05 -070036/**
37 * Sensor manager implementation that communicates with the built-in
38 * system sensors.
39 *
40 * @hide
41 */
42public class SystemSensorManager extends SensorManager {
Mathias Agopiandb772d82013-01-31 19:31:12 -080043 private static native void nativeClassInit();
44 private static native int nativeGetNextSensor(Sensor sensor, int next);
Aravind Akella18ebf732b2015-04-20 17:39:51 -070045 private static native int nativeEnableDataInjection(boolean enable);
Jeff Brown25157e42012-04-16 12:13:05 -070046
Mathias Agopiandb772d82013-01-31 19:31:12 -080047 private static boolean sSensorModuleInitialized = false;
48 private static final Object sSensorModuleLock = new Object();
49 private static final ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>();
50 private static final SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
Aravind Akella18ebf732b2015-04-20 17:39:51 -070051 private static InjectEventQueue mInjectEventQueue = null;
52 private static boolean mDataInjectionMode = false;
Mathias Agopiandb772d82013-01-31 19:31:12 -080053
54 // Listener list
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -080055 private final HashMap<SensorEventListener, SensorEventQueue> mSensorListeners =
56 new HashMap<SensorEventListener, SensorEventQueue>();
57 private final HashMap<TriggerEventListener, TriggerEventQueue> mTriggerListeners =
58 new HashMap<TriggerEventListener, TriggerEventQueue>();
Jeff Brown25157e42012-04-16 12:13:05 -070059
Jeff Brown4481d9c2012-04-16 16:14:44 -070060 // Looper associated with the context in which this instance was created.
Mathias Agopiandb772d82013-01-31 19:31:12 -080061 private final Looper mMainLooper;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -070062 private final int mTargetSdkLevel;
Aravind Akella88445992015-02-26 17:05:28 -080063 private final String mPackageName;
Aravind Akella18ebf732b2015-04-20 17:39:51 -070064 private final boolean mHasDataInjectionPermissions;
Jeff Brown25157e42012-04-16 12:13:05 -070065
Mathias Agopiandb772d82013-01-31 19:31:12 -080066 /** {@hide} */
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -070067 public SystemSensorManager(Context context, Looper mainLooper) {
Jeff Brown25157e42012-04-16 12:13:05 -070068 mMainLooper = mainLooper;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -070069 mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
Aravind Akella88445992015-02-26 17:05:28 -080070 mPackageName = context.getPackageName();
Mathias Agopiandb772d82013-01-31 19:31:12 -080071 synchronized(sSensorModuleLock) {
Jeff Brown25157e42012-04-16 12:13:05 -070072 if (!sSensorModuleInitialized) {
73 sSensorModuleInitialized = true;
74
75 nativeClassInit();
76
77 // initialize the sensor list
Jeff Brown25157e42012-04-16 12:13:05 -070078 final ArrayList<Sensor> fullList = sFullSensorsList;
79 int i = 0;
80 do {
81 Sensor sensor = new Sensor();
Mathias Agopiandb772d82013-01-31 19:31:12 -080082 i = nativeGetNextSensor(sensor, i);
Jeff Brown25157e42012-04-16 12:13:05 -070083 if (i>=0) {
84 //Log.d(TAG, "found sensor: " + sensor.getName() +
85 // ", handle=" + sensor.getHandle());
86 fullList.add(sensor);
87 sHandleToSensor.append(sensor.getHandle(), sensor);
88 }
89 } while (i>0);
Jeff Brown25157e42012-04-16 12:13:05 -070090 }
Aravind Akella18ebf732b2015-04-20 17:39:51 -070091 mHasDataInjectionPermissions = context.checkSelfPermission(
92 Manifest.permission.HARDWARE_TEST) == PackageManager.PERMISSION_GRANTED;
Jeff Brown25157e42012-04-16 12:13:05 -070093 }
94 }
95
Mathias Agopiandb772d82013-01-31 19:31:12 -080096
Jeff Brown25157e42012-04-16 12:13:05 -070097 /** @hide */
98 @Override
99 protected List<Sensor> getFullSensorList() {
100 return sFullSensorsList;
101 }
102
Jeff Brown25157e42012-04-16 12:13:05 -0700103
104 /** @hide */
Jeff Brown4481d9c2012-04-16 16:14:44 -0700105 @Override
Jeff Brown25157e42012-04-16 12:13:05 -0700106 protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700107 int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {
108 if (listener == null || sensor == null) {
109 Log.e(TAG, "sensor or listener is null");
110 return false;
111 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700112 // Trigger Sensors should use the requestTriggerSensor call.
Aravind Akella27900352014-06-03 19:20:42 -0700113 if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700114 Log.e(TAG, "Trigger Sensors should use the requestTriggerSensor.");
115 return false;
116 }
117 if (maxBatchReportLatencyUs < 0 || delayUs < 0) {
118 Log.e(TAG, "maxBatchReportLatencyUs and delayUs should be non-negative");
119 return false;
120 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700121
Mathias Agopiandb772d82013-01-31 19:31:12 -0800122 // Invariants to preserve:
123 // - one Looper per SensorEventListener
124 // - one Looper per SensorEventQueue
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800125 // We map SensorEventListener to a SensorEventQueue, which holds the looper
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800126 synchronized (mSensorListeners) {
127 SensorEventQueue queue = mSensorListeners.get(listener);
128 if (queue == null) {
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700129 Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700130 queue = new SensorEventQueue(listener, looper, this);
Aravind Akella88445992015-02-26 17:05:28 -0800131 if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs)) {
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700132 queue.dispose();
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800133 return false;
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700134 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800135 mSensorListeners.put(listener, queue);
136 return true;
137 } else {
Aravind Akella88445992015-02-26 17:05:28 -0800138 return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs);
Jeff Brown25157e42012-04-16 12:13:05 -0700139 }
140 }
Jeff Brown25157e42012-04-16 12:13:05 -0700141 }
142
143 /** @hide */
144 @Override
145 protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800146 // Trigger Sensors should use the cancelTriggerSensor call.
Aravind Akella27900352014-06-03 19:20:42 -0700147 if (sensor != null && sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800148 return;
149 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800150
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800151 synchronized (mSensorListeners) {
152 SensorEventQueue queue = mSensorListeners.get(listener);
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700153 if (queue != null) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800154 boolean result;
155 if (sensor == null) {
156 result = queue.removeAllSensors();
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700157 } else {
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700158 result = queue.removeSensor(sensor, true);
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700159 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800160 if (result && !queue.hasSensors()) {
161 mSensorListeners.remove(listener);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800162 queue.dispose();
Jeff Brown25157e42012-04-16 12:13:05 -0700163 }
164 }
165 }
166 }
167
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800168 /** @hide */
169 @Override
170 protected boolean requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor) {
171 if (sensor == null) throw new IllegalArgumentException("sensor cannot be null");
Jeff Brown25157e42012-04-16 12:13:05 -0700172
Aravind Akella27900352014-06-03 19:20:42 -0700173 if (sensor.getReportingMode() != Sensor.REPORTING_MODE_ONE_SHOT) return false;
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800174
175 synchronized (mTriggerListeners) {
176 TriggerEventQueue queue = mTriggerListeners.get(listener);
177 if (queue == null) {
178 queue = new TriggerEventQueue(listener, mMainLooper, this);
Aravind Akella88445992015-02-26 17:05:28 -0800179 if (!queue.addSensor(sensor, 0, 0)) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800180 queue.dispose();
181 return false;
182 }
183 mTriggerListeners.put(listener, queue);
184 return true;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800185 } else {
Aravind Akella88445992015-02-26 17:05:28 -0800186 return queue.addSensor(sensor, 0, 0);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800187 }
188 }
189 }
Jeff Brown25157e42012-04-16 12:13:05 -0700190
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800191 /** @hide */
192 @Override
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700193 protected boolean cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor,
194 boolean disable) {
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 false;
197 }
198 synchronized (mTriggerListeners) {
199 TriggerEventQueue queue = mTriggerListeners.get(listener);
200 if (queue != null) {
201 boolean result;
202 if (sensor == null) {
203 result = queue.removeAllSensors();
204 } else {
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700205 result = queue.removeSensor(sensor, disable);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800206 }
207 if (result && !queue.hasSensors()) {
208 mTriggerListeners.remove(listener);
209 queue.dispose();
210 }
211 return result;
212 }
213 return false;
214 }
215 }
216
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700217 protected boolean flushImpl(SensorEventListener listener) {
218 if (listener == null) throw new IllegalArgumentException("listener cannot be null");
Aravind Akellab4c76b12013-06-27 12:04:16 -0700219
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700220 synchronized (mSensorListeners) {
221 SensorEventQueue queue = mSensorListeners.get(listener);
222 if (queue == null) {
223 return false;
224 } else {
225 return (queue.flush() == 0);
226 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700227 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700228 }
229
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700230 protected boolean enableDataInjectionImpl(boolean enable) {
231 if (!mHasDataInjectionPermissions) {
232 throw new SecurityException("Permission denial. Calling enableDataInjection without "
233 + Manifest.permission.HARDWARE_TEST);
234 }
235 synchronized (sSensorModuleLock) {
236 int ret = nativeEnableDataInjection(enable);
237 // The HAL does not support injection. Ignore.
238 if (ret != 0) {
239 Log.e(TAG, "HAL does not support data injection");
240 return false;
241 }
242 mDataInjectionMode = enable;
243 // If data injection is being disabled clean up the native resources.
244 if (!enable && mInjectEventQueue != null) {
245 mInjectEventQueue.dispose();
246 mInjectEventQueue = null;
247 }
248 return true;
249 }
250 }
251
252 protected boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy,
253 long timestamp) {
254 if (!mHasDataInjectionPermissions) {
255 throw new SecurityException("Permission denial. Calling injectSensorData without "
256 + Manifest.permission.HARDWARE_TEST);
257 }
258 synchronized (sSensorModuleLock) {
259 if (!mDataInjectionMode) {
260 Log.e(TAG, "Data injection mode not activated before calling injectSensorData");
261 return false;
262 }
263 if (mInjectEventQueue == null) {
264 mInjectEventQueue = new InjectEventQueue(mMainLooper, this);
265 }
266 int ret = mInjectEventQueue.injectSensorData(sensor.getHandle(), values, accuracy,
267 timestamp);
268 // If there are any errors in data injection clean up the native resources.
269 if (ret != 0) {
270 mInjectEventQueue.dispose();
271 mInjectEventQueue = null;
272 mDataInjectionMode = false;
273 }
274 return ret == 0;
275 }
276 }
277
Mathias Agopiandb772d82013-01-31 19:31:12 -0800278 /*
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800279 * BaseEventQueue is the communication channel with the sensor service,
280 * SensorEventQueue, TriggerEventQueue are subclases and there is one-to-one mapping between
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700281 * the queues and the listeners. InjectEventQueue is also a sub-class which is a special case
282 * where data is being injected into the sensor HAL through the sensor service. It is not
283 * associated with any listener and there is one InjectEventQueue associated with a
284 * SensorManager instance.
Mathias Agopiandb772d82013-01-31 19:31:12 -0800285 */
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800286 private static abstract class BaseEventQueue {
Jeff Brown3b4049e2015-04-17 15:22:27 -0700287 private native long nativeInitBaseEventQueue(WeakReference<BaseEventQueue> eventQWeak,
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700288 MessageQueue msgQ, float[] scratch, String packageName, int mode);
Ashok Bhat4838e332014-01-03 14:37:19 +0000289 private static native int nativeEnableSensor(long eventQ, int handle, int rateUs,
Aravind Akella88445992015-02-26 17:05:28 -0800290 int maxBatchReportLatencyUs);
Ashok Bhat4838e332014-01-03 14:37:19 +0000291 private static native int nativeDisableSensor(long eventQ, int handle);
292 private static native void nativeDestroySensorEventQueue(long eventQ);
293 private static native int nativeFlushSensor(long eventQ);
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700294 private static native int nativeInjectSensorData(long eventQ, int handle,
295 float[] values,int accuracy, long timestamp);
Ashok Bhat4838e332014-01-03 14:37:19 +0000296 private long nSensorEventQueue;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800297 private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800298 protected final SparseIntArray mSensorAccuracies = new SparseIntArray();
299 protected final SparseBooleanArray mFirstEvent = new SparseBooleanArray();
Mathias Agopiandb772d82013-01-31 19:31:12 -0800300 private final CloseGuard mCloseGuard = CloseGuard.get();
301 private final float[] mScratch = new float[16];
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700302 protected final SystemSensorManager mManager;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800303
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700304 protected static final int OPERATING_MODE_NORMAL = 0;
305 protected static final int OPERATING_MODE_DATA_INJECTION = 1;
306
307 BaseEventQueue(Looper looper, SystemSensorManager manager, int mode) {
Jeff Brown3b4049e2015-04-17 15:22:27 -0700308 nSensorEventQueue = nativeInitBaseEventQueue(new WeakReference<BaseEventQueue>(this),
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700309 looper.getQueue(), mScratch, manager.mPackageName, mode);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800310 mCloseGuard.open("dispose");
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700311 mManager = manager;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800312 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800313
Mathias Agopiandb772d82013-01-31 19:31:12 -0800314 public void dispose() {
315 dispose(false);
316 }
317
Aravind Akellab4c76b12013-06-27 12:04:16 -0700318 public boolean addSensor(
Aravind Akella88445992015-02-26 17:05:28 -0800319 Sensor sensor, int delayUs, int maxBatchReportLatencyUs) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800320 // Check if already present.
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700321 int handle = sensor.getHandle();
322 if (mActiveSensors.get(handle)) return false;
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800323
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700324 // Get ready to receive events before calling enable.
325 mActiveSensors.put(handle, true);
326 addSensorEvent(sensor);
Aravind Akella88445992015-02-26 17:05:28 -0800327 if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs) != 0) {
Aravind Akellab4c76b12013-06-27 12:04:16 -0700328 // Try continuous mode if batching fails.
329 if (maxBatchReportLatencyUs == 0 ||
Aravind Akella88445992015-02-26 17:05:28 -0800330 maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0) != 0) {
Aravind Akellab4c76b12013-06-27 12:04:16 -0700331 removeSensor(sensor, false);
332 return false;
333 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800334 }
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700335 return true;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800336 }
337
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800338 public boolean removeAllSensors() {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800339 for (int i=0 ; i<mActiveSensors.size(); i++) {
340 if (mActiveSensors.valueAt(i) == true) {
341 int handle = mActiveSensors.keyAt(i);
342 Sensor sensor = sHandleToSensor.get(handle);
343 if (sensor != null) {
344 disableSensor(sensor);
345 mActiveSensors.put(handle, false);
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700346 removeSensorEvent(sensor);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800347 } else {
348 // it should never happen -- just ignore.
349 }
350 }
351 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800352 return true;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800353 }
354
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700355 public boolean removeSensor(Sensor sensor, boolean disable) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800356 final int handle = sensor.getHandle();
357 if (mActiveSensors.get(handle)) {
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700358 if (disable) disableSensor(sensor);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800359 mActiveSensors.put(sensor.getHandle(), false);
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700360 removeSensorEvent(sensor);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800361 return true;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800362 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800363 return false;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800364 }
365
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700366 public int flush() {
Aravind Akellab4c76b12013-06-27 12:04:16 -0700367 if (nSensorEventQueue == 0) throw new NullPointerException();
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700368 return nativeFlushSensor(nSensorEventQueue);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700369 }
370
Mathias Agopiandb772d82013-01-31 19:31:12 -0800371 public boolean hasSensors() {
372 // no more sensors are set
373 return mActiveSensors.indexOfValue(true) >= 0;
374 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800375
Mathias Agopiandb772d82013-01-31 19:31:12 -0800376 @Override
377 protected void finalize() throws Throwable {
378 try {
379 dispose(true);
380 } finally {
381 super.finalize();
382 }
383 }
384
385 private void dispose(boolean finalized) {
386 if (mCloseGuard != null) {
387 if (finalized) {
388 mCloseGuard.warnIfOpen();
389 }
390 mCloseGuard.close();
391 }
392 if (nSensorEventQueue != 0) {
393 nativeDestroySensorEventQueue(nSensorEventQueue);
394 nSensorEventQueue = 0;
395 }
396 }
397
Aravind Akellab4c76b12013-06-27 12:04:16 -0700398 private int enableSensor(
Aravind Akella88445992015-02-26 17:05:28 -0800399 Sensor sensor, int rateUs, int maxBatchReportLatencyUs) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800400 if (nSensorEventQueue == 0) throw new NullPointerException();
401 if (sensor == null) throw new NullPointerException();
Aravind Akellab4c76b12013-06-27 12:04:16 -0700402 return nativeEnableSensor(nSensorEventQueue, sensor.getHandle(), rateUs,
Aravind Akella88445992015-02-26 17:05:28 -0800403 maxBatchReportLatencyUs);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800404 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700405
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700406 protected int injectSensorDataBase(int handle, float[] values, int accuracy,
407 long timestamp) {
408 return nativeInjectSensorData(nSensorEventQueue, handle, values, accuracy, timestamp);
409 }
410
Mathias Agopiandb772d82013-01-31 19:31:12 -0800411 private int disableSensor(Sensor sensor) {
412 if (nSensorEventQueue == 0) throw new NullPointerException();
413 if (sensor == null) throw new NullPointerException();
414 return nativeDisableSensor(nSensorEventQueue, sensor.getHandle());
415 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800416 protected abstract void dispatchSensorEvent(int handle, float[] values, int accuracy,
417 long timestamp);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700418 protected abstract void dispatchFlushCompleteEvent(int handle);
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700419
420 protected abstract void addSensorEvent(Sensor sensor);
421 protected abstract void removeSensorEvent(Sensor sensor);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800422 }
423
424 static final class SensorEventQueue extends BaseEventQueue {
425 private final SensorEventListener mListener;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700426 private final SparseArray<SensorEvent> mSensorsEvents = new SparseArray<SensorEvent>();
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800427
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700428 public SensorEventQueue(SensorEventListener listener, Looper looper,
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700429 SystemSensorManager manager) {
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700430 super(looper, manager, OPERATING_MODE_NORMAL);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800431 mListener = listener;
432 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800433
Aravind Akella31d14ce2013-10-22 20:04:22 -0700434 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700435 public void addSensorEvent(Sensor sensor) {
436 SensorEvent t = new SensorEvent(Sensor.getMaxLengthValuesArray(sensor,
437 mManager.mTargetSdkLevel));
Aravind Akella31d14ce2013-10-22 20:04:22 -0700438 synchronized (mSensorsEvents) {
439 mSensorsEvents.put(sensor.getHandle(), t);
440 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700441 }
442
Aravind Akella31d14ce2013-10-22 20:04:22 -0700443 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700444 public void removeSensorEvent(Sensor sensor) {
Aravind Akella31d14ce2013-10-22 20:04:22 -0700445 synchronized (mSensorsEvents) {
446 mSensorsEvents.delete(sensor.getHandle());
447 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700448 }
449
Mathias Agopiandb772d82013-01-31 19:31:12 -0800450 // Called from native code.
451 @SuppressWarnings("unused")
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800452 @Override
453 protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,
454 long timestamp) {
455 final Sensor sensor = sHandleToSensor.get(handle);
Aravind Akella31d14ce2013-10-22 20:04:22 -0700456 SensorEvent t = null;
457 synchronized (mSensorsEvents) {
458 t = mSensorsEvents.get(handle);
459 }
460
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700461 if (t == null) {
Aravind Akella31d14ce2013-10-22 20:04:22 -0700462 // This may happen if the client has unregistered and there are pending events in
463 // the queue waiting to be delivered. Ignore.
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700464 return;
465 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700466 // Copy from the values array.
467 System.arraycopy(values, 0, t.values, 0, t.values.length);
468 t.timestamp = timestamp;
469 t.accuracy = inAccuracy;
470 t.sensor = sensor;
Etienne Le Grandaf805102014-05-16 12:21:41 -0700471
472 // call onAccuracyChanged() only if the value changes
473 final int accuracy = mSensorAccuracies.get(handle);
474 if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
475 mSensorAccuracies.put(handle, t.accuracy);
476 mListener.onAccuracyChanged(t.sensor, t.accuracy);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800477 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700478 mListener.onSensorChanged(t);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800479 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700480
481 @SuppressWarnings("unused")
482 protected void dispatchFlushCompleteEvent(int handle) {
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700483 if (mListener instanceof SensorEventListener2) {
484 final Sensor sensor = sHandleToSensor.get(handle);
485 ((SensorEventListener2)mListener).onFlushCompleted(sensor);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700486 }
487 return;
488 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800489 }
490
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800491 static final class TriggerEventQueue extends BaseEventQueue {
492 private final TriggerEventListener mListener;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700493 private final SparseArray<TriggerEvent> mTriggerEvents = new SparseArray<TriggerEvent>();
Mathias Agopiandb772d82013-01-31 19:31:12 -0800494
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800495 public TriggerEventQueue(TriggerEventListener listener, Looper looper,
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700496 SystemSensorManager manager) {
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700497 super(looper, manager, OPERATING_MODE_NORMAL);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800498 mListener = listener;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700499 }
500
Aravind Akella31d14ce2013-10-22 20:04:22 -0700501 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700502 public void addSensorEvent(Sensor sensor) {
503 TriggerEvent t = new TriggerEvent(Sensor.getMaxLengthValuesArray(sensor,
504 mManager.mTargetSdkLevel));
Aravind Akella31d14ce2013-10-22 20:04:22 -0700505 synchronized (mTriggerEvents) {
506 mTriggerEvents.put(sensor.getHandle(), t);
507 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700508 }
509
Aravind Akella31d14ce2013-10-22 20:04:22 -0700510 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700511 public void removeSensorEvent(Sensor sensor) {
Aravind Akella31d14ce2013-10-22 20:04:22 -0700512 synchronized (mTriggerEvents) {
513 mTriggerEvents.delete(sensor.getHandle());
514 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800515 }
516
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800517 // Called from native code.
518 @SuppressWarnings("unused")
519 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700520 protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
521 long timestamp) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800522 final Sensor sensor = sHandleToSensor.get(handle);
Aravind Akella31d14ce2013-10-22 20:04:22 -0700523 TriggerEvent t = null;
524 synchronized (mTriggerEvents) {
525 t = mTriggerEvents.get(handle);
526 }
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700527 if (t == null) {
528 Log.e(TAG, "Error: Trigger Event is null for Sensor: " + sensor);
529 return;
530 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800531
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700532 // Copy from the values array.
533 System.arraycopy(values, 0, t.values, 0, t.values.length);
534 t.timestamp = timestamp;
535 t.sensor = sensor;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800536
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700537 // A trigger sensor is auto disabled. So just clean up and don't call native
538 // disable.
539 mManager.cancelTriggerSensorImpl(mListener, sensor, false);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800540
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700541 mListener.onTrigger(t);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800542 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700543
544 @SuppressWarnings("unused")
545 protected void dispatchFlushCompleteEvent(int handle) {
546 }
547 }
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700548
549 static final class InjectEventQueue extends BaseEventQueue {
550 public InjectEventQueue(Looper looper, SystemSensorManager manager) {
551 super(looper, manager, OPERATING_MODE_DATA_INJECTION);
552 }
553
554 int injectSensorData(int handle, float[] values,int accuracy, long timestamp) {
555 return injectSensorDataBase(handle, values, accuracy, timestamp);
556 }
557
558 @SuppressWarnings("unused")
559 protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
560 long timestamp) {
561 }
562
563 @SuppressWarnings("unused")
564 protected void dispatchFlushCompleteEvent(int handle) {
565
566 }
567
568 @SuppressWarnings("unused")
569 protected void addSensorEvent(Sensor sensor) {
570
571 }
572
573 @SuppressWarnings("unused")
574 protected void removeSensorEvent(Sensor sensor) {
575
576 }
577 }
Jeff Brown25157e42012-04-16 12:13:05 -0700578}