1 /* 2 * Copyright (C) 2015 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 com.android.camera.hardware; 18 19 import com.android.camera.debug.Log; 20 21 import android.hardware.Sensor; 22 import android.hardware.SensorEvent; 23 import android.hardware.SensorEventListener; 24 import android.hardware.SensorManager; 25 26 /** 27 * A virtual sensor that reports device heading based on information 28 * provided by accelerometer sensor or magnetic sensor. 29 */ 30 public class HeadingSensor implements SensorEventListener { 31 private static final Log.Tag TAG = new Log.Tag("HeadingSensor"); 32 33 /** Invalid heading values. */ 34 public static final int INVALID_HEADING = -1; 35 /** Current device heading. */ 36 private int mHeading = INVALID_HEADING; 37 38 /** Device sensor manager. */ 39 private final SensorManager mSensorManager; 40 /** Accelerometer. */ 41 private final Sensor mAccelerometerSensor; 42 /** Compass. */ 43 private final Sensor mMagneticSensor; 44 45 /** Accelerometer data. */ 46 private final float[] mGData = new float[3]; 47 /** Magnetic sensor data. */ 48 private final float[] mMData = new float[3]; 49 /** Temporary rotation matrix. */ 50 private final float[] mRotationMatrix = new float[16]; 51 52 /** 53 * Constructs a heading sensor. 54 * 55 * @param sensorManager A {#link android.hardware.SensorManager} that 56 * provides access to device sensors. 57 */ HeadingSensor(SensorManager sensorManager)58 public HeadingSensor(SensorManager sensorManager) { 59 mSensorManager = sensorManager; 60 mAccelerometerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 61 mMagneticSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); 62 } 63 64 /** 65 * Returns current device heading. 66 * 67 * @return current device heading in degrees. INVALID_HEADING if sensors 68 * are not available. 69 */ getCurrentHeading()70 public int getCurrentHeading() { 71 return mHeading; 72 } 73 74 /** 75 * Activates corresponding device sensors to start calculating device heading. 76 * This would increase power consumption. 77 */ activate()78 public void activate() { 79 // Get events from the accelerometer and magnetic sensor. 80 if (mAccelerometerSensor != null) { 81 mSensorManager.registerListener(this, mAccelerometerSensor, 82 SensorManager.SENSOR_DELAY_NORMAL); 83 } 84 if (mMagneticSensor != null) { 85 mSensorManager.registerListener(this, mMagneticSensor, 86 SensorManager.SENSOR_DELAY_NORMAL); 87 } 88 } 89 90 /** 91 * Deactivates corresponding device sensors to stop calculating device heading. 92 */ deactivate()93 public void deactivate() { 94 // Unregister the sensors. 95 if (mAccelerometerSensor != null) { 96 mSensorManager.unregisterListener(this, mAccelerometerSensor); 97 } 98 if (mMagneticSensor != null) { 99 mSensorManager.unregisterListener(this, mMagneticSensor); 100 } 101 } 102 103 @Override onSensorChanged(SensorEvent event)104 public void onSensorChanged(SensorEvent event) { 105 // This is literally the same as the GCamModule implementation. 106 int type = event.sensor.getType(); 107 float[] data; 108 if (type == Sensor.TYPE_ACCELEROMETER) { 109 data = mGData; 110 } else if (type == Sensor.TYPE_MAGNETIC_FIELD) { 111 data = mMData; 112 } else { 113 Log.w(TAG, String.format("Unexpected sensor type %s", event.sensor.getName())); 114 return; 115 } 116 for (int i = 0; i < 3; i++) { 117 data[i] = event.values[i]; 118 } 119 float[] orientation = new float[3]; 120 SensorManager.getRotationMatrix(mRotationMatrix, null, mGData, mMData); 121 SensorManager.getOrientation(mRotationMatrix, orientation); 122 mHeading = (int) (orientation[0] * 180f / Math.PI) % 360; 123 124 if (mHeading < 0) { 125 mHeading += 360; 126 } 127 } 128 129 @Override onAccuracyChanged(Sensor sensor, int accuracy)130 public void onAccuracyChanged(Sensor sensor, int accuracy) { 131 } 132 } 133