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