summaryrefslogtreecommitdiff
path: root/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentCompassEngine.java
diff options
context:
space:
mode:
Diffstat (limited to 'platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentCompassEngine.java')
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentCompassEngine.java268
1 files changed, 0 insertions, 268 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentCompassEngine.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentCompassEngine.java
deleted file mode 100644
index ce38233031..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentCompassEngine.java
+++ /dev/null
@@ -1,268 +0,0 @@
-package com.mapbox.mapboxsdk.location;
-
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.os.SystemClock;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.view.Surface;
-import android.view.WindowManager;
-
-import com.mapbox.mapboxsdk.log.Logger;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This manager class handles compass events such as starting the tracking of device bearing, or
- * when a new compass update occurs.
- */
-class LocationComponentCompassEngine implements CompassEngine, SensorEventListener {
-
- private static final String TAG = "Mbgl-LocationComponentCompassEngine";
-
- // The rate sensor events will be delivered at. As the Android documentation states, this is only
- // a hint to the system and the events might actually be received faster or slower then this
- // specified rate. Since the minimum Android API levels about 9, we are able to set this value
- // ourselves rather than using one of the provided constants which deliver updates too quickly for
- // our use case. The default is set to 100ms
- static final int SENSOR_DELAY_MICROS = 100 * 1000;
- // Filtering coefficient 0 < ALPHA < 1
- private static final float ALPHA = 0.45f;
-
- @NonNull
- private final WindowManager windowManager;
- @NonNull
- private final SensorManager sensorManager;
- private final List<CompassListener> compassListeners = new ArrayList<>();
-
- // Not all devices have a compassSensor
- @Nullable
- private Sensor compassSensor;
- @Nullable
- private Sensor gravitySensor;
- @Nullable
- private Sensor magneticFieldSensor;
-
- @NonNull
- private float[] truncatedRotationVectorValue = new float[4];
- @NonNull
- private float[] rotationMatrix = new float[9];
- private float[] rotationVectorValue;
- private float lastHeading;
- private int lastAccuracySensorStatus;
-
- private long compassUpdateNextTimestamp;
- @Nullable
- private float[] gravityValues = new float[3];
- @Nullable
- private float[] magneticValues = new float[3];
-
- /**
- * Construct a new instance of the this class. A internal compass listeners needed to separate it
- * from the cleared list of public listeners.
- */
- LocationComponentCompassEngine(@NonNull WindowManager windowManager, @NonNull SensorManager sensorManager) {
- this.windowManager = windowManager;
- this.sensorManager = sensorManager;
- compassSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
- if (compassSensor == null) {
- if (isGyroscopeAvailable()) {
- Logger.d(TAG, "Rotation vector sensor not supported on device, "
- + "falling back to orientation.");
- compassSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
- } else {
- Logger.d(TAG, "Rotation vector sensor not supported on device, "
- + "falling back to accelerometer and magnetic field.");
- gravitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
- magneticFieldSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
- }
- }
- }
-
- @Override
- public void addCompassListener(@NonNull CompassListener compassListener) {
- if (compassListeners.isEmpty()) {
- registerSensorListeners();
- }
- compassListeners.add(compassListener);
- }
-
- @Override
- public void removeCompassListener(@NonNull CompassListener compassListener) {
- compassListeners.remove(compassListener);
- if (compassListeners.isEmpty()) {
- unregisterSensorListeners();
- }
- }
-
- @Override
- public int getLastAccuracySensorStatus() {
- return lastAccuracySensorStatus;
- }
-
- @Override
- public float getLastHeading() {
- return lastHeading;
- }
-
- @Override
- public void onSensorChanged(@NonNull SensorEvent event) {
- // check when the last time the compass was updated, return if too soon.
- long currentTime = SystemClock.elapsedRealtime();
- if (currentTime < compassUpdateNextTimestamp) {
- return;
- }
- if (lastAccuracySensorStatus == SensorManager.SENSOR_STATUS_UNRELIABLE) {
- Logger.d(TAG, "Compass sensor is unreliable, device calibration is needed.");
- return;
- }
- if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
- rotationVectorValue = getRotationVectorFromSensorEvent(event);
- updateOrientation();
- } else if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
- notifyCompassChangeListeners((event.values[0] + 360) % 360);
- } else if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
- gravityValues = lowPassFilter(getRotationVectorFromSensorEvent(event), gravityValues);
- updateOrientation();
- } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
- magneticValues = lowPassFilter(getRotationVectorFromSensorEvent(event), magneticValues);
- updateOrientation();
- }
-
- // Update the compassUpdateNextTimestamp
- compassUpdateNextTimestamp = currentTime + LocationComponentConstants.COMPASS_UPDATE_RATE_MS;
- }
-
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- if (lastAccuracySensorStatus != accuracy) {
- for (CompassListener compassListener : compassListeners) {
- compassListener.onCompassAccuracyChange(accuracy);
- }
- lastAccuracySensorStatus = accuracy;
- }
- }
-
- private boolean isGyroscopeAvailable() {
- return sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE) != null;
- }
-
- @SuppressWarnings("SuspiciousNameCombination")
- private void updateOrientation() {
- if (rotationVectorValue != null) {
- SensorManager.getRotationMatrixFromVector(rotationMatrix, rotationVectorValue);
- } else {
- // Get rotation matrix given the gravity and geomagnetic matrices
- SensorManager.getRotationMatrix(rotationMatrix, null, gravityValues, magneticValues);
- }
-
- final int worldAxisForDeviceAxisX;
- final int worldAxisForDeviceAxisY;
-
- // Remap the axes as if the device screen was the instrument panel,
- // and adjust the rotation matrix for the device orientation.
- switch (windowManager.getDefaultDisplay().getRotation()) {
- case Surface.ROTATION_90:
- worldAxisForDeviceAxisX = SensorManager.AXIS_Z;
- worldAxisForDeviceAxisY = SensorManager.AXIS_MINUS_X;
- break;
- case Surface.ROTATION_180:
- worldAxisForDeviceAxisX = SensorManager.AXIS_MINUS_X;
- worldAxisForDeviceAxisY = SensorManager.AXIS_MINUS_Z;
- break;
- case Surface.ROTATION_270:
- worldAxisForDeviceAxisX = SensorManager.AXIS_MINUS_Z;
- worldAxisForDeviceAxisY = SensorManager.AXIS_X;
- break;
- case Surface.ROTATION_0:
- default:
- worldAxisForDeviceAxisX = SensorManager.AXIS_X;
- worldAxisForDeviceAxisY = SensorManager.AXIS_Z;
- break;
- }
-
- float[] adjustedRotationMatrix = new float[9];
- SensorManager.remapCoordinateSystem(rotationMatrix, worldAxisForDeviceAxisX,
- worldAxisForDeviceAxisY, adjustedRotationMatrix);
-
- // Transform rotation matrix into azimuth/pitch/roll
- float[] orientation = new float[3];
- SensorManager.getOrientation(adjustedRotationMatrix, orientation);
-
- // The x-axis is all we care about here.
- notifyCompassChangeListeners((float) Math.toDegrees(orientation[0]));
- }
-
- private void notifyCompassChangeListeners(float heading) {
- for (CompassListener compassListener : compassListeners) {
- compassListener.onCompassChanged(heading);
- }
- lastHeading = heading;
- }
-
- private void registerSensorListeners() {
- if (isCompassSensorAvailable()) {
- // Does nothing if the sensors already registered.
- sensorManager.registerListener(this, compassSensor, SENSOR_DELAY_MICROS);
- } else {
- sensorManager.registerListener(this, gravitySensor, SENSOR_DELAY_MICROS);
- sensorManager.registerListener(this, magneticFieldSensor, SENSOR_DELAY_MICROS);
- }
- }
-
- private void unregisterSensorListeners() {
- if (isCompassSensorAvailable()) {
- sensorManager.unregisterListener(this, compassSensor);
- } else {
- sensorManager.unregisterListener(this, gravitySensor);
- sensorManager.unregisterListener(this, magneticFieldSensor);
- }
- }
-
- private boolean isCompassSensorAvailable() {
- return compassSensor != null;
- }
-
- /**
- * Helper function, that filters newValues, considering previous values
- *
- * @param newValues array of float, that contains new data
- * @param smoothedValues array of float, that contains previous state
- * @return float filtered array of float
- */
- @NonNull
- private float[] lowPassFilter(@NonNull float[] newValues, @Nullable float[] smoothedValues) {
- if (smoothedValues == null) {
- return newValues;
- }
- for (int i = 0; i < newValues.length; i++) {
- smoothedValues[i] = smoothedValues[i] + ALPHA * (newValues[i] - smoothedValues[i]);
- }
- return smoothedValues;
- }
-
- /**
- * Pulls out the rotation vector from a SensorEvent, with a maximum length
- * vector of four elements to avoid potential compatibility issues.
- *
- * @param event the sensor event
- * @return the events rotation vector, potentially truncated
- */
- @NonNull
- private float[] getRotationVectorFromSensorEvent(@NonNull SensorEvent event) {
- if (event.values.length > 4) {
- // On some Samsung devices SensorManager.getRotationMatrixFromVector
- // appears to throw an exception if rotation vector has length > 4.
- // For the purposes of this class the first 4 values of the
- // rotation vector are sufficient (see crbug.com/335298 for details).
- // Only affects Android 4.3
- System.arraycopy(event.values, 0, truncatedRotationVectorValue, 0, 4);
- return truncatedRotationVectorValue;
- } else {
- return event.values;
- }
- }
-} \ No newline at end of file