blob: 098121dfeffd5974a9f2477eb3c086ba0530c676 [file] [log] [blame]
Jeff Brown4481d9c2012-04-16 16:14:44 -07001/*
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
17package android.hardware;
18
Andrii Kulian35fa3c22017-03-11 09:37:28 -080019import static android.view.Display.DEFAULT_DISPLAY;
20
Jeff Brown4481d9c2012-04-16 16:14:44 -070021import android.os.RemoteException;
22import android.os.ServiceManager;
23import android.view.IRotationWatcher;
24import android.view.IWindowManager;
25import android.view.Surface;
26
27import java.util.HashMap;
28import java.util.List;
29
30/**
31 * Helper class for implementing the legacy sensor manager API.
32 * @hide
33 */
34@SuppressWarnings("deprecation")
35final 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
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 }
Andrii Kulian35fa3c22017-03-11 09:37:28 -080062 }, DEFAULT_DISPLAY);
Jeff Brown4481d9c2012-04-16 16:14:44 -070063 } catch (RemoteException e) {
64 }
65 }
66 }
67 }
68 }
69
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
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
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
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
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
194 static void onRotationChanged(int rotation) {
195 synchronized (SensorManager.class) {
196 sRotation = rotation;
197 }
198 }
199
200 static int getRotation() {
201 synchronized (SensorManager.class) {
202 return sRotation;
203 }
204 }
205
206 private static final class LegacyListener implements SensorEventListener {
Peng Xu62f2c872017-09-22 11:50:33 -0700207 private float[] mValues = new float[6];
Jeff Brown4481d9c2012-04-16 16:14:44 -0700208 private SensorListener mTarget;
209 private int mSensors;
210 private final LmsFilter mYawfilter = new LmsFilter();
211
212 LegacyListener(SensorListener target) {
213 mTarget = target;
214 mSensors = 0;
215 }
216
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
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
240 boolean hasSensors() {
241 return mSensors != 0;
242 }
243
244 private static boolean hasOrientationSensor(int sensors) {
245 return (sensors & (SensorManager.SENSOR_ORIENTATION
246 | SensorManager.SENSOR_ORIENTATION_RAW)) != 0;
247 }
248
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
258 public void onSensorChanged(SensorEvent event) {
Peng Xu62f2c872017-09-22 11:50:33 -0700259 final float[] v = mValues;
Jeff Brown4481d9c2012-04-16 16:14:44 -0700260 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) {
Peng Xu62f2c872017-09-22 11:50:33 -0700267 if ((mSensors & SensorManager.SENSOR_ORIENTATION_RAW) != 0) {
Jeff Brown4481d9c2012-04-16 16:14:44 -0700268 mTarget.onSensorChanged(SensorManager.SENSOR_ORIENTATION_RAW, v);
269 }
Peng Xu62f2c872017-09-22 11:50:33 -0700270 if ((mSensors & SensorManager.SENSOR_ORIENTATION) != 0) {
Jeff Brown4481d9c2012-04-16 16:14:44 -0700271 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 */
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:
Peng Xu62f2c872017-09-22 11:50:33 -0700320 values[0] = -y;
Jeff Brown4481d9c2012-04-16 16:14:44 -0700321 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:
Peng Xu62f2c872017-09-22 11:50:33 -0700340 values[0] = -x;
341 values[1] = -y;
Jeff Brown4481d9c2012-04-16 16:14:44 -0700342 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);
Peng Xu62f2c872017-09-22 11:50:33 -0700347 values[1] = -y;
348 values[2] = -z;
Jeff Brown4481d9c2012-04-16 16:14:44 -0700349 break;
350 }
351 }
352 }
353
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;
Peng Xu62f2c872017-09-22 11:50:33 -0700372 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];
Jeff Brown4481d9c2012-04-16 16:14:44 -0700377 private int mIndex;
378
379 public LmsFilter() {
380 mIndex = COUNT;
381 }
382
383 public float filter(long time, float in) {
384 float v = in;
385 final float ns = 1.0f / 1000000000.0f;
Jeff Brown4481d9c2012-04-16 16:14:44 -0700386 float v1 = mV[mIndex];
Peng Xu62f2c872017-09-22 11:50:33 -0700387 if ((v - v1) > 180) {
Jeff Brown4481d9c2012-04-16 16:14:44 -0700388 v -= 360;
Peng Xu62f2c872017-09-22 11:50:33 -0700389 } else if ((v1 - v) > 180) {
Jeff Brown4481d9c2012-04-16 16:14:44 -0700390 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++;
Peng Xu62f2c872017-09-22 11:50:33 -0700397 if (mIndex >= COUNT * 2) {
Jeff Brown4481d9c2012-04-16 16:14:44 -0700398 mIndex = COUNT;
Peng Xu62f2c872017-09-22 11:50:33 -0700399 }
Jeff Brown4481d9c2012-04-16 16:14:44 -0700400 mV[mIndex] = v;
Mathias Agopian278a9662012-10-29 16:03:46 -0700401 mT[mIndex] = time;
Peng Xu62f2c872017-09-22 11:50:33 -0700402 mV[mIndex - COUNT] = v;
403 mT[mIndex - COUNT] = time;
Jeff Brown4481d9c2012-04-16 16:14:44 -0700404
405 float A, B, C, D, E;
406 float a, b;
407 int i;
408
409 A = B = C = D = E = 0;
Peng Xu62f2c872017-09-22 11:50:33 -0700410 for (i = 0; i < COUNT - 1; i++) {
Jeff Brown4481d9c2012-04-16 16:14:44 -0700411 final int j = mIndex - 1 - i;
412 final float Z = mV[j];
Peng Xu62f2c872017-09-22 11:50:33 -0700413 final float T = (mT[j] / 2 + mT[j + 1] / 2 - time) * ns;
414 float dT = (mT[j] - mT[j + 1]) * ns;
Jeff Brown4481d9c2012-04-16 16:14:44 -0700415 dT *= dT;
Peng Xu62f2c872017-09-22 11:50:33 -0700416 A += Z * dT;
417 B += T * (T * dT);
418 C += (T * dT);
419 D += Z * (T * dT);
Jeff Brown4481d9c2012-04-16 16:14:44 -0700420 E += dT;
421 }
Peng Xu62f2c872017-09-22 11:50:33 -0700422 b = (A * B + C * D) / (E * B + C * C);
423 a = (E * b - A) / C;
424 float f = b + PREDICTION_TIME * a;
Jeff Brown4481d9c2012-04-16 16:14:44 -0700425
426 // Normalize
427 f *= (1.0f / 360.0f);
Peng Xu62f2c872017-09-22 11:50:33 -0700428 if (((f >= 0) ? f : -f) >= 0.5f) {
429 f = f - (float) Math.ceil(f + 0.5f) + 1.0f;
430 }
431 if (f < 0) {
Jeff Brown4481d9c2012-04-16 16:14:44 -0700432 f += 1.0f;
Peng Xu62f2c872017-09-22 11:50:33 -0700433 }
Jeff Brown4481d9c2012-04-16 16:14:44 -0700434 f *= 360.0f;
435 return f;
436 }
437 }
438}