// Copyright 2008 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.android.stardroid.control; import android.content.SharedPreferences; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorListener; import android.hardware.SensorManager; import android.util.Log; import com.google.android.stardroid.ApplicationConstants; import com.google.android.stardroid.util.MiscUtil; import com.google.android.stardroid.util.smoothers.ExponentiallyWeightedSmoother; import com.google.android.stardroid.util.smoothers.PlainSmootherModelAdaptor; import javax.inject.Inject; import javax.inject.Provider; /** * Sets the direction of view from the orientation sensors. * * @author John Taylor */ public class SensorOrientationController extends AbstractController implements SensorEventListener { // TODO(johntaylor): this class needs to be refactored to use the new // sensor API and to behave properly when sensors are not available. private static class SensorDampingSettings { public float damping; public int exponent; public SensorDampingSettings(float damping, int exponent) { this.damping = damping; this.exponent = exponent; } } private final static String TAG = MiscUtil.getTag(SensorOrientationController.class); /** * Parameters that control the smoothing of the accelerometer and * magnetic sensors. */ private static final SensorDampingSettings[] ACC_DAMPING_SETTINGS = new SensorDampingSettings[] { new SensorDampingSettings(0.7f, 3), new SensorDampingSettings(0.7f, 3), new SensorDampingSettings(0.1f, 3), new SensorDampingSettings(0.1f, 3), }; private static final SensorDampingSettings[] MAG_DAMPING_SETTINGS = new SensorDampingSettings[] { new SensorDampingSettings(0.05f, 3), // Derived for the Nexus One new SensorDampingSettings(0.001f, 4), // Derived for the unpatched MyTouch Slide new SensorDampingSettings(0.0001f, 5), // Just guessed for Nexus 6 new SensorDampingSettings(0.000001f, 5) // Just guessed for Nexus 6 }; private SensorManager manager; private SensorListener accelerometerSmoother; private SensorListener compassSmoother; private Provider<PlainSmootherModelAdaptor> modelAdaptorProvider; private Sensor rotationSensor; private SharedPreferences sharedPreferences; @Inject SensorOrientationController(Provider<PlainSmootherModelAdaptor> modelAdaptorProvider, SensorManager manager, SharedPreferences sharedPreferences) { this.manager = manager; this.modelAdaptorProvider = modelAdaptorProvider; this.rotationSensor = manager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR); this.sharedPreferences = sharedPreferences; } @Override public void start() { PlainSmootherModelAdaptor modelAdaptor = modelAdaptorProvider.get(); if (manager != null) { if (!sharedPreferences.getBoolean(ApplicationConstants.SHARED_PREFERENCE_DISABLE_GYRO, false)) { Log.d(TAG, "Using rotation sensor"); manager.registerListener(this, rotationSensor, SensorManager.SENSOR_DELAY_GAME); } else { // TODO(jontayler): remove this code once enough it's used in few enough phones. Log.d(TAG, "Using classic sensors"); Log.d(TAG, "Exponentially weighted smoothers used"); String dampingPreference = sharedPreferences.getString( ApplicationConstants.SENSOR_DAMPING_PREF_KEY, ApplicationConstants.SENSOR_DAMPING_STANDARD); String speedPreference = sharedPreferences.getString(ApplicationConstants.SENSOR_SPEED_PREF_KEY, ApplicationConstants.SENSOR_SPEED_STANDARD); Log.d(TAG, "Sensor damping preference " + dampingPreference); Log.d(TAG, "Sensor speed preference " + speedPreference); int dampingIndex = 0; if (ApplicationConstants.SENSOR_DAMPING_HIGH.equals(dampingPreference)) { dampingIndex = 1; } else if (ApplicationConstants.SENSOR_DAMPING_EXTRA_HIGH.equals(dampingPreference)) { dampingIndex = 2; } else if (ApplicationConstants.SENSOR_DAMPING_REALLY_HIGH.equals(dampingPreference)) { dampingIndex = 3; } int sensorSpeed = SensorManager.SENSOR_DELAY_GAME; if (ApplicationConstants.SENSOR_SPEED_SLOW.equals(speedPreference)) { sensorSpeed = SensorManager.SENSOR_DELAY_NORMAL; } else if (ApplicationConstants.SENSOR_SPEED_HIGH.equals(speedPreference)) { sensorSpeed = SensorManager.SENSOR_DELAY_FASTEST; } accelerometerSmoother = new ExponentiallyWeightedSmoother( modelAdaptor, ACC_DAMPING_SETTINGS[dampingIndex].damping, ACC_DAMPING_SETTINGS[dampingIndex].exponent); compassSmoother = new ExponentiallyWeightedSmoother( modelAdaptor, MAG_DAMPING_SETTINGS[dampingIndex].damping, MAG_DAMPING_SETTINGS[dampingIndex].exponent); manager.registerListener(accelerometerSmoother, SensorManager.SENSOR_ACCELEROMETER, sensorSpeed); manager.registerListener(compassSmoother, SensorManager.SENSOR_MAGNETIC_FIELD, sensorSpeed); } } Log.d(TAG, "Registered sensor listener"); } @Override public void stop() { Log.d( TAG, "Unregistering sensor listeners: " + accelerometerSmoother + ", " + compassSmoother + ", " + this); manager.unregisterListener(accelerometerSmoother); manager.unregisterListener(compassSmoother); manager.unregisterListener(this); } @Override public void onSensorChanged(SensorEvent event) { if (event.sensor != rotationSensor) { return; } model.setPhoneSensorValues(event.values); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // Ignore } }