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