blob: 22a9e9c8a1c8a03ba677a2e3f17db59b3b65910b [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();
Svet Ganovb9d71a62015-04-30 10:38:13 -070044 private static native long nativeCreate(String opPackageName);
45 private static native int nativeGetNextSensor(long nativeInstance, Sensor sensor, int next);
46 private static native int nativeEnableDataInjection(long nativeInstance, boolean enable);
Jeff Brown25157e42012-04-16 12:13:05 -070047
Mathias Agopiandb772d82013-01-31 19:31:12 -080048 private static boolean sSensorModuleInitialized = false;
Aravind Akella18ebf732b2015-04-20 17:39:51 -070049 private static InjectEventQueue mInjectEventQueue = null;
50 private static boolean mDataInjectionMode = false;
Mathias Agopiandb772d82013-01-31 19:31:12 -080051
Svet Ganovb9d71a62015-04-30 10:38:13 -070052 private final Object mLock = new Object();
53
54 private final ArrayList<Sensor> mFullSensorsList = new ArrayList<>();
55 private final SparseArray<Sensor> mHandleToSensor = new SparseArray<>();
56
Mathias Agopiandb772d82013-01-31 19:31:12 -080057 // Listener list
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -080058 private final HashMap<SensorEventListener, SensorEventQueue> mSensorListeners =
59 new HashMap<SensorEventListener, SensorEventQueue>();
60 private final HashMap<TriggerEventListener, TriggerEventQueue> mTriggerListeners =
61 new HashMap<TriggerEventListener, TriggerEventQueue>();
Jeff Brown25157e42012-04-16 12:13:05 -070062
Jeff Brown4481d9c2012-04-16 16:14:44 -070063 // Looper associated with the context in which this instance was created.
Mathias Agopiandb772d82013-01-31 19:31:12 -080064 private final Looper mMainLooper;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -070065 private final int mTargetSdkLevel;
Svet Ganovb9d71a62015-04-30 10:38:13 -070066 private final Context mContext;
Aravind Akella18ebf732b2015-04-20 17:39:51 -070067 private final boolean mHasDataInjectionPermissions;
Svet Ganovb9d71a62015-04-30 10:38:13 -070068 private final long mNativeInstance;
Jeff Brown25157e42012-04-16 12:13:05 -070069
Mathias Agopiandb772d82013-01-31 19:31:12 -080070 /** {@hide} */
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -070071 public SystemSensorManager(Context context, Looper mainLooper) {
Jeff Brown25157e42012-04-16 12:13:05 -070072 mMainLooper = mainLooper;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -070073 mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
Svet Ganovb9d71a62015-04-30 10:38:13 -070074 mContext = context;
75 mNativeInstance = nativeCreate(context.getOpPackageName());
76
77 synchronized(mLock) {
Jeff Brown25157e42012-04-16 12:13:05 -070078 if (!sSensorModuleInitialized) {
79 sSensorModuleInitialized = true;
Jeff Brown25157e42012-04-16 12:13:05 -070080 nativeClassInit();
Jeff Brown25157e42012-04-16 12:13:05 -070081 }
Aravind Akella18ebf732b2015-04-20 17:39:51 -070082 mHasDataInjectionPermissions = context.checkSelfPermission(
83 Manifest.permission.HARDWARE_TEST) == PackageManager.PERMISSION_GRANTED;
Jeff Brown25157e42012-04-16 12:13:05 -070084 }
Svet Ganovb9d71a62015-04-30 10:38:13 -070085
86 // initialize the sensor list
87 int i = 0;
88 while(true) {
89 Sensor sensor = new Sensor();
90 i = nativeGetNextSensor(mNativeInstance, sensor, i);
91 if (i <= 0) {
92 break;
93 }
94 mFullSensorsList.add(sensor);
95 mHandleToSensor.append(sensor.getHandle(), sensor);
96 }
Jeff Brown25157e42012-04-16 12:13:05 -070097 }
98
Mathias Agopiandb772d82013-01-31 19:31:12 -080099
Jeff Brown25157e42012-04-16 12:13:05 -0700100 /** @hide */
101 @Override
102 protected List<Sensor> getFullSensorList() {
Svet Ganovb9d71a62015-04-30 10:38:13 -0700103 return mFullSensorsList;
Jeff Brown25157e42012-04-16 12:13:05 -0700104 }
105
Jeff Brown25157e42012-04-16 12:13:05 -0700106
107 /** @hide */
Jeff Brown4481d9c2012-04-16 16:14:44 -0700108 @Override
Jeff Brown25157e42012-04-16 12:13:05 -0700109 protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700110 int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {
111 if (listener == null || sensor == null) {
112 Log.e(TAG, "sensor or listener is null");
113 return false;
114 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700115 // Trigger Sensors should use the requestTriggerSensor call.
Aravind Akella27900352014-06-03 19:20:42 -0700116 if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700117 Log.e(TAG, "Trigger Sensors should use the requestTriggerSensor.");
118 return false;
119 }
120 if (maxBatchReportLatencyUs < 0 || delayUs < 0) {
121 Log.e(TAG, "maxBatchReportLatencyUs and delayUs should be non-negative");
122 return false;
123 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700124
Mathias Agopiandb772d82013-01-31 19:31:12 -0800125 // Invariants to preserve:
126 // - one Looper per SensorEventListener
127 // - one Looper per SensorEventQueue
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800128 // We map SensorEventListener to a SensorEventQueue, which holds the looper
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800129 synchronized (mSensorListeners) {
130 SensorEventQueue queue = mSensorListeners.get(listener);
131 if (queue == null) {
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700132 Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700133 queue = new SensorEventQueue(listener, looper, this);
Aravind Akella88445992015-02-26 17:05:28 -0800134 if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs)) {
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700135 queue.dispose();
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800136 return false;
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700137 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800138 mSensorListeners.put(listener, queue);
139 return true;
140 } else {
Aravind Akella88445992015-02-26 17:05:28 -0800141 return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs);
Jeff Brown25157e42012-04-16 12:13:05 -0700142 }
143 }
Jeff Brown25157e42012-04-16 12:13:05 -0700144 }
145
146 /** @hide */
147 @Override
148 protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800149 // Trigger Sensors should use the cancelTriggerSensor call.
Aravind Akella27900352014-06-03 19:20:42 -0700150 if (sensor != null && sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800151 return;
152 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800153
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800154 synchronized (mSensorListeners) {
155 SensorEventQueue queue = mSensorListeners.get(listener);
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700156 if (queue != null) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800157 boolean result;
158 if (sensor == null) {
159 result = queue.removeAllSensors();
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700160 } else {
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700161 result = queue.removeSensor(sensor, true);
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700162 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800163 if (result && !queue.hasSensors()) {
164 mSensorListeners.remove(listener);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800165 queue.dispose();
Jeff Brown25157e42012-04-16 12:13:05 -0700166 }
167 }
168 }
169 }
170
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800171 /** @hide */
172 @Override
173 protected boolean requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor) {
174 if (sensor == null) throw new IllegalArgumentException("sensor cannot be null");
Jeff Brown25157e42012-04-16 12:13:05 -0700175
Aravind Akella27900352014-06-03 19:20:42 -0700176 if (sensor.getReportingMode() != Sensor.REPORTING_MODE_ONE_SHOT) return false;
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800177
178 synchronized (mTriggerListeners) {
179 TriggerEventQueue queue = mTriggerListeners.get(listener);
180 if (queue == null) {
181 queue = new TriggerEventQueue(listener, mMainLooper, this);
Aravind Akella88445992015-02-26 17:05:28 -0800182 if (!queue.addSensor(sensor, 0, 0)) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800183 queue.dispose();
184 return false;
185 }
186 mTriggerListeners.put(listener, queue);
187 return true;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800188 } else {
Aravind Akella88445992015-02-26 17:05:28 -0800189 return queue.addSensor(sensor, 0, 0);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800190 }
191 }
192 }
Jeff Brown25157e42012-04-16 12:13:05 -0700193
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800194 /** @hide */
195 @Override
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700196 protected boolean cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor,
197 boolean disable) {
Aravind Akella27900352014-06-03 19:20:42 -0700198 if (sensor != null && sensor.getReportingMode() != Sensor.REPORTING_MODE_ONE_SHOT) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800199 return false;
200 }
201 synchronized (mTriggerListeners) {
202 TriggerEventQueue queue = mTriggerListeners.get(listener);
203 if (queue != null) {
204 boolean result;
205 if (sensor == null) {
206 result = queue.removeAllSensors();
207 } else {
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700208 result = queue.removeSensor(sensor, disable);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800209 }
210 if (result && !queue.hasSensors()) {
211 mTriggerListeners.remove(listener);
212 queue.dispose();
213 }
214 return result;
215 }
216 return false;
217 }
218 }
219
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700220 protected boolean flushImpl(SensorEventListener listener) {
221 if (listener == null) throw new IllegalArgumentException("listener cannot be null");
Aravind Akellab4c76b12013-06-27 12:04:16 -0700222
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700223 synchronized (mSensorListeners) {
224 SensorEventQueue queue = mSensorListeners.get(listener);
225 if (queue == null) {
226 return false;
227 } else {
228 return (queue.flush() == 0);
229 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700230 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700231 }
232
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700233 protected boolean enableDataInjectionImpl(boolean enable) {
234 if (!mHasDataInjectionPermissions) {
235 throw new SecurityException("Permission denial. Calling enableDataInjection without "
236 + Manifest.permission.HARDWARE_TEST);
237 }
Svet Ganovb9d71a62015-04-30 10:38:13 -0700238 synchronized (mLock) {
239 int ret = nativeEnableDataInjection(mNativeInstance, enable);
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700240 // The HAL does not support injection. Ignore.
241 if (ret != 0) {
242 Log.e(TAG, "HAL does not support data injection");
243 return false;
244 }
245 mDataInjectionMode = enable;
246 // If data injection is being disabled clean up the native resources.
247 if (!enable && mInjectEventQueue != null) {
248 mInjectEventQueue.dispose();
249 mInjectEventQueue = null;
250 }
251 return true;
252 }
253 }
254
255 protected boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy,
256 long timestamp) {
257 if (!mHasDataInjectionPermissions) {
258 throw new SecurityException("Permission denial. Calling injectSensorData without "
259 + Manifest.permission.HARDWARE_TEST);
260 }
Svet Ganovb9d71a62015-04-30 10:38:13 -0700261 synchronized (mLock) {
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700262 if (!mDataInjectionMode) {
263 Log.e(TAG, "Data injection mode not activated before calling injectSensorData");
264 return false;
265 }
266 if (mInjectEventQueue == null) {
267 mInjectEventQueue = new InjectEventQueue(mMainLooper, this);
268 }
269 int ret = mInjectEventQueue.injectSensorData(sensor.getHandle(), values, accuracy,
270 timestamp);
271 // If there are any errors in data injection clean up the native resources.
272 if (ret != 0) {
273 mInjectEventQueue.dispose();
274 mInjectEventQueue = null;
275 mDataInjectionMode = false;
276 }
277 return ret == 0;
278 }
279 }
280
Mathias Agopiandb772d82013-01-31 19:31:12 -0800281 /*
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800282 * BaseEventQueue is the communication channel with the sensor service,
283 * SensorEventQueue, TriggerEventQueue are subclases and there is one-to-one mapping between
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700284 * the queues and the listeners. InjectEventQueue is also a sub-class which is a special case
285 * where data is being injected into the sensor HAL through the sensor service. It is not
286 * associated with any listener and there is one InjectEventQueue associated with a
287 * SensorManager instance.
Mathias Agopiandb772d82013-01-31 19:31:12 -0800288 */
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800289 private static abstract class BaseEventQueue {
Svet Ganovb9d71a62015-04-30 10:38:13 -0700290 private static native long nativeInitBaseEventQueue(long nativeManager,
291 WeakReference<BaseEventQueue> eventQWeak, MessageQueue msgQ, float[] scratch,
292 String packageName, int mode, String opPackageName);
Ashok Bhat4838e332014-01-03 14:37:19 +0000293 private static native int nativeEnableSensor(long eventQ, int handle, int rateUs,
Aravind Akella88445992015-02-26 17:05:28 -0800294 int maxBatchReportLatencyUs);
Ashok Bhat4838e332014-01-03 14:37:19 +0000295 private static native int nativeDisableSensor(long eventQ, int handle);
296 private static native void nativeDestroySensorEventQueue(long eventQ);
297 private static native int nativeFlushSensor(long eventQ);
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700298 private static native int nativeInjectSensorData(long eventQ, int handle,
Svet Ganovb9d71a62015-04-30 10:38:13 -0700299 float[] values,int accuracy, long timestamp);
300
Ashok Bhat4838e332014-01-03 14:37:19 +0000301 private long nSensorEventQueue;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800302 private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800303 protected final SparseIntArray mSensorAccuracies = new SparseIntArray();
304 protected final SparseBooleanArray mFirstEvent = new SparseBooleanArray();
Mathias Agopiandb772d82013-01-31 19:31:12 -0800305 private final CloseGuard mCloseGuard = CloseGuard.get();
306 private final float[] mScratch = new float[16];
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700307 protected final SystemSensorManager mManager;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800308
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700309 protected static final int OPERATING_MODE_NORMAL = 0;
310 protected static final int OPERATING_MODE_DATA_INJECTION = 1;
311
312 BaseEventQueue(Looper looper, SystemSensorManager manager, int mode) {
Svet Ganovb9d71a62015-04-30 10:38:13 -0700313 nSensorEventQueue = nativeInitBaseEventQueue(manager.mNativeInstance,
314 new WeakReference<>(this), looper.getQueue(), mScratch,
315 manager.mContext.getPackageName(), mode, manager.mContext.getOpPackageName());
Mathias Agopiandb772d82013-01-31 19:31:12 -0800316 mCloseGuard.open("dispose");
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700317 mManager = manager;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800318 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800319
Mathias Agopiandb772d82013-01-31 19:31:12 -0800320 public void dispose() {
321 dispose(false);
322 }
323
Aravind Akellab4c76b12013-06-27 12:04:16 -0700324 public boolean addSensor(
Aravind Akella88445992015-02-26 17:05:28 -0800325 Sensor sensor, int delayUs, int maxBatchReportLatencyUs) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800326 // Check if already present.
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700327 int handle = sensor.getHandle();
328 if (mActiveSensors.get(handle)) return false;
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800329
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700330 // Get ready to receive events before calling enable.
331 mActiveSensors.put(handle, true);
332 addSensorEvent(sensor);
Aravind Akella88445992015-02-26 17:05:28 -0800333 if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs) != 0) {
Aravind Akellab4c76b12013-06-27 12:04:16 -0700334 // Try continuous mode if batching fails.
335 if (maxBatchReportLatencyUs == 0 ||
Aravind Akella88445992015-02-26 17:05:28 -0800336 maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0) != 0) {
Aravind Akellab4c76b12013-06-27 12:04:16 -0700337 removeSensor(sensor, false);
338 return false;
339 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800340 }
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700341 return true;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800342 }
343
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800344 public boolean removeAllSensors() {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800345 for (int i=0 ; i<mActiveSensors.size(); i++) {
346 if (mActiveSensors.valueAt(i) == true) {
347 int handle = mActiveSensors.keyAt(i);
Svet Ganovb9d71a62015-04-30 10:38:13 -0700348 Sensor sensor = mManager.mHandleToSensor.get(handle);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800349 if (sensor != null) {
350 disableSensor(sensor);
351 mActiveSensors.put(handle, false);
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700352 removeSensorEvent(sensor);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800353 } else {
354 // it should never happen -- just ignore.
355 }
356 }
357 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800358 return true;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800359 }
360
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700361 public boolean removeSensor(Sensor sensor, boolean disable) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800362 final int handle = sensor.getHandle();
363 if (mActiveSensors.get(handle)) {
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700364 if (disable) disableSensor(sensor);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800365 mActiveSensors.put(sensor.getHandle(), false);
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700366 removeSensorEvent(sensor);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800367 return true;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800368 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800369 return false;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800370 }
371
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700372 public int flush() {
Aravind Akellab4c76b12013-06-27 12:04:16 -0700373 if (nSensorEventQueue == 0) throw new NullPointerException();
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700374 return nativeFlushSensor(nSensorEventQueue);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700375 }
376
Mathias Agopiandb772d82013-01-31 19:31:12 -0800377 public boolean hasSensors() {
378 // no more sensors are set
379 return mActiveSensors.indexOfValue(true) >= 0;
380 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800381
Mathias Agopiandb772d82013-01-31 19:31:12 -0800382 @Override
383 protected void finalize() throws Throwable {
384 try {
385 dispose(true);
386 } finally {
387 super.finalize();
388 }
389 }
390
391 private void dispose(boolean finalized) {
392 if (mCloseGuard != null) {
393 if (finalized) {
394 mCloseGuard.warnIfOpen();
395 }
396 mCloseGuard.close();
397 }
398 if (nSensorEventQueue != 0) {
399 nativeDestroySensorEventQueue(nSensorEventQueue);
400 nSensorEventQueue = 0;
401 }
402 }
403
Aravind Akellab4c76b12013-06-27 12:04:16 -0700404 private int enableSensor(
Aravind Akella88445992015-02-26 17:05:28 -0800405 Sensor sensor, int rateUs, int maxBatchReportLatencyUs) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800406 if (nSensorEventQueue == 0) throw new NullPointerException();
407 if (sensor == null) throw new NullPointerException();
Aravind Akellab4c76b12013-06-27 12:04:16 -0700408 return nativeEnableSensor(nSensorEventQueue, sensor.getHandle(), rateUs,
Aravind Akella88445992015-02-26 17:05:28 -0800409 maxBatchReportLatencyUs);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800410 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700411
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700412 protected int injectSensorDataBase(int handle, float[] values, int accuracy,
413 long timestamp) {
414 return nativeInjectSensorData(nSensorEventQueue, handle, values, accuracy, timestamp);
415 }
416
Mathias Agopiandb772d82013-01-31 19:31:12 -0800417 private int disableSensor(Sensor sensor) {
418 if (nSensorEventQueue == 0) throw new NullPointerException();
419 if (sensor == null) throw new NullPointerException();
420 return nativeDisableSensor(nSensorEventQueue, sensor.getHandle());
421 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800422 protected abstract void dispatchSensorEvent(int handle, float[] values, int accuracy,
423 long timestamp);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700424 protected abstract void dispatchFlushCompleteEvent(int handle);
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700425
426 protected abstract void addSensorEvent(Sensor sensor);
427 protected abstract void removeSensorEvent(Sensor sensor);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800428 }
429
430 static final class SensorEventQueue extends BaseEventQueue {
431 private final SensorEventListener mListener;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700432 private final SparseArray<SensorEvent> mSensorsEvents = new SparseArray<SensorEvent>();
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800433
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700434 public SensorEventQueue(SensorEventListener listener, Looper looper,
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700435 SystemSensorManager manager) {
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700436 super(looper, manager, OPERATING_MODE_NORMAL);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800437 mListener = listener;
438 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800439
Aravind Akella31d14ce2013-10-22 20:04:22 -0700440 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700441 public void addSensorEvent(Sensor sensor) {
442 SensorEvent t = new SensorEvent(Sensor.getMaxLengthValuesArray(sensor,
443 mManager.mTargetSdkLevel));
Aravind Akella31d14ce2013-10-22 20:04:22 -0700444 synchronized (mSensorsEvents) {
445 mSensorsEvents.put(sensor.getHandle(), t);
446 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700447 }
448
Aravind Akella31d14ce2013-10-22 20:04:22 -0700449 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700450 public void removeSensorEvent(Sensor sensor) {
Aravind Akella31d14ce2013-10-22 20:04:22 -0700451 synchronized (mSensorsEvents) {
452 mSensorsEvents.delete(sensor.getHandle());
453 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700454 }
455
Mathias Agopiandb772d82013-01-31 19:31:12 -0800456 // Called from native code.
457 @SuppressWarnings("unused")
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800458 @Override
459 protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,
460 long timestamp) {
Svet Ganovb9d71a62015-04-30 10:38:13 -0700461 final Sensor sensor = mManager.mHandleToSensor.get(handle);
Aravind Akella31d14ce2013-10-22 20:04:22 -0700462 SensorEvent t = null;
463 synchronized (mSensorsEvents) {
464 t = mSensorsEvents.get(handle);
465 }
466
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700467 if (t == null) {
Aravind Akella31d14ce2013-10-22 20:04:22 -0700468 // This may happen if the client has unregistered and there are pending events in
469 // the queue waiting to be delivered. Ignore.
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700470 return;
471 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700472 // Copy from the values array.
473 System.arraycopy(values, 0, t.values, 0, t.values.length);
474 t.timestamp = timestamp;
475 t.accuracy = inAccuracy;
476 t.sensor = sensor;
Etienne Le Grandaf805102014-05-16 12:21:41 -0700477
478 // call onAccuracyChanged() only if the value changes
479 final int accuracy = mSensorAccuracies.get(handle);
480 if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
481 mSensorAccuracies.put(handle, t.accuracy);
482 mListener.onAccuracyChanged(t.sensor, t.accuracy);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800483 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700484 mListener.onSensorChanged(t);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800485 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700486
487 @SuppressWarnings("unused")
488 protected void dispatchFlushCompleteEvent(int handle) {
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700489 if (mListener instanceof SensorEventListener2) {
Svet Ganovb9d71a62015-04-30 10:38:13 -0700490 final Sensor sensor = mManager.mHandleToSensor.get(handle);
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700491 ((SensorEventListener2)mListener).onFlushCompleted(sensor);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700492 }
493 return;
494 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800495 }
496
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800497 static final class TriggerEventQueue extends BaseEventQueue {
498 private final TriggerEventListener mListener;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700499 private final SparseArray<TriggerEvent> mTriggerEvents = new SparseArray<TriggerEvent>();
Mathias Agopiandb772d82013-01-31 19:31:12 -0800500
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800501 public TriggerEventQueue(TriggerEventListener listener, Looper looper,
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700502 SystemSensorManager manager) {
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700503 super(looper, manager, OPERATING_MODE_NORMAL);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800504 mListener = listener;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700505 }
506
Aravind Akella31d14ce2013-10-22 20:04:22 -0700507 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700508 public void addSensorEvent(Sensor sensor) {
509 TriggerEvent t = new TriggerEvent(Sensor.getMaxLengthValuesArray(sensor,
510 mManager.mTargetSdkLevel));
Aravind Akella31d14ce2013-10-22 20:04:22 -0700511 synchronized (mTriggerEvents) {
512 mTriggerEvents.put(sensor.getHandle(), t);
513 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700514 }
515
Aravind Akella31d14ce2013-10-22 20:04:22 -0700516 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700517 public void removeSensorEvent(Sensor sensor) {
Aravind Akella31d14ce2013-10-22 20:04:22 -0700518 synchronized (mTriggerEvents) {
519 mTriggerEvents.delete(sensor.getHandle());
520 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800521 }
522
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800523 // Called from native code.
524 @SuppressWarnings("unused")
525 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700526 protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
527 long timestamp) {
Svet Ganovb9d71a62015-04-30 10:38:13 -0700528 final Sensor sensor = mManager.mHandleToSensor.get(handle);
Aravind Akella31d14ce2013-10-22 20:04:22 -0700529 TriggerEvent t = null;
530 synchronized (mTriggerEvents) {
531 t = mTriggerEvents.get(handle);
532 }
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700533 if (t == null) {
534 Log.e(TAG, "Error: Trigger Event is null for Sensor: " + sensor);
535 return;
536 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800537
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700538 // Copy from the values array.
539 System.arraycopy(values, 0, t.values, 0, t.values.length);
540 t.timestamp = timestamp;
541 t.sensor = sensor;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800542
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700543 // A trigger sensor is auto disabled. So just clean up and don't call native
544 // disable.
545 mManager.cancelTriggerSensorImpl(mListener, sensor, false);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800546
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700547 mListener.onTrigger(t);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800548 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700549
550 @SuppressWarnings("unused")
551 protected void dispatchFlushCompleteEvent(int handle) {
552 }
553 }
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700554
Svet Ganovb9d71a62015-04-30 10:38:13 -0700555 final class InjectEventQueue extends BaseEventQueue {
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700556 public InjectEventQueue(Looper looper, SystemSensorManager manager) {
557 super(looper, manager, OPERATING_MODE_DATA_INJECTION);
558 }
559
560 int injectSensorData(int handle, float[] values,int accuracy, long timestamp) {
561 return injectSensorDataBase(handle, values, accuracy, timestamp);
562 }
563
564 @SuppressWarnings("unused")
565 protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
566 long timestamp) {
567 }
568
569 @SuppressWarnings("unused")
570 protected void dispatchFlushCompleteEvent(int handle) {
571
572 }
573
574 @SuppressWarnings("unused")
575 protected void addSensorEvent(Sensor sensor) {
576
577 }
578
579 @SuppressWarnings("unused")
580 protected void removeSensorEvent(Sensor sensor) {
581
582 }
583 }
Jeff Brown25157e42012-04-16 12:13:05 -0700584}