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