1 /*
2  * 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 
17 package android.hardware;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.os.Handler;
24 import android.os.Looper;
25 import android.os.MemoryFile;
26 import android.os.MessageQueue;
27 import android.util.Log;
28 import android.util.SparseArray;
29 import android.util.SparseBooleanArray;
30 import android.util.SparseIntArray;
31 import dalvik.system.CloseGuard;
32 
33 import com.android.internal.annotations.GuardedBy;
34 
35 import java.io.IOException;
36 import java.io.UncheckedIOException;
37 import java.lang.ref.WeakReference;
38 import java.util.ArrayList;
39 import java.util.HashMap;
40 import java.util.List;
41 import java.util.Map;
42 
43 
44 /**
45  * Sensor manager implementation that communicates with the built-in
46  * system sensors.
47  *
48  * @hide
49  */
50 public class SystemSensorManager extends SensorManager {
51     //TODO: disable extra logging before release
52     private static final boolean DEBUG_DYNAMIC_SENSOR = true;
53     private static final int MIN_DIRECT_CHANNEL_BUFFER_SIZE = 104;
54     private static final int MAX_LISTENER_COUNT = 128;
55 
nativeClassInit()56     private static native void nativeClassInit();
nativeCreate(String opPackageName)57     private static native long nativeCreate(String opPackageName);
nativeGetSensorAtIndex(long nativeInstance, Sensor sensor, int index)58     private static native boolean nativeGetSensorAtIndex(long nativeInstance,
59             Sensor sensor, int index);
nativeGetDynamicSensors(long nativeInstance, List<Sensor> list)60     private static native void nativeGetDynamicSensors(long nativeInstance, List<Sensor> list);
nativeIsDataInjectionEnabled(long nativeInstance)61     private static native boolean nativeIsDataInjectionEnabled(long nativeInstance);
62 
nativeCreateDirectChannel( long nativeInstance, long size, int channelType, int fd, HardwareBuffer buffer)63     private static native int nativeCreateDirectChannel(
64             long nativeInstance, long size, int channelType, int fd, HardwareBuffer buffer);
nativeDestroyDirectChannel( long nativeInstance, int channelHandle)65     private static native void nativeDestroyDirectChannel(
66             long nativeInstance, int channelHandle);
nativeConfigDirectChannel( long nativeInstance, int channelHandle, int sensorHandle, int rate)67     private static native int nativeConfigDirectChannel(
68             long nativeInstance, int channelHandle, int sensorHandle, int rate);
69 
nativeSetOperationParameter( long nativeInstance, int type, float[] floatValues, int[] intValues)70     private static native int nativeSetOperationParameter(
71             long nativeInstance, int type, float[] floatValues, int[] intValues);
72 
73     private static final Object sLock = new Object();
74     @GuardedBy("sLock")
75     private static boolean sNativeClassInited = false;
76     @GuardedBy("sLock")
77     private static InjectEventQueue sInjectEventQueue = null;
78 
79     private final ArrayList<Sensor> mFullSensorsList = new ArrayList<>();
80     private List<Sensor> mFullDynamicSensorsList = new ArrayList<>();
81     private boolean mDynamicSensorListDirty = true;
82 
83     private final HashMap<Integer, Sensor> mHandleToSensor = new HashMap<>();
84 
85     // Listener list
86     private final HashMap<SensorEventListener, SensorEventQueue> mSensorListeners =
87             new HashMap<SensorEventListener, SensorEventQueue>();
88     private final HashMap<TriggerEventListener, TriggerEventQueue> mTriggerListeners =
89             new HashMap<TriggerEventListener, TriggerEventQueue>();
90 
91     // Dynamic Sensor callbacks
92     private HashMap<DynamicSensorCallback, Handler>
93             mDynamicSensorCallbacks = new HashMap<>();
94     private BroadcastReceiver mDynamicSensorBroadcastReceiver;
95 
96     // Looper associated with the context in which this instance was created.
97     private final Looper mMainLooper;
98     private final int mTargetSdkLevel;
99     private final Context mContext;
100     private final long mNativeInstance;
101 
102     /** {@hide} */
SystemSensorManager(Context context, Looper mainLooper)103     public SystemSensorManager(Context context, Looper mainLooper) {
104         synchronized(sLock) {
105             if (!sNativeClassInited) {
106                 sNativeClassInited = true;
107                 nativeClassInit();
108             }
109         }
110 
111         mMainLooper = mainLooper;
112         mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
113         mContext = context;
114         mNativeInstance = nativeCreate(context.getOpPackageName());
115 
116         // initialize the sensor list
117         for (int index = 0;;++index) {
118             Sensor sensor = new Sensor();
119             if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
120             mFullSensorsList.add(sensor);
121             mHandleToSensor.put(sensor.getHandle(), sensor);
122         }
123     }
124 
125 
126     /** @hide */
127     @Override
getFullSensorList()128     protected List<Sensor> getFullSensorList() {
129         return mFullSensorsList;
130     }
131 
132     /** @hide */
133     @Override
getFullDynamicSensorList()134     protected List<Sensor> getFullDynamicSensorList() {
135         // only set up broadcast receiver if the application tries to find dynamic sensors or
136         // explicitly register a DynamicSensorCallback
137         setupDynamicSensorBroadcastReceiver();
138         updateDynamicSensorList();
139         return mFullDynamicSensorsList;
140     }
141 
142     /** @hide */
143     @Override
registerListenerImpl(SensorEventListener listener, Sensor sensor, int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags)144     protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
145             int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {
146         if (listener == null || sensor == null) {
147             Log.e(TAG, "sensor or listener is null");
148             return false;
149         }
150         // Trigger Sensors should use the requestTriggerSensor call.
151         if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
152             Log.e(TAG, "Trigger Sensors should use the requestTriggerSensor.");
153             return false;
154         }
155         if (maxBatchReportLatencyUs < 0 || delayUs < 0) {
156             Log.e(TAG, "maxBatchReportLatencyUs and delayUs should be non-negative");
157             return false;
158         }
159         if (mSensorListeners.size() >= MAX_LISTENER_COUNT) {
160             throw new IllegalStateException("register failed, " +
161                 "the sensor listeners size has exceeded the maximum limit " +
162                 MAX_LISTENER_COUNT);
163         }
164 
165         // Invariants to preserve:
166         // - one Looper per SensorEventListener
167         // - one Looper per SensorEventQueue
168         // We map SensorEventListener to a SensorEventQueue, which holds the looper
169         synchronized (mSensorListeners) {
170             SensorEventQueue queue = mSensorListeners.get(listener);
171             if (queue == null) {
172                 Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
173                 final String fullClassName = listener.getClass().getEnclosingClass() != null ?
174                     listener.getClass().getEnclosingClass().getName() :
175                     listener.getClass().getName();
176                 queue = new SensorEventQueue(listener, looper, this, fullClassName);
177                 if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs)) {
178                     queue.dispose();
179                     return false;
180                 }
181                 mSensorListeners.put(listener, queue);
182                 return true;
183             } else {
184                 return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs);
185             }
186         }
187     }
188 
189     /** @hide */
190     @Override
unregisterListenerImpl(SensorEventListener listener, Sensor sensor)191     protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
192         // Trigger Sensors should use the cancelTriggerSensor call.
193         if (sensor != null && sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
194             return;
195         }
196 
197         synchronized (mSensorListeners) {
198             SensorEventQueue queue = mSensorListeners.get(listener);
199             if (queue != null) {
200                 boolean result;
201                 if (sensor == null) {
202                     result = queue.removeAllSensors();
203                 } else {
204                     result = queue.removeSensor(sensor, true);
205                 }
206                 if (result && !queue.hasSensors()) {
207                     mSensorListeners.remove(listener);
208                     queue.dispose();
209                 }
210             }
211         }
212     }
213 
214     /** @hide */
215     @Override
requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor)216     protected boolean requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor) {
217         if (sensor == null) throw new IllegalArgumentException("sensor cannot be null");
218 
219         if (listener == null) throw new IllegalArgumentException("listener cannot be null");
220 
221         if (sensor.getReportingMode() != Sensor.REPORTING_MODE_ONE_SHOT) return false;
222 
223         if (mTriggerListeners.size() >= MAX_LISTENER_COUNT) {
224             throw new IllegalStateException("request failed, " +
225                     "the trigger listeners size has exceeded the maximum limit " +
226                     MAX_LISTENER_COUNT);
227         }
228 
229         synchronized (mTriggerListeners) {
230             TriggerEventQueue queue = mTriggerListeners.get(listener);
231             if (queue == null) {
232                 final String fullClassName = listener.getClass().getEnclosingClass() != null ?
233                     listener.getClass().getEnclosingClass().getName() :
234                     listener.getClass().getName();
235                 queue = new TriggerEventQueue(listener, mMainLooper, this, fullClassName);
236                 if (!queue.addSensor(sensor, 0, 0)) {
237                     queue.dispose();
238                     return false;
239                 }
240                 mTriggerListeners.put(listener, queue);
241                 return true;
242             } else {
243                 return queue.addSensor(sensor, 0, 0);
244             }
245         }
246     }
247 
248     /** @hide */
249     @Override
cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor, boolean disable)250     protected boolean cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor,
251             boolean disable) {
252         if (sensor != null && sensor.getReportingMode() != Sensor.REPORTING_MODE_ONE_SHOT) {
253             return false;
254         }
255         synchronized (mTriggerListeners) {
256             TriggerEventQueue queue = mTriggerListeners.get(listener);
257             if (queue != null) {
258                 boolean result;
259                 if (sensor == null) {
260                     result = queue.removeAllSensors();
261                 } else {
262                     result = queue.removeSensor(sensor, disable);
263                 }
264                 if (result && !queue.hasSensors()) {
265                     mTriggerListeners.remove(listener);
266                     queue.dispose();
267                 }
268                 return result;
269             }
270             return false;
271         }
272     }
273 
flushImpl(SensorEventListener listener)274     protected boolean flushImpl(SensorEventListener listener) {
275         if (listener == null) throw new IllegalArgumentException("listener cannot be null");
276 
277         synchronized (mSensorListeners) {
278             SensorEventQueue queue = mSensorListeners.get(listener);
279             if (queue == null) {
280                 return false;
281             } else {
282                 return (queue.flush() == 0);
283             }
284         }
285     }
286 
initDataInjectionImpl(boolean enable)287     protected boolean initDataInjectionImpl(boolean enable) {
288         synchronized (sLock) {
289             if (enable) {
290                 boolean isDataInjectionModeEnabled = nativeIsDataInjectionEnabled(mNativeInstance);
291                 // The HAL does not support injection OR SensorService hasn't been set in DI mode.
292                 if (!isDataInjectionModeEnabled) {
293                     Log.e(TAG, "Data Injection mode not enabled");
294                     return false;
295                 }
296                 // Initialize a client for data_injection.
297                 if (sInjectEventQueue == null) {
298                     try {
299                         sInjectEventQueue = new InjectEventQueue(
300                                 mMainLooper, this, mContext.getPackageName());
301                     } catch (RuntimeException e) {
302                         Log.e(TAG, "Cannot create InjectEventQueue: " + e);
303                     }
304                 }
305                 return sInjectEventQueue != null;
306             } else {
307                 // If data injection is being disabled clean up the native resources.
308                 if (sInjectEventQueue != null) {
309                     sInjectEventQueue.dispose();
310                     sInjectEventQueue = null;
311                 }
312                 return true;
313             }
314         }
315     }
316 
injectSensorDataImpl(Sensor sensor, float[] values, int accuracy, long timestamp)317     protected boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy,
318             long timestamp) {
319         synchronized (sLock) {
320             if (sInjectEventQueue == null) {
321                 Log.e(TAG, "Data injection mode not activated before calling injectSensorData");
322                 return false;
323             }
324             int ret = sInjectEventQueue.injectSensorData(sensor.getHandle(), values, accuracy,
325                                                          timestamp);
326             // If there are any errors in data injection clean up the native resources.
327             if (ret != 0) {
328                 sInjectEventQueue.dispose();
329                 sInjectEventQueue = null;
330             }
331             return ret == 0;
332         }
333     }
334 
cleanupSensorConnection(Sensor sensor)335     private void cleanupSensorConnection(Sensor sensor) {
336         mHandleToSensor.remove(sensor.getHandle());
337 
338         if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
339             synchronized(mTriggerListeners) {
340                 HashMap<TriggerEventListener, TriggerEventQueue> triggerListeners =
341                     new HashMap<TriggerEventListener, TriggerEventQueue>(mTriggerListeners);
342 
343                 for (TriggerEventListener l: triggerListeners.keySet()) {
344                     if (DEBUG_DYNAMIC_SENSOR){
345                         Log.i(TAG, "removed trigger listener" + l.toString() +
346                                    " due to sensor disconnection");
347                     }
348                     cancelTriggerSensorImpl(l, sensor, true);
349                 }
350             }
351         } else {
352             synchronized(mSensorListeners) {
353                 HashMap<SensorEventListener, SensorEventQueue> sensorListeners =
354                     new HashMap<SensorEventListener, SensorEventQueue>(mSensorListeners);
355 
356                 for (SensorEventListener l: sensorListeners.keySet()) {
357                     if (DEBUG_DYNAMIC_SENSOR){
358                         Log.i(TAG, "removed event listener" + l.toString() +
359                                    " due to sensor disconnection");
360                     }
361                     unregisterListenerImpl(l, sensor);
362                 }
363             }
364         }
365     }
366 
updateDynamicSensorList()367     private void updateDynamicSensorList() {
368         synchronized(mFullDynamicSensorsList) {
369             if (mDynamicSensorListDirty) {
370                 List<Sensor> list = new ArrayList<>();
371                 nativeGetDynamicSensors(mNativeInstance, list);
372 
373                 final List<Sensor> updatedList = new ArrayList<>();
374                 final List<Sensor> addedList = new ArrayList<>();
375                 final List<Sensor> removedList = new ArrayList<>();
376 
377                 boolean changed = diffSortedSensorList(
378                         mFullDynamicSensorsList, list, updatedList, addedList, removedList);
379 
380                 if (changed) {
381                     if (DEBUG_DYNAMIC_SENSOR) {
382                         Log.i(TAG, "DYNS dynamic sensor list cached should be updated");
383                     }
384                     mFullDynamicSensorsList = updatedList;
385 
386                     for (Sensor s: addedList) {
387                         mHandleToSensor.put(s.getHandle(), s);
388                     }
389 
390                     Handler mainHandler = new Handler(mContext.getMainLooper());
391 
392                     for (Map.Entry<DynamicSensorCallback, Handler> entry :
393                             mDynamicSensorCallbacks.entrySet()) {
394                         final DynamicSensorCallback callback = entry.getKey();
395                         Handler handler =
396                                 entry.getValue() == null ? mainHandler : entry.getValue();
397 
398                         handler.post(new Runnable() {
399                             @Override
400                             public void run() {
401                                 for (Sensor s: addedList) {
402                                     callback.onDynamicSensorConnected(s);
403                                 }
404                                 for (Sensor s: removedList) {
405                                     callback.onDynamicSensorDisconnected(s);
406                                 }
407                             }
408                         });
409                     }
410 
411                     for (Sensor s: removedList) {
412                         cleanupSensorConnection(s);
413                     }
414                 }
415 
416                 mDynamicSensorListDirty = false;
417             }
418         }
419     }
420 
setupDynamicSensorBroadcastReceiver()421     private void setupDynamicSensorBroadcastReceiver() {
422         if (mDynamicSensorBroadcastReceiver == null) {
423             mDynamicSensorBroadcastReceiver = new BroadcastReceiver() {
424                 @Override
425                 public void onReceive(Context context, Intent intent) {
426                     if (intent.getAction() == Intent.ACTION_DYNAMIC_SENSOR_CHANGED) {
427                         if (DEBUG_DYNAMIC_SENSOR) {
428                             Log.i(TAG, "DYNS received DYNAMIC_SENSOR_CHANED broadcast");
429                         }
430                         // Dynamic sensors probably changed
431                         mDynamicSensorListDirty = true;
432                         updateDynamicSensorList();
433                     }
434                 }
435             };
436 
437             IntentFilter filter = new IntentFilter("dynamic_sensor_change");
438             filter.addAction(Intent.ACTION_DYNAMIC_SENSOR_CHANGED);
439             mContext.registerReceiver(mDynamicSensorBroadcastReceiver, filter);
440         }
441     }
442 
teardownDynamicSensorBroadcastReceiver()443     private void teardownDynamicSensorBroadcastReceiver() {
444         mDynamicSensorCallbacks.clear();
445         mContext.unregisterReceiver(mDynamicSensorBroadcastReceiver);
446         mDynamicSensorBroadcastReceiver = null;
447     }
448 
449     /** @hide */
registerDynamicSensorCallbackImpl( DynamicSensorCallback callback, Handler handler)450     protected void registerDynamicSensorCallbackImpl(
451             DynamicSensorCallback callback, Handler handler) {
452         if (DEBUG_DYNAMIC_SENSOR) {
453             Log.i(TAG, "DYNS Register dynamic sensor callback");
454         }
455 
456         if (callback == null) {
457             throw new IllegalArgumentException("callback cannot be null");
458         }
459         if (mDynamicSensorCallbacks.containsKey(callback)) {
460             // has been already registered, ignore
461             return;
462         }
463 
464         setupDynamicSensorBroadcastReceiver();
465         mDynamicSensorCallbacks.put(callback, handler);
466     }
467 
468     /** @hide */
unregisterDynamicSensorCallbackImpl( DynamicSensorCallback callback)469     protected void unregisterDynamicSensorCallbackImpl(
470             DynamicSensorCallback callback) {
471         if (DEBUG_DYNAMIC_SENSOR) {
472             Log.i(TAG, "Removing dynamic sensor listerner");
473         }
474         mDynamicSensorCallbacks.remove(callback);
475     }
476 
477     /*
478      * Find the difference of two List<Sensor> assuming List are sorted by handle of sensor,
479      * assuming the input list is already sorted by handle. Inputs are ol and nl; outputs are
480      * updated, added and removed. Any of the output lists can be null in case the result is not
481      * interested.
482      */
diffSortedSensorList( List<Sensor> oldList, List<Sensor> newList, List<Sensor> updated, List<Sensor> added, List<Sensor> removed)483     private static boolean diffSortedSensorList(
484             List<Sensor> oldList, List<Sensor> newList, List<Sensor> updated,
485             List<Sensor> added, List<Sensor> removed) {
486 
487         boolean changed = false;
488 
489         int i = 0, j = 0;
490         while (true) {
491             if (j < oldList.size() && ( i >= newList.size() ||
492                     newList.get(i).getHandle() > oldList.get(j).getHandle()) ) {
493                 changed = true;
494                 if (removed != null) {
495                     removed.add(oldList.get(j));
496                 }
497                 ++j;
498             } else if (i < newList.size() && ( j >= oldList.size() ||
499                     newList.get(i).getHandle() < oldList.get(j).getHandle())) {
500                 changed = true;
501                 if (added != null) {
502                     added.add(newList.get(i));
503                 }
504                 if (updated != null) {
505                     updated.add(newList.get(i));
506                 }
507                 ++i;
508             } else if (i < newList.size() && j < oldList.size() &&
509                     newList.get(i).getHandle() == oldList.get(j).getHandle()) {
510                 if (updated != null) {
511                     updated.add(oldList.get(j));
512                 }
513                 ++i;
514                 ++j;
515             } else {
516                 break;
517             }
518         }
519         return changed;
520     }
521 
522     /** @hide */
configureDirectChannelImpl( SensorDirectChannel channel, Sensor sensor, int rate)523     protected int configureDirectChannelImpl(
524             SensorDirectChannel channel, Sensor sensor, int rate) {
525         if (!channel.isOpen()) {
526             throw new IllegalStateException("channel is closed");
527         }
528 
529         if (rate < SensorDirectChannel.RATE_STOP
530                 || rate > SensorDirectChannel.RATE_VERY_FAST) {
531             throw new IllegalArgumentException("rate parameter invalid");
532         }
533 
534         if (sensor == null && rate != SensorDirectChannel.RATE_STOP) {
535             // the stop all sensors case
536             throw new IllegalArgumentException(
537                     "when sensor is null, rate can only be DIRECT_RATE_STOP");
538         }
539 
540         int sensorHandle = (sensor == null) ? -1 : sensor.getHandle();
541 
542         int ret = nativeConfigDirectChannel(
543                 mNativeInstance, channel.getNativeHandle(), sensorHandle, rate);
544 
545         if (rate == SensorDirectChannel.RATE_STOP) {
546             return (ret == 0) ? 1 : 0;
547         } else {
548             return (ret > 0) ? ret : 0;
549         }
550     }
551 
552     /** @hide */
createDirectChannelImpl( MemoryFile memoryFile, HardwareBuffer hardwareBuffer)553     protected SensorDirectChannel createDirectChannelImpl(
554             MemoryFile memoryFile, HardwareBuffer hardwareBuffer) {
555         int id;
556         int type;
557         long size;
558         if (memoryFile != null) {
559             int fd;
560             try {
561                 fd = memoryFile.getFileDescriptor().getInt$();
562             } catch (IOException e) {
563                 throw new IllegalArgumentException("MemoryFile object is not valid");
564             }
565 
566             if (memoryFile.length() < MIN_DIRECT_CHANNEL_BUFFER_SIZE) {
567                 throw new IllegalArgumentException(
568                         "Size of MemoryFile has to be greater than "
569                         + MIN_DIRECT_CHANNEL_BUFFER_SIZE);
570             }
571 
572             size = memoryFile.length();
573             id = nativeCreateDirectChannel(
574                     mNativeInstance, size, SensorDirectChannel.TYPE_MEMORY_FILE, fd, null);
575             if (id <= 0) {
576                 throw new UncheckedIOException(
577                         new IOException("create MemoryFile direct channel failed " + id));
578             }
579             type = SensorDirectChannel.TYPE_MEMORY_FILE;
580         } else if (hardwareBuffer != null) {
581             if (hardwareBuffer.getFormat() != HardwareBuffer.BLOB) {
582                 throw new IllegalArgumentException("Format of HardwareBuffer must be BLOB");
583             }
584             if (hardwareBuffer.getHeight() != 1) {
585                 throw new IllegalArgumentException("Height of HardwareBuffer must be 1");
586             }
587             if (hardwareBuffer.getWidth() < MIN_DIRECT_CHANNEL_BUFFER_SIZE) {
588                 throw new IllegalArgumentException(
589                         "Width if HaradwareBuffer must be greater than "
590                         + MIN_DIRECT_CHANNEL_BUFFER_SIZE);
591             }
592             if ((hardwareBuffer.getUsage() & HardwareBuffer.USAGE_SENSOR_DIRECT_DATA) == 0) {
593                 throw new IllegalArgumentException(
594                         "HardwareBuffer must set usage flag USAGE_SENSOR_DIRECT_DATA");
595             }
596             size = hardwareBuffer.getWidth();
597             id = nativeCreateDirectChannel(
598                     mNativeInstance, size, SensorDirectChannel.TYPE_HARDWARE_BUFFER,
599                     -1, hardwareBuffer);
600             if (id <= 0) {
601                 throw new UncheckedIOException(
602                         new IOException("create HardwareBuffer direct channel failed " + id));
603             }
604             type = SensorDirectChannel.TYPE_HARDWARE_BUFFER;
605         } else {
606             throw new NullPointerException("shared memory object cannot be null");
607         }
608         return new SensorDirectChannel(this, id, type, size);
609     }
610 
611     /** @hide */
destroyDirectChannelImpl(SensorDirectChannel channel)612     protected void destroyDirectChannelImpl(SensorDirectChannel channel) {
613         if (channel != null) {
614             nativeDestroyDirectChannel(mNativeInstance, channel.getNativeHandle());
615         }
616     }
617 
618     /*
619      * BaseEventQueue is the communication channel with the sensor service,
620      * SensorEventQueue, TriggerEventQueue are subclases and there is one-to-one mapping between
621      * the queues and the listeners. InjectEventQueue is also a sub-class which is a special case
622      * where data is being injected into the sensor HAL through the sensor service. It is not
623      * associated with any listener and there is one InjectEventQueue associated with a
624      * SensorManager instance.
625      */
626     private static abstract class BaseEventQueue {
nativeInitBaseEventQueue(long nativeManager, WeakReference<BaseEventQueue> eventQWeak, MessageQueue msgQ, String packageName, int mode, String opPackageName)627         private static native long nativeInitBaseEventQueue(long nativeManager,
628                 WeakReference<BaseEventQueue> eventQWeak, MessageQueue msgQ,
629                 String packageName, int mode, String opPackageName);
nativeEnableSensor(long eventQ, int handle, int rateUs, int maxBatchReportLatencyUs)630         private static native int nativeEnableSensor(long eventQ, int handle, int rateUs,
631                 int maxBatchReportLatencyUs);
nativeDisableSensor(long eventQ, int handle)632         private static native int nativeDisableSensor(long eventQ, int handle);
nativeDestroySensorEventQueue(long eventQ)633         private static native void nativeDestroySensorEventQueue(long eventQ);
nativeFlushSensor(long eventQ)634         private static native int nativeFlushSensor(long eventQ);
nativeInjectSensorData(long eventQ, int handle, float[] values,int accuracy, long timestamp)635         private static native int nativeInjectSensorData(long eventQ, int handle,
636                 float[] values,int accuracy, long timestamp);
637 
638         private long nSensorEventQueue;
639         private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();
640         protected final SparseIntArray mSensorAccuracies = new SparseIntArray();
641         private final CloseGuard mCloseGuard = CloseGuard.get();
642         protected final SystemSensorManager mManager;
643 
644         protected static final int OPERATING_MODE_NORMAL = 0;
645         protected static final int OPERATING_MODE_DATA_INJECTION = 1;
646 
BaseEventQueue(Looper looper, SystemSensorManager manager, int mode, String packageName)647         BaseEventQueue(Looper looper, SystemSensorManager manager, int mode, String packageName) {
648             if (packageName == null) packageName = "";
649             nSensorEventQueue = nativeInitBaseEventQueue(manager.mNativeInstance,
650                     new WeakReference<>(this), looper.getQueue(),
651                     packageName, mode, manager.mContext.getOpPackageName());
652             mCloseGuard.open("dispose");
653             mManager = manager;
654         }
655 
dispose()656         public void dispose() {
657             dispose(false);
658         }
659 
addSensor( Sensor sensor, int delayUs, int maxBatchReportLatencyUs)660         public boolean addSensor(
661                 Sensor sensor, int delayUs, int maxBatchReportLatencyUs) {
662             // Check if already present.
663             int handle = sensor.getHandle();
664             if (mActiveSensors.get(handle)) return false;
665 
666             // Get ready to receive events before calling enable.
667             mActiveSensors.put(handle, true);
668             addSensorEvent(sensor);
669             if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs) != 0) {
670                 // Try continuous mode if batching fails.
671                 if (maxBatchReportLatencyUs == 0 ||
672                     maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0) != 0) {
673                   removeSensor(sensor, false);
674                   return false;
675                 }
676             }
677             return true;
678         }
679 
removeAllSensors()680         public boolean removeAllSensors() {
681             for (int i=0 ; i<mActiveSensors.size(); i++) {
682                 if (mActiveSensors.valueAt(i) == true) {
683                     int handle = mActiveSensors.keyAt(i);
684                     Sensor sensor = mManager.mHandleToSensor.get(handle);
685                     if (sensor != null) {
686                         disableSensor(sensor);
687                         mActiveSensors.put(handle, false);
688                         removeSensorEvent(sensor);
689                     } else {
690                         // sensor just disconnected -- just ignore.
691                     }
692                 }
693             }
694             return true;
695         }
696 
removeSensor(Sensor sensor, boolean disable)697         public boolean removeSensor(Sensor sensor, boolean disable) {
698             final int handle = sensor.getHandle();
699             if (mActiveSensors.get(handle)) {
700                 if (disable) disableSensor(sensor);
701                 mActiveSensors.put(sensor.getHandle(), false);
702                 removeSensorEvent(sensor);
703                 return true;
704             }
705             return false;
706         }
707 
flush()708         public int flush() {
709             if (nSensorEventQueue == 0) throw new NullPointerException();
710             return nativeFlushSensor(nSensorEventQueue);
711         }
712 
hasSensors()713         public boolean hasSensors() {
714             // no more sensors are set
715             return mActiveSensors.indexOfValue(true) >= 0;
716         }
717 
718         @Override
finalize()719         protected void finalize() throws Throwable {
720             try {
721                 dispose(true);
722             } finally {
723                 super.finalize();
724             }
725         }
726 
dispose(boolean finalized)727         private void dispose(boolean finalized) {
728             if (mCloseGuard != null) {
729                 if (finalized) {
730                     mCloseGuard.warnIfOpen();
731                 }
732                 mCloseGuard.close();
733             }
734             if (nSensorEventQueue != 0) {
735                 nativeDestroySensorEventQueue(nSensorEventQueue);
736                 nSensorEventQueue = 0;
737             }
738         }
739 
enableSensor( Sensor sensor, int rateUs, int maxBatchReportLatencyUs)740         private int enableSensor(
741                 Sensor sensor, int rateUs, int maxBatchReportLatencyUs) {
742             if (nSensorEventQueue == 0) throw new NullPointerException();
743             if (sensor == null) throw new NullPointerException();
744             return nativeEnableSensor(nSensorEventQueue, sensor.getHandle(), rateUs,
745                     maxBatchReportLatencyUs);
746         }
747 
injectSensorDataBase(int handle, float[] values, int accuracy, long timestamp)748         protected int injectSensorDataBase(int handle, float[] values, int accuracy,
749                                            long timestamp) {
750             return nativeInjectSensorData(nSensorEventQueue, handle, values, accuracy, timestamp);
751         }
752 
disableSensor(Sensor sensor)753         private int disableSensor(Sensor sensor) {
754             if (nSensorEventQueue == 0) throw new NullPointerException();
755             if (sensor == null) throw new NullPointerException();
756             return nativeDisableSensor(nSensorEventQueue, sensor.getHandle());
757         }
dispatchSensorEvent(int handle, float[] values, int accuracy, long timestamp)758         protected abstract void dispatchSensorEvent(int handle, float[] values, int accuracy,
759                 long timestamp);
dispatchFlushCompleteEvent(int handle)760         protected abstract void dispatchFlushCompleteEvent(int handle);
761 
dispatchAdditionalInfoEvent( int handle, int type, int serial, float[] floatValues, int[] intValues)762         protected void dispatchAdditionalInfoEvent(
763                 int handle, int type, int serial, float[] floatValues, int[] intValues) {
764             // default implementation is do nothing
765         }
766 
addSensorEvent(Sensor sensor)767         protected abstract void addSensorEvent(Sensor sensor);
removeSensorEvent(Sensor sensor)768         protected abstract void removeSensorEvent(Sensor sensor);
769     }
770 
771     static final class SensorEventQueue extends BaseEventQueue {
772         private final SensorEventListener mListener;
773         private final SparseArray<SensorEvent> mSensorsEvents = new SparseArray<SensorEvent>();
774 
SensorEventQueue(SensorEventListener listener, Looper looper, SystemSensorManager manager, String packageName)775         public SensorEventQueue(SensorEventListener listener, Looper looper,
776                 SystemSensorManager manager, String packageName) {
777             super(looper, manager, OPERATING_MODE_NORMAL, packageName);
778             mListener = listener;
779         }
780 
781         @Override
addSensorEvent(Sensor sensor)782         public void addSensorEvent(Sensor sensor) {
783             SensorEvent t = new SensorEvent(Sensor.getMaxLengthValuesArray(sensor,
784                     mManager.mTargetSdkLevel));
785             synchronized (mSensorsEvents) {
786                 mSensorsEvents.put(sensor.getHandle(), t);
787             }
788         }
789 
790         @Override
removeSensorEvent(Sensor sensor)791         public void removeSensorEvent(Sensor sensor) {
792             synchronized (mSensorsEvents) {
793                 mSensorsEvents.delete(sensor.getHandle());
794             }
795         }
796 
797         // Called from native code.
798         @SuppressWarnings("unused")
799         @Override
dispatchSensorEvent(int handle, float[] values, int inAccuracy, long timestamp)800         protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,
801                 long timestamp) {
802             final Sensor sensor = mManager.mHandleToSensor.get(handle);
803             if (sensor == null) {
804                 // sensor disconnected
805                 return;
806             }
807 
808             SensorEvent t = null;
809             synchronized (mSensorsEvents) {
810                 t = mSensorsEvents.get(handle);
811             }
812 
813             if (t == null) {
814                 // This may happen if the client has unregistered and there are pending events in
815                 // the queue waiting to be delivered. Ignore.
816                 return;
817             }
818             // Copy from the values array.
819             System.arraycopy(values, 0, t.values, 0, t.values.length);
820             t.timestamp = timestamp;
821             t.accuracy = inAccuracy;
822             t.sensor = sensor;
823 
824             // call onAccuracyChanged() only if the value changes
825             final int accuracy = mSensorAccuracies.get(handle);
826             if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
827                 mSensorAccuracies.put(handle, t.accuracy);
828                 mListener.onAccuracyChanged(t.sensor, t.accuracy);
829             }
830             mListener.onSensorChanged(t);
831         }
832 
833         // Called from native code.
834         @SuppressWarnings("unused")
835         @Override
dispatchFlushCompleteEvent(int handle)836         protected void dispatchFlushCompleteEvent(int handle) {
837             if (mListener instanceof SensorEventListener2) {
838                 final Sensor sensor = mManager.mHandleToSensor.get(handle);
839                 if (sensor == null) {
840                     // sensor disconnected
841                     return;
842                 }
843                 ((SensorEventListener2)mListener).onFlushCompleted(sensor);
844             }
845             return;
846         }
847 
848         // Called from native code.
849         @SuppressWarnings("unused")
850         @Override
dispatchAdditionalInfoEvent( int handle, int type, int serial, float[] floatValues, int[] intValues)851         protected void dispatchAdditionalInfoEvent(
852                 int handle, int type, int serial, float[] floatValues, int[] intValues) {
853             if (mListener instanceof SensorEventCallback) {
854                 final Sensor sensor = mManager.mHandleToSensor.get(handle);
855                 if (sensor == null) {
856                     // sensor disconnected
857                     return;
858                 }
859                 SensorAdditionalInfo info =
860                         new SensorAdditionalInfo(sensor, type, serial, intValues, floatValues);
861                 ((SensorEventCallback)mListener).onSensorAdditionalInfo(info);
862             }
863         }
864     }
865 
866     static final class TriggerEventQueue extends BaseEventQueue {
867         private final TriggerEventListener mListener;
868         private final SparseArray<TriggerEvent> mTriggerEvents = new SparseArray<TriggerEvent>();
869 
TriggerEventQueue(TriggerEventListener listener, Looper looper, SystemSensorManager manager, String packageName)870         public TriggerEventQueue(TriggerEventListener listener, Looper looper,
871                 SystemSensorManager manager, String packageName) {
872             super(looper, manager, OPERATING_MODE_NORMAL, packageName);
873             mListener = listener;
874         }
875 
876         @Override
addSensorEvent(Sensor sensor)877         public void addSensorEvent(Sensor sensor) {
878             TriggerEvent t = new TriggerEvent(Sensor.getMaxLengthValuesArray(sensor,
879                     mManager.mTargetSdkLevel));
880             synchronized (mTriggerEvents) {
881                 mTriggerEvents.put(sensor.getHandle(), t);
882             }
883         }
884 
885         @Override
removeSensorEvent(Sensor sensor)886         public void removeSensorEvent(Sensor sensor) {
887             synchronized (mTriggerEvents) {
888                 mTriggerEvents.delete(sensor.getHandle());
889             }
890         }
891 
892         // Called from native code.
893         @SuppressWarnings("unused")
894         @Override
dispatchSensorEvent(int handle, float[] values, int accuracy, long timestamp)895         protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
896                 long timestamp) {
897             final Sensor sensor = mManager.mHandleToSensor.get(handle);
898             if (sensor == null) {
899                 // sensor disconnected
900                 return;
901             }
902             TriggerEvent t = null;
903             synchronized (mTriggerEvents) {
904                 t = mTriggerEvents.get(handle);
905             }
906             if (t == null) {
907                 Log.e(TAG, "Error: Trigger Event is null for Sensor: " + sensor);
908                 return;
909             }
910 
911             // Copy from the values array.
912             System.arraycopy(values, 0, t.values, 0, t.values.length);
913             t.timestamp = timestamp;
914             t.sensor = sensor;
915 
916             // A trigger sensor is auto disabled. So just clean up and don't call native
917             // disable.
918             mManager.cancelTriggerSensorImpl(mListener, sensor, false);
919 
920             mListener.onTrigger(t);
921         }
922 
923         @SuppressWarnings("unused")
dispatchFlushCompleteEvent(int handle)924         protected void dispatchFlushCompleteEvent(int handle) {
925         }
926     }
927 
928     final class InjectEventQueue extends BaseEventQueue {
InjectEventQueue(Looper looper, SystemSensorManager manager, String packageName)929         public InjectEventQueue(Looper looper, SystemSensorManager manager, String packageName) {
930             super(looper, manager, OPERATING_MODE_DATA_INJECTION, packageName);
931         }
932 
injectSensorData(int handle, float[] values,int accuracy, long timestamp)933         int injectSensorData(int handle, float[] values,int accuracy, long timestamp) {
934              return injectSensorDataBase(handle, values, accuracy, timestamp);
935         }
936 
937         @SuppressWarnings("unused")
dispatchSensorEvent(int handle, float[] values, int accuracy, long timestamp)938         protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
939                 long timestamp) {
940         }
941 
942         @SuppressWarnings("unused")
dispatchFlushCompleteEvent(int handle)943         protected void dispatchFlushCompleteEvent(int handle) {
944 
945         }
946 
947         @SuppressWarnings("unused")
addSensorEvent(Sensor sensor)948         protected void addSensorEvent(Sensor sensor) {
949 
950         }
951 
952         @SuppressWarnings("unused")
removeSensorEvent(Sensor sensor)953         protected void removeSensorEvent(Sensor sensor) {
954 
955         }
956     }
957 
setOperationParameterImpl(SensorAdditionalInfo parameter)958     protected boolean setOperationParameterImpl(SensorAdditionalInfo parameter) {
959         return nativeSetOperationParameter(
960                 mNativeInstance, parameter.type, parameter.floatValues, parameter.intValues) == 0;
961     }
962 }
963