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