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 static android.view.Display.DEFAULT_DISPLAY; 20 21 import android.os.RemoteException; 22 import android.os.ServiceManager; 23 import android.view.IRotationWatcher; 24 import android.view.IWindowManager; 25 import android.view.Surface; 26 27 import java.util.HashMap; 28 import java.util.List; 29 30 /** 31 * Helper class for implementing the legacy sensor manager API. 32 * @hide 33 */ 34 @SuppressWarnings("deprecation") 35 final class LegacySensorManager { 36 private static boolean sInitialized; 37 private static IWindowManager sWindowManager; 38 private static int sRotation = Surface.ROTATION_0; 39 40 private final SensorManager mSensorManager; 41 42 // List of legacy listeners. Guarded by mLegacyListenersMap. 43 private final HashMap<SensorListener, LegacyListener> mLegacyListenersMap = 44 new HashMap<SensorListener, LegacyListener>(); 45 LegacySensorManager(SensorManager sensorManager)46 public LegacySensorManager(SensorManager sensorManager) { 47 mSensorManager = sensorManager; 48 49 synchronized (SensorManager.class) { 50 if (!sInitialized) { 51 sWindowManager = IWindowManager.Stub.asInterface( 52 ServiceManager.getService("window")); 53 if (sWindowManager != null) { 54 // if it's null we're running in the system process 55 // which won't get the rotated values 56 try { 57 sRotation = sWindowManager.watchRotation( 58 new IRotationWatcher.Stub() { 59 public void onRotationChanged(int rotation) { 60 LegacySensorManager.onRotationChanged(rotation); 61 } 62 }, DEFAULT_DISPLAY); 63 } catch (RemoteException e) { 64 } 65 } 66 } 67 } 68 } 69 getSensors()70 public int getSensors() { 71 int result = 0; 72 final List<Sensor> fullList = mSensorManager.getFullSensorList(); 73 for (Sensor i : fullList) { 74 switch (i.getType()) { 75 case Sensor.TYPE_ACCELEROMETER: 76 result |= SensorManager.SENSOR_ACCELEROMETER; 77 break; 78 case Sensor.TYPE_MAGNETIC_FIELD: 79 result |= SensorManager.SENSOR_MAGNETIC_FIELD; 80 break; 81 case Sensor.TYPE_ORIENTATION: 82 result |= SensorManager.SENSOR_ORIENTATION 83 | SensorManager.SENSOR_ORIENTATION_RAW; 84 break; 85 } 86 } 87 return result; 88 } 89 registerListener(SensorListener listener, int sensors, int rate)90 public boolean registerListener(SensorListener listener, int sensors, int rate) { 91 if (listener == null) { 92 return false; 93 } 94 boolean result = false; 95 result = registerLegacyListener(SensorManager.SENSOR_ACCELEROMETER, 96 Sensor.TYPE_ACCELEROMETER, listener, sensors, rate) || result; 97 result = registerLegacyListener(SensorManager.SENSOR_MAGNETIC_FIELD, 98 Sensor.TYPE_MAGNETIC_FIELD, listener, sensors, rate) || result; 99 result = registerLegacyListener(SensorManager.SENSOR_ORIENTATION_RAW, 100 Sensor.TYPE_ORIENTATION, listener, sensors, rate) || result; 101 result = registerLegacyListener(SensorManager.SENSOR_ORIENTATION, 102 Sensor.TYPE_ORIENTATION, listener, sensors, rate) || result; 103 result = registerLegacyListener(SensorManager.SENSOR_TEMPERATURE, 104 Sensor.TYPE_TEMPERATURE, listener, sensors, rate) || result; 105 return result; 106 } 107 registerLegacyListener(int legacyType, int type, SensorListener listener, int sensors, int rate)108 private boolean registerLegacyListener(int legacyType, int type, 109 SensorListener listener, int sensors, int rate) { 110 boolean result = false; 111 // Are we activating this legacy sensor? 112 if ((sensors & legacyType) != 0) { 113 // if so, find a suitable Sensor 114 Sensor sensor = mSensorManager.getDefaultSensor(type); 115 if (sensor != null) { 116 // We do all of this work holding the legacy listener lock to ensure 117 // that the invariants around listeners are maintained. This is safe 118 // because neither registerLegacyListener nor unregisterLegacyListener 119 // are called reentrantly while sensors are being registered or unregistered. 120 synchronized (mLegacyListenersMap) { 121 // If we don't already have one, create a LegacyListener 122 // to wrap this listener and process the events as 123 // they are expected by legacy apps. 124 LegacyListener legacyListener = mLegacyListenersMap.get(listener); 125 if (legacyListener == null) { 126 // we didn't find a LegacyListener for this client, 127 // create one, and put it in our list. 128 legacyListener = new LegacyListener(listener); 129 mLegacyListenersMap.put(listener, legacyListener); 130 } 131 132 // register this legacy sensor with this legacy listener 133 if (legacyListener.registerSensor(legacyType)) { 134 // and finally, register the legacy listener with the new apis 135 result = mSensorManager.registerListener(legacyListener, sensor, rate); 136 } else { 137 result = true; // sensor already enabled 138 } 139 } 140 } 141 } 142 return result; 143 } 144 unregisterListener(SensorListener listener, int sensors)145 public void unregisterListener(SensorListener listener, int sensors) { 146 if (listener == null) { 147 return; 148 } 149 unregisterLegacyListener(SensorManager.SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER, 150 listener, sensors); 151 unregisterLegacyListener(SensorManager.SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD, 152 listener, sensors); 153 unregisterLegacyListener(SensorManager.SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION, 154 listener, sensors); 155 unregisterLegacyListener(SensorManager.SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION, 156 listener, sensors); 157 unregisterLegacyListener(SensorManager.SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE, 158 listener, sensors); 159 } 160 unregisterLegacyListener(int legacyType, int type, SensorListener listener, int sensors)161 private void unregisterLegacyListener(int legacyType, int type, 162 SensorListener listener, int sensors) { 163 // Are we deactivating this legacy sensor? 164 if ((sensors & legacyType) != 0) { 165 // if so, find the corresponding Sensor 166 Sensor sensor = mSensorManager.getDefaultSensor(type); 167 if (sensor != null) { 168 // We do all of this work holding the legacy listener lock to ensure 169 // that the invariants around listeners are maintained. This is safe 170 // because neither registerLegacyListener nor unregisterLegacyListener 171 // are called re-entrantly while sensors are being registered or unregistered. 172 synchronized (mLegacyListenersMap) { 173 // do we know about this listener? 174 LegacyListener legacyListener = mLegacyListenersMap.get(listener); 175 if (legacyListener != null) { 176 // unregister this legacy sensor and if we don't 177 // need the corresponding Sensor, unregister it too 178 if (legacyListener.unregisterSensor(legacyType)) { 179 // corresponding sensor not needed, unregister 180 mSensorManager.unregisterListener(legacyListener, sensor); 181 182 // finally check if we still need the legacyListener 183 // in our mapping, if not, get rid of it too. 184 if (!legacyListener.hasSensors()) { 185 mLegacyListenersMap.remove(listener); 186 } 187 } 188 } 189 } 190 } 191 } 192 } 193 onRotationChanged(int rotation)194 static void onRotationChanged(int rotation) { 195 synchronized (SensorManager.class) { 196 sRotation = rotation; 197 } 198 } 199 getRotation()200 static int getRotation() { 201 synchronized (SensorManager.class) { 202 return sRotation; 203 } 204 } 205 206 private static final class LegacyListener implements SensorEventListener { 207 private float[] mValues = new float[6]; 208 private SensorListener mTarget; 209 private int mSensors; 210 private final LmsFilter mYawfilter = new LmsFilter(); 211 LegacyListener(SensorListener target)212 LegacyListener(SensorListener target) { 213 mTarget = target; 214 mSensors = 0; 215 } 216 registerSensor(int legacyType)217 boolean registerSensor(int legacyType) { 218 if ((mSensors & legacyType) != 0) { 219 return false; 220 } 221 boolean alreadyHasOrientationSensor = hasOrientationSensor(mSensors); 222 mSensors |= legacyType; 223 if (alreadyHasOrientationSensor && hasOrientationSensor(legacyType)) { 224 return false; // don't need to re-register the orientation sensor 225 } 226 return true; 227 } 228 unregisterSensor(int legacyType)229 boolean unregisterSensor(int legacyType) { 230 if ((mSensors & legacyType) == 0) { 231 return false; 232 } 233 mSensors &= ~legacyType; 234 if (hasOrientationSensor(legacyType) && hasOrientationSensor(mSensors)) { 235 return false; // can't unregister the orientation sensor just yet 236 } 237 return true; 238 } 239 hasSensors()240 boolean hasSensors() { 241 return mSensors != 0; 242 } 243 hasOrientationSensor(int sensors)244 private static boolean hasOrientationSensor(int sensors) { 245 return (sensors & (SensorManager.SENSOR_ORIENTATION 246 | SensorManager.SENSOR_ORIENTATION_RAW)) != 0; 247 } 248 onAccuracyChanged(Sensor sensor, int accuracy)249 public void onAccuracyChanged(Sensor sensor, int accuracy) { 250 try { 251 mTarget.onAccuracyChanged(getLegacySensorType(sensor.getType()), accuracy); 252 } catch (AbstractMethodError e) { 253 // old app that doesn't implement this method 254 // just ignore it. 255 } 256 } 257 onSensorChanged(SensorEvent event)258 public void onSensorChanged(SensorEvent event) { 259 final float[] v = mValues; 260 v[0] = event.values[0]; 261 v[1] = event.values[1]; 262 v[2] = event.values[2]; 263 int type = event.sensor.getType(); 264 int legacyType = getLegacySensorType(type); 265 mapSensorDataToWindow(legacyType, v, LegacySensorManager.getRotation()); 266 if (type == Sensor.TYPE_ORIENTATION) { 267 if ((mSensors & SensorManager.SENSOR_ORIENTATION_RAW) != 0) { 268 mTarget.onSensorChanged(SensorManager.SENSOR_ORIENTATION_RAW, v); 269 } 270 if ((mSensors & SensorManager.SENSOR_ORIENTATION) != 0) { 271 v[0] = mYawfilter.filter(event.timestamp, v[0]); 272 mTarget.onSensorChanged(SensorManager.SENSOR_ORIENTATION, v); 273 } 274 } else { 275 mTarget.onSensorChanged(legacyType, v); 276 } 277 } 278 279 /* 280 * Helper function to convert the specified sensor's data to the windows's 281 * coordinate space from the device's coordinate space. 282 * 283 * output: 3,4,5: values in the old API format 284 * 0,1,2: transformed values in the old API format 285 * 286 */ mapSensorDataToWindow(int sensor, float[] values, int orientation)287 private void mapSensorDataToWindow(int sensor, 288 float[] values, int orientation) { 289 float x = values[0]; 290 float y = values[1]; 291 float z = values[2]; 292 293 switch (sensor) { 294 case SensorManager.SENSOR_ORIENTATION: 295 case SensorManager.SENSOR_ORIENTATION_RAW: 296 z = -z; 297 break; 298 case SensorManager.SENSOR_ACCELEROMETER: 299 x = -x; 300 y = -y; 301 z = -z; 302 break; 303 case SensorManager.SENSOR_MAGNETIC_FIELD: 304 x = -x; 305 y = -y; 306 break; 307 } 308 values[0] = x; 309 values[1] = y; 310 values[2] = z; 311 values[3] = x; 312 values[4] = y; 313 values[5] = z; 314 315 if ((orientation & Surface.ROTATION_90) != 0) { 316 // handles 90 and 270 rotation 317 switch (sensor) { 318 case SensorManager.SENSOR_ACCELEROMETER: 319 case SensorManager.SENSOR_MAGNETIC_FIELD: 320 values[0] = -y; 321 values[1] = x; 322 values[2] = z; 323 break; 324 case SensorManager.SENSOR_ORIENTATION: 325 case SensorManager.SENSOR_ORIENTATION_RAW: 326 values[0] = x + ((x < 270) ? 90 : -270); 327 values[1] = z; 328 values[2] = y; 329 break; 330 } 331 } 332 if ((orientation & Surface.ROTATION_180) != 0) { 333 x = values[0]; 334 y = values[1]; 335 z = values[2]; 336 // handles 180 (flip) and 270 (flip + 90) rotation 337 switch (sensor) { 338 case SensorManager.SENSOR_ACCELEROMETER: 339 case SensorManager.SENSOR_MAGNETIC_FIELD: 340 values[0] = -x; 341 values[1] = -y; 342 values[2] = z; 343 break; 344 case SensorManager.SENSOR_ORIENTATION: 345 case SensorManager.SENSOR_ORIENTATION_RAW: 346 values[0] = (x >= 180) ? (x - 180) : (x + 180); 347 values[1] = -y; 348 values[2] = -z; 349 break; 350 } 351 } 352 } 353 getLegacySensorType(int type)354 private static int getLegacySensorType(int type) { 355 switch (type) { 356 case Sensor.TYPE_ACCELEROMETER: 357 return SensorManager.SENSOR_ACCELEROMETER; 358 case Sensor.TYPE_MAGNETIC_FIELD: 359 return SensorManager.SENSOR_MAGNETIC_FIELD; 360 case Sensor.TYPE_ORIENTATION: 361 return SensorManager.SENSOR_ORIENTATION_RAW; 362 case Sensor.TYPE_TEMPERATURE: 363 return SensorManager.SENSOR_TEMPERATURE; 364 } 365 return 0; 366 } 367 } 368 369 private static final class LmsFilter { 370 private static final int SENSORS_RATE_MS = 20; 371 private static final int COUNT = 12; 372 private static final float PREDICTION_RATIO = 1.0f / 3.0f; 373 private static final float PREDICTION_TIME = 374 (SENSORS_RATE_MS * COUNT / 1000.0f) * PREDICTION_RATIO; 375 private float[] mV = new float[COUNT * 2]; 376 private long[] mT = new long[COUNT * 2]; 377 private int mIndex; 378 LmsFilter()379 public LmsFilter() { 380 mIndex = COUNT; 381 } 382 filter(long time, float in)383 public float filter(long time, float in) { 384 float v = in; 385 final float ns = 1.0f / 1000000000.0f; 386 float v1 = mV[mIndex]; 387 if ((v - v1) > 180) { 388 v -= 360; 389 } else if ((v1 - v) > 180) { 390 v += 360; 391 } 392 /* Manage the circular buffer, we write the data twice spaced 393 * by COUNT values, so that we don't have to copy the array 394 * when it's full 395 */ 396 mIndex++; 397 if (mIndex >= COUNT * 2) { 398 mIndex = COUNT; 399 } 400 mV[mIndex] = v; 401 mT[mIndex] = time; 402 mV[mIndex - COUNT] = v; 403 mT[mIndex - COUNT] = time; 404 405 float A, B, C, D, E; 406 float a, b; 407 int i; 408 409 A = B = C = D = E = 0; 410 for (i = 0; i < COUNT - 1; i++) { 411 final int j = mIndex - 1 - i; 412 final float Z = mV[j]; 413 final float T = (mT[j] / 2 + mT[j + 1] / 2 - time) * ns; 414 float dT = (mT[j] - mT[j + 1]) * ns; 415 dT *= dT; 416 A += Z * dT; 417 B += T * (T * dT); 418 C += (T * dT); 419 D += Z * (T * dT); 420 E += dT; 421 } 422 b = (A * B + C * D) / (E * B + C * C); 423 a = (E * b - A) / C; 424 float f = b + PREDICTION_TIME * a; 425 426 // Normalize 427 f *= (1.0f / 360.0f); 428 if (((f >= 0) ? f : -f) >= 0.5f) { 429 f = f - (float) Math.ceil(f + 0.5f) + 1.0f; 430 } 431 if (f < 0) { 432 f += 1.0f; 433 } 434 f *= 360.0f; 435 return f; 436 } 437 } 438 } 439