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