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