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