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