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