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.os.Looper; 20 import android.os.Process; 21 import android.os.Handler; 22 import android.os.Message; 23 import android.util.Log; 24 import android.util.SparseArray; 25 import android.util.SparseBooleanArray; 26 import android.util.SparseIntArray; 27 28 import java.util.ArrayList; 29 import java.util.List; 30 31 /** 32 * Sensor manager implementation that communicates with the built-in 33 * system sensors. 34 * 35 * @hide 36 */ 37 public class SystemSensorManager extends SensorManager { 38 private static final int SENSOR_DISABLE = -1; 39 private static boolean sSensorModuleInitialized = false; 40 private static ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>(); 41 /* The thread and the sensor list are global to the process 42 * but the actual thread is spawned on demand */ 43 private static SensorThread sSensorThread; 44 private static int sQueue; 45 46 // Used within this module from outside SensorManager, don't make private 47 static SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>(); 48 static final ArrayList<ListenerDelegate> sListeners = 49 new ArrayList<ListenerDelegate>(); 50 51 // Common pool of sensor events. 52 static SensorEventPool sPool; 53 54 // Looper associated with the context in which this instance was created. 55 final Looper mMainLooper; 56 57 /*-----------------------------------------------------------------------*/ 58 59 static private class SensorThread { 60 61 Thread mThread; 62 boolean mSensorsReady; 63 SensorThread()64 SensorThread() { 65 } 66 67 @Override finalize()68 protected void finalize() { 69 } 70 71 // must be called with sListeners lock startLocked()72 boolean startLocked() { 73 try { 74 if (mThread == null) { 75 mSensorsReady = false; 76 SensorThreadRunnable runnable = new SensorThreadRunnable(); 77 Thread thread = new Thread(runnable, SensorThread.class.getName()); 78 thread.start(); 79 synchronized (runnable) { 80 while (mSensorsReady == false) { 81 runnable.wait(); 82 } 83 } 84 mThread = thread; 85 } 86 } catch (InterruptedException e) { 87 } 88 return mThread == null ? false : true; 89 } 90 91 private class SensorThreadRunnable implements Runnable { SensorThreadRunnable()92 SensorThreadRunnable() { 93 } 94 open()95 private boolean open() { 96 // NOTE: this cannot synchronize on sListeners, since 97 // it's held in the main thread at least until we 98 // return from here. 99 sQueue = sensors_create_queue(); 100 return true; 101 } 102 run()103 public void run() { 104 //Log.d(TAG, "entering main sensor thread"); 105 final float[] values = new float[3]; 106 final int[] status = new int[1]; 107 final long timestamp[] = new long[1]; 108 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY); 109 110 if (!open()) { 111 return; 112 } 113 114 synchronized (this) { 115 // we've open the driver, we're ready to open the sensors 116 mSensorsReady = true; 117 this.notify(); 118 } 119 120 while (true) { 121 // wait for an event 122 final int sensor = sensors_data_poll(sQueue, values, status, timestamp); 123 124 int accuracy = status[0]; 125 synchronized (sListeners) { 126 if (sensor == -1 || sListeners.isEmpty()) { 127 // we lost the connection to the event stream. this happens 128 // when the last listener is removed or if there is an error 129 if (sensor == -1 && !sListeners.isEmpty()) { 130 // log a warning in case of abnormal termination 131 Log.e(TAG, "_sensors_data_poll() failed, we bail out: sensors=" + sensor); 132 } 133 // we have no more listeners or polling failed, terminate the thread 134 sensors_destroy_queue(sQueue); 135 sQueue = 0; 136 mThread = null; 137 break; 138 } 139 final Sensor sensorObject = sHandleToSensor.get(sensor); 140 if (sensorObject != null) { 141 // report the sensor event to all listeners that 142 // care about it. 143 final int size = sListeners.size(); 144 for (int i=0 ; i<size ; i++) { 145 ListenerDelegate listener = sListeners.get(i); 146 if (listener.hasSensor(sensorObject)) { 147 // this is asynchronous (okay to call 148 // with sListeners lock held). 149 listener.onSensorChangedLocked(sensorObject, 150 values, timestamp, accuracy); 151 } 152 } 153 } 154 } 155 } 156 //Log.d(TAG, "exiting main sensor thread"); 157 } 158 } 159 } 160 161 /*-----------------------------------------------------------------------*/ 162 163 private class ListenerDelegate { 164 private final SensorEventListener mSensorEventListener; 165 private final ArrayList<Sensor> mSensorList = new ArrayList<Sensor>(); 166 private final Handler mHandler; 167 public SparseBooleanArray mSensors = new SparseBooleanArray(); 168 public SparseBooleanArray mFirstEvent = new SparseBooleanArray(); 169 public SparseIntArray mSensorAccuracies = new SparseIntArray(); 170 ListenerDelegate(SensorEventListener listener, Sensor sensor, Handler handler)171 ListenerDelegate(SensorEventListener listener, Sensor sensor, Handler handler) { 172 mSensorEventListener = listener; 173 Looper looper = (handler != null) ? handler.getLooper() : mMainLooper; 174 // currently we create one Handler instance per listener, but we could 175 // have one per looper (we'd need to pass the ListenerDelegate 176 // instance to handleMessage and keep track of them separately). 177 mHandler = new Handler(looper) { 178 @Override 179 public void handleMessage(Message msg) { 180 final SensorEvent t = (SensorEvent)msg.obj; 181 final int handle = t.sensor.getHandle(); 182 183 switch (t.sensor.getType()) { 184 // Only report accuracy for sensors that support it. 185 case Sensor.TYPE_MAGNETIC_FIELD: 186 case Sensor.TYPE_ORIENTATION: 187 // call onAccuracyChanged() only if the value changes 188 final int accuracy = mSensorAccuracies.get(handle); 189 if ((t.accuracy >= 0) && (accuracy != t.accuracy)) { 190 mSensorAccuracies.put(handle, t.accuracy); 191 mSensorEventListener.onAccuracyChanged(t.sensor, t.accuracy); 192 } 193 break; 194 default: 195 // For other sensors, just report the accuracy once 196 if (mFirstEvent.get(handle) == false) { 197 mFirstEvent.put(handle, true); 198 mSensorEventListener.onAccuracyChanged( 199 t.sensor, SENSOR_STATUS_ACCURACY_HIGH); 200 } 201 break; 202 } 203 204 mSensorEventListener.onSensorChanged(t); 205 sPool.returnToPool(t); 206 } 207 }; 208 addSensor(sensor); 209 } 210 getListener()211 Object getListener() { 212 return mSensorEventListener; 213 } 214 addSensor(Sensor sensor)215 void addSensor(Sensor sensor) { 216 mSensors.put(sensor.getHandle(), true); 217 mSensorList.add(sensor); 218 } removeSensor(Sensor sensor)219 int removeSensor(Sensor sensor) { 220 mSensors.delete(sensor.getHandle()); 221 mSensorList.remove(sensor); 222 return mSensors.size(); 223 } hasSensor(Sensor sensor)224 boolean hasSensor(Sensor sensor) { 225 return mSensors.get(sensor.getHandle()); 226 } getSensors()227 List<Sensor> getSensors() { 228 return mSensorList; 229 } 230 onSensorChangedLocked(Sensor sensor, float[] values, long[] timestamp, int accuracy)231 void onSensorChangedLocked(Sensor sensor, float[] values, long[] timestamp, int accuracy) { 232 SensorEvent t = sPool.getFromPool(); 233 final float[] v = t.values; 234 v[0] = values[0]; 235 v[1] = values[1]; 236 v[2] = values[2]; 237 t.timestamp = timestamp[0]; 238 t.accuracy = accuracy; 239 t.sensor = sensor; 240 Message msg = Message.obtain(); 241 msg.what = 0; 242 msg.obj = t; 243 msg.setAsynchronous(true); 244 mHandler.sendMessage(msg); 245 } 246 } 247 248 /** 249 * {@hide} 250 */ SystemSensorManager(Looper mainLooper)251 public SystemSensorManager(Looper mainLooper) { 252 mMainLooper = mainLooper; 253 254 synchronized(sListeners) { 255 if (!sSensorModuleInitialized) { 256 sSensorModuleInitialized = true; 257 258 nativeClassInit(); 259 260 // initialize the sensor list 261 sensors_module_init(); 262 final ArrayList<Sensor> fullList = sFullSensorsList; 263 int i = 0; 264 do { 265 Sensor sensor = new Sensor(); 266 i = sensors_module_get_next_sensor(sensor, i); 267 268 if (i>=0) { 269 //Log.d(TAG, "found sensor: " + sensor.getName() + 270 // ", handle=" + sensor.getHandle()); 271 fullList.add(sensor); 272 sHandleToSensor.append(sensor.getHandle(), sensor); 273 } 274 } while (i>0); 275 276 sPool = new SensorEventPool( sFullSensorsList.size()*2 ); 277 sSensorThread = new SensorThread(); 278 } 279 } 280 } 281 282 /** @hide */ 283 @Override getFullSensorList()284 protected List<Sensor> getFullSensorList() { 285 return sFullSensorsList; 286 } 287 enableSensorLocked(Sensor sensor, int delay)288 private boolean enableSensorLocked(Sensor sensor, int delay) { 289 boolean result = false; 290 for (ListenerDelegate i : sListeners) { 291 if (i.hasSensor(sensor)) { 292 String name = sensor.getName(); 293 int handle = sensor.getHandle(); 294 result = sensors_enable_sensor(sQueue, name, handle, delay); 295 break; 296 } 297 } 298 return result; 299 } 300 disableSensorLocked(Sensor sensor)301 private boolean disableSensorLocked(Sensor sensor) { 302 for (ListenerDelegate i : sListeners) { 303 if (i.hasSensor(sensor)) { 304 // not an error, it's just that this sensor is still in use 305 return true; 306 } 307 } 308 String name = sensor.getName(); 309 int handle = sensor.getHandle(); 310 return sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE); 311 } 312 313 /** @hide */ 314 @Override registerListenerImpl(SensorEventListener listener, Sensor sensor, int delay, Handler handler)315 protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, 316 int delay, Handler handler) { 317 boolean result = true; 318 synchronized (sListeners) { 319 // look for this listener in our list 320 ListenerDelegate l = null; 321 for (ListenerDelegate i : sListeners) { 322 if (i.getListener() == listener) { 323 l = i; 324 break; 325 } 326 } 327 328 // if we don't find it, add it to the list 329 if (l == null) { 330 l = new ListenerDelegate(listener, sensor, handler); 331 sListeners.add(l); 332 // if the list is not empty, start our main thread 333 if (!sListeners.isEmpty()) { 334 if (sSensorThread.startLocked()) { 335 if (!enableSensorLocked(sensor, delay)) { 336 // oops. there was an error 337 sListeners.remove(l); 338 result = false; 339 } 340 } else { 341 // there was an error, remove the listener 342 sListeners.remove(l); 343 result = false; 344 } 345 } else { 346 // weird, we couldn't add the listener 347 result = false; 348 } 349 } else if (!l.hasSensor(sensor)) { 350 l.addSensor(sensor); 351 if (!enableSensorLocked(sensor, delay)) { 352 // oops. there was an error 353 l.removeSensor(sensor); 354 result = false; 355 } 356 } 357 } 358 359 return result; 360 } 361 362 /** @hide */ 363 @Override unregisterListenerImpl(SensorEventListener listener, Sensor sensor)364 protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) { 365 synchronized (sListeners) { 366 final int size = sListeners.size(); 367 for (int i=0 ; i<size ; i++) { 368 ListenerDelegate l = sListeners.get(i); 369 if (l.getListener() == listener) { 370 if (sensor == null) { 371 sListeners.remove(i); 372 // disable all sensors for this listener 373 for (Sensor s : l.getSensors()) { 374 disableSensorLocked(s); 375 } 376 } else if (l.removeSensor(sensor) == 0) { 377 // if we have no more sensors enabled on this listener, 378 // take it off the list. 379 sListeners.remove(i); 380 disableSensorLocked(sensor); 381 } 382 break; 383 } 384 } 385 } 386 } 387 nativeClassInit()388 private static native void nativeClassInit(); 389 sensors_module_init()390 private static native int sensors_module_init(); sensors_module_get_next_sensor(Sensor sensor, int next)391 private static native int sensors_module_get_next_sensor(Sensor sensor, int next); 392 393 // Used within this module from outside SensorManager, don't make private sensors_create_queue()394 static native int sensors_create_queue(); sensors_destroy_queue(int queue)395 static native void sensors_destroy_queue(int queue); sensors_enable_sensor(int queue, String name, int sensor, int enable)396 static native boolean sensors_enable_sensor(int queue, String name, int sensor, int enable); sensors_data_poll(int queue, float[] values, int[] status, long[] timestamp)397 static native int sensors_data_poll(int queue, float[] values, int[] status, long[] timestamp); 398 } 399