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