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