18b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu/*
28b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu * Copyright (C) 2015 The Android Open Source Project
38b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu *
48b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu * Licensed under the Apache License, Version 2.0 (the "License");
58b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu * you may not use this file except in compliance with the License.
68b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu * You may obtain a copy of the License at
78b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu *
88b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu *      http://www.apache.org/licenses/LICENSE-2.0
98b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu *
108b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu * Unless required by applicable law or agreed to in writing, software
118b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu * distributed under the License is distributed on an "AS IS" BASIS,
128b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu * See the License for the specific language governing permissions and
148b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu * limitations under the License.
158b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu */
168b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu
178b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hupackage com.android.camera.hardware;
188b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu
198b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Huimport com.android.camera.debug.Log;
208b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu
218b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Huimport android.hardware.Sensor;
228b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Huimport android.hardware.SensorEvent;
238b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Huimport android.hardware.SensorEventListener;
248b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Huimport android.hardware.SensorManager;
258b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu
268b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu/**
278b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu * A virtual sensor that reports device heading based on information
288b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu * provided by accelerometer sensor or magnetic sensor.
298b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu */
308b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hupublic class HeadingSensor implements SensorEventListener {
318b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    private static final Log.Tag TAG = new Log.Tag("HeadingSensor");
328b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu
338b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    /** Invalid heading values. */
348b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    public static final int INVALID_HEADING = -1;
358b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    /** Current device heading. */
368b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    private int mHeading = INVALID_HEADING;
378b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu
388b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    /** Device sensor manager. */
398b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    private final SensorManager mSensorManager;
408b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    /** Accelerometer. */
418b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    private final Sensor mAccelerometerSensor;
428b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    /** Compass. */
438b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    private final Sensor mMagneticSensor;
448b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu
458b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    /** Accelerometer data. */
468b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    private final float[] mGData = new float[3];
478b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    /** Magnetic sensor data. */
488b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    private final float[] mMData = new float[3];
498b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    /** Temporary rotation matrix. */
508b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    private final float[] mRotationMatrix = new float[16];
518b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu
528b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    /**
538b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu     * Constructs a heading sensor.
548b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu     *
558b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu     * @param sensorManager A {#link android.hardware.SensorManager} that
568b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu     *                      provides access to device sensors.
578b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu     */
588b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    public HeadingSensor(SensorManager sensorManager) {
598b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        mSensorManager = sensorManager;
608b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        mAccelerometerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
618b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        mMagneticSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
628b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    }
638b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu
648b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    /**
658b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu     * Returns current device heading.
668b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu     *
678b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu     * @return current device heading in degrees. INVALID_HEADING if sensors
688b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu     *         are not available.
698b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu     */
708b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    public int getCurrentHeading() {
718b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        return mHeading;
728b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    }
738b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu
748b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    /**
758b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu     * Activates corresponding device sensors to start calculating device heading.
768b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu     * This would increase power consumption.
778b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu     */
788b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    public void activate() {
798b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        // Get events from the accelerometer and magnetic sensor.
808b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        if (mAccelerometerSensor != null) {
818b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu            mSensorManager.registerListener(this, mAccelerometerSensor,
828b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu                    SensorManager.SENSOR_DELAY_NORMAL);
838b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        }
848b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        if (mMagneticSensor != null) {
858b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu            mSensorManager.registerListener(this, mMagneticSensor,
868b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu                    SensorManager.SENSOR_DELAY_NORMAL);
878b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        }
888b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    }
898b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu
908b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    /**
918b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu     * Deactivates corresponding device sensors to stop calculating device heading.
928b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu     */
938b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    public void deactivate() {
948b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        // Unregister the sensors.
958b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        if (mAccelerometerSensor != null) {
968b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu            mSensorManager.unregisterListener(this, mAccelerometerSensor);
978b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        }
988b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        if (mMagneticSensor != null) {
998b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu            mSensorManager.unregisterListener(this, mMagneticSensor);
1008b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        }
1018b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    }
1028b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu
1038b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    @Override
1048b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    public void onSensorChanged(SensorEvent event) {
1058b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        // This is literally the same as the GCamModule implementation.
1068b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        int type = event.sensor.getType();
1078b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        float[] data;
1088b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        if (type == Sensor.TYPE_ACCELEROMETER) {
1098b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu            data = mGData;
1108b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        } else if (type == Sensor.TYPE_MAGNETIC_FIELD) {
1118b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu            data = mMData;
1128b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        } else {
1138b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu            Log.w(TAG, String.format("Unexpected sensor type %s", event.sensor.getName()));
1148b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu            return;
1158b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        }
1168b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        for (int i = 0; i < 3; i++) {
1178b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu            data[i] = event.values[i];
1188b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        }
1198b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        float[] orientation = new float[3];
1208b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        SensorManager.getRotationMatrix(mRotationMatrix, null, mGData, mMData);
1218b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        SensorManager.getOrientation(mRotationMatrix, orientation);
1228b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        mHeading = (int) (orientation[0] * 180f / Math.PI) % 360;
1238b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu
1248b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        if (mHeading < 0) {
1258b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu            mHeading += 360;
1268b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu        }
1278b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    }
1288b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu
1298b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    @Override
1308b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    public void onAccuracyChanged(Sensor sensor, int accuracy) {
1318b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu    }
1328b2a3ef10a7eea3e703397a3d94766029b0c5581Senpo Hu}
133