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