blob: 7ad3a683cd6f690cf7fd5922544459df47cfb664 [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
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -070019import android.content.Context;
Jeff Brown25157e42012-04-16 12:13:05 -070020import android.os.Handler;
Mathias Agopiandb772d82013-01-31 19:31:12 -080021import android.os.Looper;
22import android.os.MessageQueue;
Jaikumar Ganesh2e900892013-04-11 10:40:33 -070023import android.util.Log;
Jeff Brown25157e42012-04-16 12:13:05 -070024import android.util.SparseArray;
25import android.util.SparseBooleanArray;
26import android.util.SparseIntArray;
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -080027import dalvik.system.CloseGuard;
28
Jeff Brown3b4049e2015-04-17 15:22:27 -070029import java.lang.ref.WeakReference;
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -080030import java.util.ArrayList;
31import java.util.HashMap;
32import java.util.List;
Jeff Brown25157e42012-04-16 12:13:05 -070033
Jeff Brown25157e42012-04-16 12:13:05 -070034/**
35 * Sensor manager implementation that communicates with the built-in
36 * system sensors.
37 *
38 * @hide
39 */
40public class SystemSensorManager extends SensorManager {
Mathias Agopiandb772d82013-01-31 19:31:12 -080041 private static native void nativeClassInit();
42 private static native int nativeGetNextSensor(Sensor sensor, int next);
Jeff Brown25157e42012-04-16 12:13:05 -070043
Mathias Agopiandb772d82013-01-31 19:31:12 -080044 private static boolean sSensorModuleInitialized = false;
45 private static final Object sSensorModuleLock = new Object();
46 private static final ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>();
47 private static final SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
48
49 // Listener list
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -080050 private final HashMap<SensorEventListener, SensorEventQueue> mSensorListeners =
51 new HashMap<SensorEventListener, SensorEventQueue>();
52 private final HashMap<TriggerEventListener, TriggerEventQueue> mTriggerListeners =
53 new HashMap<TriggerEventListener, TriggerEventQueue>();
Jeff Brown25157e42012-04-16 12:13:05 -070054
Jeff Brown4481d9c2012-04-16 16:14:44 -070055 // Looper associated with the context in which this instance was created.
Mathias Agopiandb772d82013-01-31 19:31:12 -080056 private final Looper mMainLooper;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -070057 private final int mTargetSdkLevel;
Aravind Akella88445992015-02-26 17:05:28 -080058 private final String mPackageName;
Jeff Brown25157e42012-04-16 12:13:05 -070059
Mathias Agopiandb772d82013-01-31 19:31:12 -080060 /** {@hide} */
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -070061 public SystemSensorManager(Context context, Looper mainLooper) {
Jeff Brown25157e42012-04-16 12:13:05 -070062 mMainLooper = mainLooper;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -070063 mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
Aravind Akella88445992015-02-26 17:05:28 -080064 mPackageName = context.getPackageName();
Mathias Agopiandb772d82013-01-31 19:31:12 -080065 synchronized(sSensorModuleLock) {
Jeff Brown25157e42012-04-16 12:13:05 -070066 if (!sSensorModuleInitialized) {
67 sSensorModuleInitialized = true;
68
69 nativeClassInit();
70
71 // initialize the sensor list
Jeff Brown25157e42012-04-16 12:13:05 -070072 final ArrayList<Sensor> fullList = sFullSensorsList;
73 int i = 0;
74 do {
75 Sensor sensor = new Sensor();
Mathias Agopiandb772d82013-01-31 19:31:12 -080076 i = nativeGetNextSensor(sensor, i);
Jeff Brown25157e42012-04-16 12:13:05 -070077 if (i>=0) {
78 //Log.d(TAG, "found sensor: " + sensor.getName() +
79 // ", handle=" + sensor.getHandle());
80 fullList.add(sensor);
81 sHandleToSensor.append(sensor.getHandle(), sensor);
82 }
83 } while (i>0);
Jeff Brown25157e42012-04-16 12:13:05 -070084 }
85 }
86 }
87
Mathias Agopiandb772d82013-01-31 19:31:12 -080088
Jeff Brown25157e42012-04-16 12:13:05 -070089 /** @hide */
90 @Override
91 protected List<Sensor> getFullSensorList() {
92 return sFullSensorsList;
93 }
94
Jeff Brown25157e42012-04-16 12:13:05 -070095
96 /** @hide */
Jeff Brown4481d9c2012-04-16 16:14:44 -070097 @Override
Jeff Brown25157e42012-04-16 12:13:05 -070098 protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
Aravind Akella4bdc37d2013-10-01 17:58:35 -070099 int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {
100 if (listener == null || sensor == null) {
101 Log.e(TAG, "sensor or listener is null");
102 return false;
103 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700104 // Trigger Sensors should use the requestTriggerSensor call.
Aravind Akella27900352014-06-03 19:20:42 -0700105 if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700106 Log.e(TAG, "Trigger Sensors should use the requestTriggerSensor.");
107 return false;
108 }
109 if (maxBatchReportLatencyUs < 0 || delayUs < 0) {
110 Log.e(TAG, "maxBatchReportLatencyUs and delayUs should be non-negative");
111 return false;
112 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700113
Mathias Agopiandb772d82013-01-31 19:31:12 -0800114 // Invariants to preserve:
115 // - one Looper per SensorEventListener
116 // - one Looper per SensorEventQueue
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800117 // We map SensorEventListener to a SensorEventQueue, which holds the looper
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800118 synchronized (mSensorListeners) {
119 SensorEventQueue queue = mSensorListeners.get(listener);
120 if (queue == null) {
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700121 Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700122 queue = new SensorEventQueue(listener, looper, this);
Aravind Akella88445992015-02-26 17:05:28 -0800123 if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs)) {
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700124 queue.dispose();
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800125 return false;
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700126 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800127 mSensorListeners.put(listener, queue);
128 return true;
129 } else {
Aravind Akella88445992015-02-26 17:05:28 -0800130 return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs);
Jeff Brown25157e42012-04-16 12:13:05 -0700131 }
132 }
Jeff Brown25157e42012-04-16 12:13:05 -0700133 }
134
135 /** @hide */
136 @Override
137 protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800138 // Trigger Sensors should use the cancelTriggerSensor call.
Aravind Akella27900352014-06-03 19:20:42 -0700139 if (sensor != null && sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800140 return;
141 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800142
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800143 synchronized (mSensorListeners) {
144 SensorEventQueue queue = mSensorListeners.get(listener);
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700145 if (queue != null) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800146 boolean result;
147 if (sensor == null) {
148 result = queue.removeAllSensors();
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700149 } else {
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700150 result = queue.removeSensor(sensor, true);
Jaikumar Ganesh1aab1db2013-03-13 15:00:21 -0700151 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800152 if (result && !queue.hasSensors()) {
153 mSensorListeners.remove(listener);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800154 queue.dispose();
Jeff Brown25157e42012-04-16 12:13:05 -0700155 }
156 }
157 }
158 }
159
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800160 /** @hide */
161 @Override
162 protected boolean requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor) {
163 if (sensor == null) throw new IllegalArgumentException("sensor cannot be null");
Jeff Brown25157e42012-04-16 12:13:05 -0700164
Aravind Akella27900352014-06-03 19:20:42 -0700165 if (sensor.getReportingMode() != Sensor.REPORTING_MODE_ONE_SHOT) return false;
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800166
167 synchronized (mTriggerListeners) {
168 TriggerEventQueue queue = mTriggerListeners.get(listener);
169 if (queue == null) {
170 queue = new TriggerEventQueue(listener, mMainLooper, this);
Aravind Akella88445992015-02-26 17:05:28 -0800171 if (!queue.addSensor(sensor, 0, 0)) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800172 queue.dispose();
173 return false;
174 }
175 mTriggerListeners.put(listener, queue);
176 return true;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800177 } else {
Aravind Akella88445992015-02-26 17:05:28 -0800178 return queue.addSensor(sensor, 0, 0);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800179 }
180 }
181 }
Jeff Brown25157e42012-04-16 12:13:05 -0700182
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800183 /** @hide */
184 @Override
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700185 protected boolean cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor,
186 boolean disable) {
Aravind Akella27900352014-06-03 19:20:42 -0700187 if (sensor != null && sensor.getReportingMode() != Sensor.REPORTING_MODE_ONE_SHOT) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800188 return false;
189 }
190 synchronized (mTriggerListeners) {
191 TriggerEventQueue queue = mTriggerListeners.get(listener);
192 if (queue != null) {
193 boolean result;
194 if (sensor == null) {
195 result = queue.removeAllSensors();
196 } else {
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700197 result = queue.removeSensor(sensor, disable);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800198 }
199 if (result && !queue.hasSensors()) {
200 mTriggerListeners.remove(listener);
201 queue.dispose();
202 }
203 return result;
204 }
205 return false;
206 }
207 }
208
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700209 protected boolean flushImpl(SensorEventListener listener) {
210 if (listener == null) throw new IllegalArgumentException("listener cannot be null");
Aravind Akellab4c76b12013-06-27 12:04:16 -0700211
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700212 synchronized (mSensorListeners) {
213 SensorEventQueue queue = mSensorListeners.get(listener);
214 if (queue == null) {
215 return false;
216 } else {
217 return (queue.flush() == 0);
218 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700219 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700220 }
221
Mathias Agopiandb772d82013-01-31 19:31:12 -0800222 /*
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800223 * BaseEventQueue is the communication channel with the sensor service,
224 * SensorEventQueue, TriggerEventQueue are subclases and there is one-to-one mapping between
225 * the queues and the listeners.
Mathias Agopiandb772d82013-01-31 19:31:12 -0800226 */
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800227 private static abstract class BaseEventQueue {
Jeff Brown3b4049e2015-04-17 15:22:27 -0700228 private native long nativeInitBaseEventQueue(WeakReference<BaseEventQueue> eventQWeak,
229 MessageQueue msgQ, float[] scratch, String packageName);
Ashok Bhat4838e332014-01-03 14:37:19 +0000230 private static native int nativeEnableSensor(long eventQ, int handle, int rateUs,
Aravind Akella88445992015-02-26 17:05:28 -0800231 int maxBatchReportLatencyUs);
Ashok Bhat4838e332014-01-03 14:37:19 +0000232 private static native int nativeDisableSensor(long eventQ, int handle);
233 private static native void nativeDestroySensorEventQueue(long eventQ);
234 private static native int nativeFlushSensor(long eventQ);
235 private long nSensorEventQueue;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800236 private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800237 protected final SparseIntArray mSensorAccuracies = new SparseIntArray();
238 protected final SparseBooleanArray mFirstEvent = new SparseBooleanArray();
Mathias Agopiandb772d82013-01-31 19:31:12 -0800239 private final CloseGuard mCloseGuard = CloseGuard.get();
240 private final float[] mScratch = new float[16];
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700241 protected final SystemSensorManager mManager;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800242
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700243 BaseEventQueue(Looper looper, SystemSensorManager manager) {
Jeff Brown3b4049e2015-04-17 15:22:27 -0700244 nSensorEventQueue = nativeInitBaseEventQueue(new WeakReference<BaseEventQueue>(this),
245 looper.getQueue(), mScratch,
Aravind Akella88445992015-02-26 17:05:28 -0800246 manager.mPackageName);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800247 mCloseGuard.open("dispose");
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700248 mManager = manager;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800249 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800250
Mathias Agopiandb772d82013-01-31 19:31:12 -0800251 public void dispose() {
252 dispose(false);
253 }
254
Aravind Akellab4c76b12013-06-27 12:04:16 -0700255 public boolean addSensor(
Aravind Akella88445992015-02-26 17:05:28 -0800256 Sensor sensor, int delayUs, int maxBatchReportLatencyUs) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800257 // Check if already present.
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700258 int handle = sensor.getHandle();
259 if (mActiveSensors.get(handle)) return false;
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800260
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700261 // Get ready to receive events before calling enable.
262 mActiveSensors.put(handle, true);
263 addSensorEvent(sensor);
Aravind Akella88445992015-02-26 17:05:28 -0800264 if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs) != 0) {
Aravind Akellab4c76b12013-06-27 12:04:16 -0700265 // Try continuous mode if batching fails.
266 if (maxBatchReportLatencyUs == 0 ||
Aravind Akella88445992015-02-26 17:05:28 -0800267 maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0) != 0) {
Aravind Akellab4c76b12013-06-27 12:04:16 -0700268 removeSensor(sensor, false);
269 return false;
270 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800271 }
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700272 return true;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800273 }
274
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800275 public boolean removeAllSensors() {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800276 for (int i=0 ; i<mActiveSensors.size(); i++) {
277 if (mActiveSensors.valueAt(i) == true) {
278 int handle = mActiveSensors.keyAt(i);
279 Sensor sensor = sHandleToSensor.get(handle);
280 if (sensor != null) {
281 disableSensor(sensor);
282 mActiveSensors.put(handle, false);
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700283 removeSensorEvent(sensor);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800284 } else {
285 // it should never happen -- just ignore.
286 }
287 }
288 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800289 return true;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800290 }
291
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700292 public boolean removeSensor(Sensor sensor, boolean disable) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800293 final int handle = sensor.getHandle();
294 if (mActiveSensors.get(handle)) {
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700295 if (disable) disableSensor(sensor);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800296 mActiveSensors.put(sensor.getHandle(), false);
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700297 removeSensorEvent(sensor);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800298 return true;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800299 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800300 return false;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800301 }
302
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700303 public int flush() {
Aravind Akellab4c76b12013-06-27 12:04:16 -0700304 if (nSensorEventQueue == 0) throw new NullPointerException();
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700305 return nativeFlushSensor(nSensorEventQueue);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700306 }
307
Mathias Agopiandb772d82013-01-31 19:31:12 -0800308 public boolean hasSensors() {
309 // no more sensors are set
310 return mActiveSensors.indexOfValue(true) >= 0;
311 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800312
Mathias Agopiandb772d82013-01-31 19:31:12 -0800313 @Override
314 protected void finalize() throws Throwable {
315 try {
316 dispose(true);
317 } finally {
318 super.finalize();
319 }
320 }
321
322 private void dispose(boolean finalized) {
323 if (mCloseGuard != null) {
324 if (finalized) {
325 mCloseGuard.warnIfOpen();
326 }
327 mCloseGuard.close();
328 }
329 if (nSensorEventQueue != 0) {
330 nativeDestroySensorEventQueue(nSensorEventQueue);
331 nSensorEventQueue = 0;
332 }
333 }
334
Aravind Akellab4c76b12013-06-27 12:04:16 -0700335 private int enableSensor(
Aravind Akella88445992015-02-26 17:05:28 -0800336 Sensor sensor, int rateUs, int maxBatchReportLatencyUs) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800337 if (nSensorEventQueue == 0) throw new NullPointerException();
338 if (sensor == null) throw new NullPointerException();
Aravind Akellab4c76b12013-06-27 12:04:16 -0700339 return nativeEnableSensor(nSensorEventQueue, sensor.getHandle(), rateUs,
Aravind Akella88445992015-02-26 17:05:28 -0800340 maxBatchReportLatencyUs);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800341 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700342
Mathias Agopiandb772d82013-01-31 19:31:12 -0800343 private int disableSensor(Sensor sensor) {
344 if (nSensorEventQueue == 0) throw new NullPointerException();
345 if (sensor == null) throw new NullPointerException();
346 return nativeDisableSensor(nSensorEventQueue, sensor.getHandle());
347 }
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800348 protected abstract void dispatchSensorEvent(int handle, float[] values, int accuracy,
349 long timestamp);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700350 protected abstract void dispatchFlushCompleteEvent(int handle);
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700351
352 protected abstract void addSensorEvent(Sensor sensor);
353 protected abstract void removeSensorEvent(Sensor sensor);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800354 }
355
356 static final class SensorEventQueue extends BaseEventQueue {
357 private final SensorEventListener mListener;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700358 private final SparseArray<SensorEvent> mSensorsEvents = new SparseArray<SensorEvent>();
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800359
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700360 public SensorEventQueue(SensorEventListener listener, Looper looper,
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700361 SystemSensorManager manager) {
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700362 super(looper, manager);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800363 mListener = listener;
364 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800365
Aravind Akella31d14ce2013-10-22 20:04:22 -0700366 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700367 public void addSensorEvent(Sensor sensor) {
368 SensorEvent t = new SensorEvent(Sensor.getMaxLengthValuesArray(sensor,
369 mManager.mTargetSdkLevel));
Aravind Akella31d14ce2013-10-22 20:04:22 -0700370 synchronized (mSensorsEvents) {
371 mSensorsEvents.put(sensor.getHandle(), t);
372 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700373 }
374
Aravind Akella31d14ce2013-10-22 20:04:22 -0700375 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700376 public void removeSensorEvent(Sensor sensor) {
Aravind Akella31d14ce2013-10-22 20:04:22 -0700377 synchronized (mSensorsEvents) {
378 mSensorsEvents.delete(sensor.getHandle());
379 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700380 }
381
Mathias Agopiandb772d82013-01-31 19:31:12 -0800382 // Called from native code.
383 @SuppressWarnings("unused")
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800384 @Override
385 protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,
386 long timestamp) {
387 final Sensor sensor = sHandleToSensor.get(handle);
Aravind Akella31d14ce2013-10-22 20:04:22 -0700388 SensorEvent t = null;
389 synchronized (mSensorsEvents) {
390 t = mSensorsEvents.get(handle);
391 }
392
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700393 if (t == null) {
Aravind Akella31d14ce2013-10-22 20:04:22 -0700394 // This may happen if the client has unregistered and there are pending events in
395 // the queue waiting to be delivered. Ignore.
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700396 return;
397 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700398 // Copy from the values array.
399 System.arraycopy(values, 0, t.values, 0, t.values.length);
400 t.timestamp = timestamp;
401 t.accuracy = inAccuracy;
402 t.sensor = sensor;
Etienne Le Grandaf805102014-05-16 12:21:41 -0700403
404 // call onAccuracyChanged() only if the value changes
405 final int accuracy = mSensorAccuracies.get(handle);
406 if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
407 mSensorAccuracies.put(handle, t.accuracy);
408 mListener.onAccuracyChanged(t.sensor, t.accuracy);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800409 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700410 mListener.onSensorChanged(t);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800411 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700412
413 @SuppressWarnings("unused")
414 protected void dispatchFlushCompleteEvent(int handle) {
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700415 if (mListener instanceof SensorEventListener2) {
416 final Sensor sensor = sHandleToSensor.get(handle);
417 ((SensorEventListener2)mListener).onFlushCompleted(sensor);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700418 }
419 return;
420 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800421 }
422
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800423 static final class TriggerEventQueue extends BaseEventQueue {
424 private final TriggerEventListener mListener;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700425 private final SparseArray<TriggerEvent> mTriggerEvents = new SparseArray<TriggerEvent>();
Mathias Agopiandb772d82013-01-31 19:31:12 -0800426
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800427 public TriggerEventQueue(TriggerEventListener listener, Looper looper,
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700428 SystemSensorManager manager) {
429 super(looper, manager);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800430 mListener = listener;
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700431 }
432
Aravind Akella31d14ce2013-10-22 20:04:22 -0700433 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700434 public void addSensorEvent(Sensor sensor) {
435 TriggerEvent t = new TriggerEvent(Sensor.getMaxLengthValuesArray(sensor,
436 mManager.mTargetSdkLevel));
Aravind Akella31d14ce2013-10-22 20:04:22 -0700437 synchronized (mTriggerEvents) {
438 mTriggerEvents.put(sensor.getHandle(), t);
439 }
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700440 }
441
Aravind Akella31d14ce2013-10-22 20:04:22 -0700442 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700443 public void removeSensorEvent(Sensor sensor) {
Aravind Akella31d14ce2013-10-22 20:04:22 -0700444 synchronized (mTriggerEvents) {
445 mTriggerEvents.delete(sensor.getHandle());
446 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800447 }
448
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800449 // Called from native code.
450 @SuppressWarnings("unused")
451 @Override
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700452 protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
453 long timestamp) {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800454 final Sensor sensor = sHandleToSensor.get(handle);
Aravind Akella31d14ce2013-10-22 20:04:22 -0700455 TriggerEvent t = null;
456 synchronized (mTriggerEvents) {
457 t = mTriggerEvents.get(handle);
458 }
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700459 if (t == null) {
460 Log.e(TAG, "Error: Trigger Event is null for Sensor: " + sensor);
461 return;
462 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800463
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700464 // Copy from the values array.
465 System.arraycopy(values, 0, t.values, 0, t.values.length);
466 t.timestamp = timestamp;
467 t.sensor = sensor;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800468
Jaikumar Ganesh2e900892013-04-11 10:40:33 -0700469 // A trigger sensor is auto disabled. So just clean up and don't call native
470 // disable.
471 mManager.cancelTriggerSensorImpl(mListener, sensor, false);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800472
Jaikumar Ganesh6d0c1d782013-03-27 17:41:33 -0700473 mListener.onTrigger(t);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800474 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700475
476 @SuppressWarnings("unused")
477 protected void dispatchFlushCompleteEvent(int handle) {
478 }
479 }
Jeff Brown25157e42012-04-16 12:13:05 -0700480}