blob: 2fd9d541e016e358f83d0bb8c90e5b070b5dd10a [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.android.camera.settings;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.preference.PreferenceManager;
import android.util.SparseArray;
import com.android.camera.ListPreference;
import com.android.camera.app.AppController;
import com.android.camera.app.LocationManager;
import com.android.camera.debug.Log;
import com.android.camera.util.CameraUtil;
import com.android.camera.util.SettingsHelper;
import com.android.camera2.R;
import java.util.ArrayList;
import java.util.List;
/**
* SettingsManager class provides an api for getting and setting both global and
* local SharedPreferences.
*/
public class SettingsManager {
private static final Log.Tag TAG = new Log.Tag("SettingsManager");
private final Context mContext;
private final SharedPreferences mDefaultSettings;
private final SettingsCache mSettingsCache;
private SharedPreferences mGlobalSettings;
private SharedPreferences mCameraSettings;
private final SparseArray<SharedPreferences> mModuleSettings = new SparseArray<SharedPreferences>();
private SettingsCapabilities mCapabilities;
private int mCameraId = -1;
private final AppController mAppController;
/**
* General settings upgrade model:
*
* On app upgrade, there are three main ways Settings can be stale/incorrect:
* (1) if the type of a setting has changed.
* (2) if a set value is no longer a member of the set of possible values.
* (3) if the SharedPreferences backing file has changed for a setting.
*
* Recovery strategies:
* (1) catch the ClassCastException or NumberFormatException and try to do a
* type conversion, or reset the setting to whatever default is valid.
* (2) sanitize sets, and reset to default if set value is no longer valid.
* (3) use the default value by virtue of the setting not yet being in the
* new file.
*
* Special cases:
*
* There are some settings which shouldn't be reset to default on upgrade if
* possible. We provide a callback which is executed only on strict upgrade.
* This callback does special case upgrades to a subset of the settings. This
* contrasts with the general upgrade strategies, which happen lazily, once a
* setting is used.
*
* Removing obsolete key/value pairs:
*
* This can be done in the strict upgrade callback. The strict upgrade callback
* should be idempotent, so it is important to leave removal code in the upgrade
* callback so the key/value pairs are removed even if a user skips a version.
*/
public interface StrictUpgradeCallback {
/**
* Will be executed in the SettingsManager constructor if the strict
* upgrade version counter has changed.
*/
public void upgrade(SettingsManager settingsManager, int version);
}
/**
* Increment this value whenever a new StrictUpgradeCallback needs to
* be executed. This defines upgrade behavior that should be executed
* strictly on app upgrades, when the upgrade behavior differs from the general,
* lazy upgrade strategies.
*/
private static final int STRICT_UPGRADE_VERSION = 2;
/**
* A List of OnSettingChangedListener's, maintained to compare to new
* listeners and prevent duplicate registering.
*/
private final List<OnSettingChangedListener> mListeners = new ArrayList<OnSettingChangedListener>();
/**
* A List of OnSharedPreferenceChangeListener's, maintained to hold pointers
* to actually registered listeners, so they can be unregistered.
*/
private final List<OnSharedPreferenceChangeListener> mSharedPreferenceListeners = new ArrayList<OnSharedPreferenceChangeListener>();
public SettingsManager(Context context, AppController app, int nCameras,
StrictUpgradeCallback upgradeCallback) {
mContext = context;
mAppController = app;
SettingsCache.ExtraSettings extraSettings = new SettingsHelper();
mSettingsCache = new SettingsCache(mContext, extraSettings);
mDefaultSettings = PreferenceManager.getDefaultSharedPreferences(context);
initGlobal();
if (upgradeCallback != null) {
// Check for a strict version upgrade.
int version = getInt(SETTING_STRICT_UPGRADE_VERSION);
if (STRICT_UPGRADE_VERSION != version) {
upgradeCallback.upgrade(this, STRICT_UPGRADE_VERSION);
}
setInt(SETTING_STRICT_UPGRADE_VERSION, STRICT_UPGRADE_VERSION);
}
}
/**
* Initialize global SharedPreferences.
*/
private void initGlobal() {
String globalKey = mContext.getPackageName() + "_preferences_camera";
mGlobalSettings = mContext.getSharedPreferences(globalKey, Context.MODE_PRIVATE);
}
/**
* Load and cache a module specific SharedPreferences.
*/
public SharedPreferences getModulePreferences(int modeIndex) {
SharedPreferences sharedPreferences = mModuleSettings.get(modeIndex);
if (sharedPreferences == null) {
String moduleKey = mContext.getPackageName() + "_preferences_module_" + modeIndex;
sharedPreferences = mContext.getSharedPreferences(moduleKey, Context.MODE_PRIVATE);
mModuleSettings.put(modeIndex, sharedPreferences);
}
return sharedPreferences;
}
/**
* Initialize SharedPreferences for other cameras.
*/
public void changeCamera(int cameraId, SettingsCapabilities capabilities) {
mCapabilities = capabilities;
mSettingsCache.setCapabilities(mCapabilities);
if (cameraId == mCameraId) {
return;
}
// We've changed camera ids, that means we need to flush the
// settings cache of settings dependent on SettingsCapabilities.
mSettingsCache.flush();
// Cache the camera id so we don't need to reload preferences
// if we're using the same camera.
mCameraId = cameraId;
String cameraKey = mContext.getPackageName() + "_preferences_" + cameraId;
mCameraSettings = mContext.getSharedPreferences(
cameraKey, Context.MODE_PRIVATE);
for (OnSharedPreferenceChangeListener listener : mSharedPreferenceListeners) {
mCameraSettings.registerOnSharedPreferenceChangeListener(listener);
}
}
/**
* Interface with Camera Parameters and Modules.
*/
public interface OnSettingChangedListener {
/**
* Called every time a SharedPreference has been changed.
*/
public void onSettingChanged(SettingsManager settingsManager, int setting);
}
private OnSharedPreferenceChangeListener getSharedPreferenceListener(
final OnSettingChangedListener listener) {
return new OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key) {
Integer settingId = mSettingsCache.getId(key);
if (settingId != null) {
listener.onSettingChanged(SettingsManager.this, settingId);
} else {
Log.w(TAG, "Setting id from key=" + key + " is null");
}
}
};
}
/**
* Add an OnSettingChangedListener to the SettingsManager, which will
* execute onSettingsChanged when any SharedPreference has been updated.
*/
public void addListener(final OnSettingChangedListener listener) {
if (listener == null) {
throw new IllegalArgumentException("OnSettingChangedListener cannot be null.");
}
if (mListeners.contains(listener)) {
return;
}
mListeners.add(listener);
OnSharedPreferenceChangeListener sharedPreferenceListener =
getSharedPreferenceListener(listener);
mSharedPreferenceListeners.add(sharedPreferenceListener);
if (mGlobalSettings != null) {
mGlobalSettings.registerOnSharedPreferenceChangeListener(sharedPreferenceListener);
}
if (mCameraSettings != null) {
mCameraSettings.registerOnSharedPreferenceChangeListener(sharedPreferenceListener);
}
if (mDefaultSettings != null) {
mDefaultSettings.registerOnSharedPreferenceChangeListener(sharedPreferenceListener);
}
}
/**
* Remove a specific SettingsListener. This should be done in onPause if a
* listener has been set.
*/
public void removeListener(OnSettingChangedListener listener) {
if (listener == null) {
throw new IllegalArgumentException();
}
if (!mListeners.contains(listener)) {
return;
}
int index = mListeners.indexOf(listener);
mListeners.remove(listener);
// Get the reference to the actual OnSharedPreferenceChangeListener
// that was registered.
OnSharedPreferenceChangeListener sharedPreferenceListener =
mSharedPreferenceListeners.get(index);
mSharedPreferenceListeners.remove(index);
if (mGlobalSettings != null) {
mGlobalSettings.unregisterOnSharedPreferenceChangeListener(
sharedPreferenceListener);
}
if (mCameraSettings != null) {
mCameraSettings.unregisterOnSharedPreferenceChangeListener(
sharedPreferenceListener);
}
if (mDefaultSettings != null) {
mDefaultSettings.unregisterOnSharedPreferenceChangeListener(
sharedPreferenceListener);
}
}
/**
* Remove all OnSharedPreferenceChangedListener's. This should be done in
* onDestroy.
*/
public void removeAllListeners() {
for (OnSharedPreferenceChangeListener listener : mSharedPreferenceListeners) {
if (mGlobalSettings != null) {
mGlobalSettings.unregisterOnSharedPreferenceChangeListener(listener);
}
if (mCameraSettings != null) {
mCameraSettings.unregisterOnSharedPreferenceChangeListener(listener);
}
if (mDefaultSettings != null) {
mDefaultSettings.unregisterOnSharedPreferenceChangeListener(listener);
}
}
mSharedPreferenceListeners.clear();
mListeners.clear();
}
/**
* SettingsCapabilities defines constraints around settings that need to be
* queried from external sources, like the camera parameters. This interface
* is camera api agnostic.
*/
public interface SettingsCapabilities {
/**
* Returns a dynamically calculated list of exposure values, based on
* the min and max exposure compensation supported by the camera device.
*/
public String[] getSupportedExposureValues();
/**
* Returns a list of camera ids based on the number of cameras available
* on the device.
*/
public String[] getSupportedCameraIds();
}
/**
* Get the camera id for which the SettingsManager has loaded camera
* specific preferences.
*/
public int getRegisteredCameraId() {
return mCameraId;
}
// Manage individual settings.
public static final String VALUE_NONE = "none";
public static final String VALUE_ON = "on";
public static final String VALUE_OFF = "off";
public static final String TYPE_STRING = "string";
public static final String TYPE_BOOLEAN = "boolean";
public static final String TYPE_INTEGER = "integer";
public static final String SOURCE_DEFAULT = "default";
public static final String SOURCE_GLOBAL = "global";
public static final String SOURCE_CAMERA = "camera";
public static final String SOURCE_MODULE = "module";
public static final boolean FLUSH_ON = true;
public static final boolean FLUSH_OFF = false;
// For quick lookup from id to Setting.
public static final int SETTING_RECORD_LOCATION = 0;
public static final int SETTING_VIDEO_QUALITY_BACK = 1;
public static final int SETTING_VIDEO_QUALITY_FRONT = 2;
public static final int SETTING_VIDEO_TIME_LAPSE_FRAME_INTERVAL = 3;
public static final int SETTING_PICTURE_SIZE_BACK = 4;
public static final int SETTING_PICTURE_SIZE_FRONT = 5;
public static final int SETTING_JPEG_QUALITY = 6;
public static final int SETTING_FOCUS_MODE = 7;
public static final int SETTING_FLASH_MODE = 8;
public static final int SETTING_VIDEOCAMERA_FLASH_MODE = 9;
public static final int SETTING_WHITE_BALANCE = 10;
public static final int SETTING_SCENE_MODE = 11;
public static final int SETTING_EXPOSURE = 12;
public static final int SETTING_TIMER = 13;
public static final int SETTING_TIMER_SOUND_EFFECTS = 14;
public static final int SETTING_VIDEO_EFFECT = 15;
public static final int SETTING_CAMERA_ID = 16;
public static final int SETTING_CAMERA_HDR = 17;
public static final int SETTING_CAMERA_HDR_PLUS = 18;
public static final int SETTING_CAMERA_FIRST_USE_HINT_SHOWN = 19;
public static final int SETTING_VIDEO_FIRST_USE_HINT_SHOWN = 20;
public static final int SETTING_STARTUP_MODULE_INDEX = 21;
public static final int SETTING_KEY_CAMERA_MODULE_LAST_USED_INDEX = 23;
public static final int SETTING_CAMERA_PANO_ORIENTATION = 24;
public static final int SETTING_CAMERA_GRID_LINES = 25;
public static final int SETTING_RELEASE_DIALOG_LAST_SHOWN_VERSION = 26;
public static final int SETTING_FLASH_SUPPORTED_BACK_CAMERA = 27;
public static final int SETTING_STRICT_UPGRADE_VERSION = 28;
// A boolean for requesting to return to HDR plus
// as soon as possible, if a user requests a setting/mode option
// that forces them to leave HDR plus.
public static final int SETTING_REQUEST_RETURN_HDR_PLUS = 30;
// Shared preference keys.
public static final String KEY_RECORD_LOCATION = "pref_camera_recordlocation_key";
public static final String KEY_VIDEO_QUALITY_BACK = "pref_video_quality_back_key";
public static final String KEY_VIDEO_QUALITY_FRONT = "pref_video_quality_front_key";
public static final String KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL =
"pref_video_time_lapse_frame_interval_key";
public static final String KEY_PICTURE_SIZE_BACK = "pref_camera_picturesize_back_key";
public static final String KEY_PICTURE_SIZE_FRONT = "pref_camera_picturesize_front_key";
public static final String KEY_JPEG_QUALITY = "pref_camera_jpegquality_key";
public static final String KEY_FOCUS_MODE = "pref_camera_focusmode_key";
public static final String KEY_FLASH_MODE = "pref_camera_flashmode_key";
public static final String KEY_VIDEOCAMERA_FLASH_MODE = "pref_camera_video_flashmode_key";
public static final String KEY_WHITE_BALANCE = "pref_camera_whitebalance_key";
public static final String KEY_SCENE_MODE = "pref_camera_scenemode_key";
public static final String KEY_EXPOSURE = "pref_camera_exposure_key";
public static final String KEY_TIMER = "pref_camera_timer_key";
public static final String KEY_TIMER_SOUND_EFFECTS = "pref_camera_timer_sound_key";
public static final String KEY_VIDEO_EFFECT = "pref_video_effect_key";
public static final String KEY_CAMERA_ID = "pref_camera_id_key";
public static final String KEY_CAMERA_HDR = "pref_camera_hdr_key";
public static final String KEY_CAMERA_HDR_PLUS = "pref_camera_hdr_plus_key";
public static final String KEY_CAMERA_FIRST_USE_HINT_SHOWN =
"pref_camera_first_use_hint_shown_key";
public static final String KEY_VIDEO_FIRST_USE_HINT_SHOWN =
"pref_video_first_use_hint_shown_key";
public static final String KEY_STARTUP_MODULE_INDEX = "camera.startup_module";
public static final String KEY_CAMERA_MODULE_LAST_USED =
"pref_camera_module_last_used_index";
public static final String KEY_CAMERA_PANO_ORIENTATION = "pref_camera_pano_orientation";
public static final String KEY_CAMERA_GRID_LINES = "pref_camera_grid_lines";
public static final String KEY_RELEASE_DIALOG_LAST_SHOWN_VERSION =
"pref_release_dialog_last_shown_version";
public static final String KEY_FLASH_SUPPORTED_BACK_CAMERA =
"pref_flash_supported_back_camera";
public static final String KEY_STRICT_UPGRADE_VERSION = "pref_strict_upgrade_version";
public static final String KEY_REQUEST_RETURN_HDR_PLUS = "pref_request_return_hdr_plus";
public static final int WHITE_BALANCE_DEFAULT_INDEX = 2;
/**
* Defines a simple class for holding a the spec of a setting. This spec is
* used by the generic api methods to query and update a setting.
*/
public static class Setting {
private final String mSource;
private final String mType;
private final String mDefault;
private final String mKey;
private final String[] mValues;
private final boolean mFlushOnCameraChange;
/**
* A constructor used to store a setting's profile.
*/
public Setting(String source, String type, String defaultValue, String key,
String[] values, boolean flushOnCameraChange) {
mSource = source;
mType = type;
mDefault = defaultValue;
mKey = key;
mValues = values;
mFlushOnCameraChange = flushOnCameraChange;
}
/**
* Returns the id of a SharedPreferences instance from which this
* Setting may be found. Possible values are {@link #SOURCE_DEFAULT},
* {@link #SOURCE_GLOBAL}, {@link #SOURCE_CAMERA}.
*/
public String getSource() {
return mSource;
}
/**
* Returns the type of the setting stored in SharedPreferences. Possible
* values are {@link #TYPE_STRING}, {@link #TYPE_INTEGER},
* {@link #TYPE_BOOLEAN}.
*/
public String getType() {
return mType;
}
/**
* Returns the default value of this setting.
*/
public String getDefault() {
return mDefault;
}
/**
* Returns the SharedPreferences key for this setting.
*/
public String getKey() {
return mKey;
}
/**
* Returns an array of possible String values for this setting. If this
* setting is not of type {@link #TYPE_STRING}, or it's not possible to
* generate the string values, this should return null;
*/
public String[] getStringValues() {
return mValues;
}
/**
* Returns whether the setting should be flushed from the cache when the
* camera device has changed.
*/
public boolean isFlushedOnCameraChanged() {
return mFlushOnCameraChange;
}
}
/**
* Get the SharedPreferences needed to query/update the setting.
*/
public SharedPreferences getSettingSource(Setting setting) {
return getSettingSource(setting.getSource());
}
private SharedPreferences getSettingSource(String source) {
if (source.equals(SOURCE_DEFAULT)) {
return mDefaultSettings;
}
if (source.equals(SOURCE_GLOBAL)) {
return mGlobalSettings;
}
if (source.equals(SOURCE_CAMERA)) {
return mCameraSettings;
}
if (source.equals(SOURCE_MODULE)) {
int modeIndex = CameraUtil.getCameraModeParentModeId(
mAppController.getCurrentModuleIndex(), mAppController.getAndroidContext());
return getModulePreferences(modeIndex);
}
return null;
}
/**
* Based on Setting id, finds the index of a Setting's String value in an
* array of possible String values. If the Setting is not of type String,
* this returns -1.
* <p>
* TODO: make this a supported api call for all types.
* </p>
*/
public int getStringValueIndex(int id) {
Setting setting = mSettingsCache.get(id);
if (setting == null || !TYPE_STRING.equals(setting.getType())) {
return -1;
}
return getStringValueIndex(setting.getStringValues(), get(id));
}
private int getStringValueIndex(String[] possibleValues, String value) {
if (value != null) {
if (possibleValues != null) {
for (int i = 0; i < possibleValues.length; i++) {
if (value.equals(possibleValues[i])) {
return i;
}
}
}
}
return -1;
}
/**
* Based on Setting id, sets a Setting's String value using the index into
* an array of possible String values. Fails to set a value if the index is
* out of bounds or the Setting is not of type String.
*
* @return Whether the value was set.
*/
public boolean setStringValueIndex(int id, int index) {
Setting setting = mSettingsCache.get(id);
if (setting == null || setting.getType() != TYPE_STRING) {
return false;
}
String[] possibleValues = setting.getStringValues();
if (possibleValues != null) {
if (index >= 0 && index < possibleValues.length) {
set(id, possibleValues[index]);
return true;
}
}
return false;
}
/**
* Returns whether this Setting was last set as a String.
*/
private boolean isString(int id, String source) {
Setting setting = mSettingsCache.get(id);
SharedPreferences preferences = getSettingSource(source);
try {
preferences.getString(setting.getKey(), null);
return true;
} catch (ClassCastException e) {
return false;
}
}
/**
* Returns whether this Setting was last set as a boolean.
*/
private boolean isBoolean(int id, String source) {
Setting setting = mSettingsCache.get(id);
SharedPreferences preferences = getSettingSource(source);
try {
preferences.getBoolean(setting.getKey(), false);
return true;
} catch (ClassCastException e) {
return false;
}
}
/**
* Returns whether this Setting was last set as an Integer.
*/
private boolean isInteger(int id, String source) {
Setting setting = mSettingsCache.get(id);
SharedPreferences preferences = getSettingSource(source);
try {
preferences.getInt(setting.getKey(), 0);
return true;
} catch (NumberFormatException e) {
return false;
}
}
/**
* Recover a Setting by converting it to a String if the type
* is known and the type conversion is successful, otherwise
* reset to the default.
*/
private String recoverToString(int id, String source) {
String value;
try {
if (isBoolean(id, source)) {
value = (getBoolean(id, source) ? VALUE_ON : VALUE_OFF);
} else if (isInteger(id, source)) {
value = Integer.toString(getInt(id, source));
} else {
throw new Exception();
}
} catch (Exception e) {
value = mSettingsCache.get(id).getDefault();
}
set(id, source, value);
return value;
}
/**
* Recover a Setting by converting it to a boolean if the type
* is known and the type conversion is successful, otherwise
* reset to the default.
*/
private boolean recoverToBoolean(int id, String source) {
boolean value;
try {
if (isString(id, source)) {
value = VALUE_ON.equals(get(id, source));
} else if (isInteger(id, source)) {
value = getInt(id, source) != 0;
} else {
throw new Exception();
}
} catch (Exception e) {
value = VALUE_ON.equals(mSettingsCache.get(id).getDefault());
}
setBoolean(id, source, value);
return value;
}
/**
* Recover a Setting by converting it to an Integer if the type
* is known and the type conversion is successful, otherwise
* reset to the default.
*/
private int recoverToInteger(int id, String source) {
int value;
try {
if (isString(id, source)) {
value = Integer.parseInt(get(id, source));
} else if (isBoolean(id, source)) {
value = getBoolean(id, source) ? 1 : 0;
} else {
throw new Exception();
}
} catch (Exception e) {
value = Integer.parseInt(mSettingsCache.get(id).getDefault());
}
setInt(id, value);
return value;
}
/**
* Check if a String value is in the set of possible values for a Setting.
* We only keep track of possible values for String types for now.
*/
private String sanitize(Setting setting, String value) {
if (setting.getStringValues() != null &&
getStringValueIndex(setting.getStringValues(), value) < 0) {
// If the set of possible values is not empty, and the value
// is not in the set of possible values, use the default, because
// the set of possible values probably changed.
return setting.getDefault();
}
return value;
}
/**
* Get a Setting's String value based on Setting id.
*/
// TODO: rename to something more descriptive like getString.
public String get(int id) {
Setting setting = mSettingsCache.get(id);
return get(id, setting.getSource());
}
/**
* Get a Setting's String value based on Setting id and a source file id.
*/
public String get(int id, String source) {
Setting setting = mSettingsCache.get(id);
SharedPreferences preferences = getSettingSource(source);
if (preferences != null) {
try {
String value = preferences.getString(setting.getKey(), setting.getDefault());
return sanitize(setting, value);
} catch (ClassCastException e) {
// If the api defines this Setting as a String, but the
// last set saved it as a different type, try to recover
// the value, but if impossible reset to default.
return recoverToString(id, source);
}
} else {
throw new IllegalStateException(
"Setting source=" + source + " is unitialized.");
}
}
/**
* Get a Setting's boolean value based on Setting id.
*/
public boolean getBoolean(int id) {
Setting setting = mSettingsCache.get(id);
return getBoolean(id, setting.getSource());
}
/**
* Get a Setting's boolean value based on a Setting id and a source file id.
*/
public boolean getBoolean(int id, String source) {
Setting setting = mSettingsCache.get(id);
SharedPreferences preferences = getSettingSource(source);
boolean defaultValue = VALUE_ON.equals(setting.getDefault());
if (preferences != null) {
try {
return preferences.getBoolean(setting.getKey(), defaultValue);
} catch (ClassCastException e) {
// If the api defines this Setting as a boolean, but the
// last set saved it as a different type, try to recover
// the value, but if impossible reset to default.
return recoverToBoolean(id, source);
}
} else {
throw new IllegalStateException(
"Setting source=" + source + " is unitialized.");
}
}
/**
* Get a Setting's int value based on Setting id.
*/
public int getInt(int id) {
Setting setting = mSettingsCache.get(id);
return getInt(id, setting.getSource());
}
/**
* Get a Setting's int value based on Setting id and a source file id.
*/
public int getInt(int id, String source) {
Setting setting = mSettingsCache.get(id);
SharedPreferences preferences = getSettingSource(source);
int defaultValue = Integer.parseInt(setting.getDefault());
if (preferences != null) {
try {
return preferences.getInt(setting.getKey(), defaultValue);
} catch (NumberFormatException e) {
// If the api defines this Setting as an Integer, but the
// last set saved it as a different type, try to recover
// the value, but if impossible reset to default.
return recoverToInteger(id, source);
}
} else {
throw new IllegalStateException(
"Setting source=" + source + " is unitialized.");
}
}
/**
* Set a Setting with a String value based on Setting id.
*/
// TODO: rename to something more descriptive.
public void set(int id, String value) {
Setting setting = mSettingsCache.get(id);
set(id, setting.getSource(), value);
}
/**
* Set a Setting with a String value based on Setting id and a source file id.
*/
public void set(int id, String source, String value) {
Setting setting = mSettingsCache.get(id);
value = sanitize(setting, value);
SharedPreferences preferences = getSettingSource(source);
if (preferences != null) {
preferences.edit().putString(setting.getKey(), value).apply();
} else {
throw new IllegalStateException(
"Setting source=" + source + " is unitialized.");
}
}
/**
* Set a Setting with a boolean value based on Setting id.
*/
public void setBoolean(int id, boolean value) {
Setting setting = mSettingsCache.get(id);
setBoolean(id, setting.getSource(), value);
}
/**
* Set a Setting with a boolean value based on Setting id and a source file id.
*/
public void setBoolean(int id, String source, boolean value) {
Setting setting = mSettingsCache.get(id);
SharedPreferences preferences = getSettingSource(source);
if (preferences != null) {
preferences.edit().putBoolean(setting.getKey(), value).apply();
} else {
throw new IllegalStateException(
"Setting source=" + source + " is unitialized.");
}
}
/**
* Set a Setting with an int value based on Setting id.
*/
public void setInt(int id, int value) {
Setting setting = mSettingsCache.get(id);
setInt(id, setting.getSource(), value);
}
/**
* Set a Setting with an int value based on Setting id and a source file id.
*/
public void setInt(int id, String source, int value) {
Setting setting = mSettingsCache.get(id);
SharedPreferences preferences = getSettingSource(source);
if (preferences != null) {
preferences.edit().putInt(setting.getKey(), value).apply();
} else {
throw new IllegalStateException(
"Setting source=" + source + " is unitialized.");
}
}
/**
* Check if a Setting has ever been set based on Setting id.
*/
public boolean isSet(int id) {
Setting setting = mSettingsCache.get(id);
return isSet(id, setting.getSource());
}
/**
* Check if a Setting has ever been set based on Setting id and a source file id.
*/
public boolean isSet(int id, String source) {
Setting setting = mSettingsCache.get(id);
SharedPreferences preferences = getSettingSource(source);
if (preferences != null) {
return preferences.contains(setting.getKey());
} else {
throw new IllegalStateException(
"Setting source=" + setting.getSource() + " is unitialized.");
}
}
/**
* Set a Setting to its default value based on Setting id.
*/
public void setDefault(int id) {
Setting setting = mSettingsCache.get(id);
SharedPreferences preferences = getSettingSource(setting);
if (preferences != null) {
preferences.edit().putString(setting.getKey(), setting.getDefault());
} else {
throw new IllegalStateException(
"Setting source=" + setting.getSource() + " is unitialized.");
}
}
/**
* Check if a Setting is set to its default value.
*/
public boolean isDefault(int id) {
Setting setting = mSettingsCache.get(id);
SharedPreferences preferences = getSettingSource(setting);
if (preferences != null) {
String type = setting.getType();
if (TYPE_STRING.equals(type)) {
String value = get(id);
return (value.equals(setting.getDefault()));
} else if (TYPE_BOOLEAN.equals(type)) {
boolean value = getBoolean(id);
boolean defaultValue = VALUE_ON.equals(setting.getDefault());
return (value == defaultValue);
} else if (TYPE_INTEGER.equals(type)) {
int value = getInt(id);
int defaultValue = Integer.parseInt(setting.getDefault());
return (value == defaultValue);
} else {
throw new IllegalArgumentException("Type " + type + " is not known.");
}
} else {
throw new IllegalStateException(
"Setting source=" + setting.getSource() + " is unitialized.");
}
}
/**
* Remove a Setting from SharedPreferences.
*/
public void remove(int id) {
Setting setting = mSettingsCache.get(id);
SharedPreferences preferences = getSettingSource(setting);
if (preferences != null) {
preferences.edit().remove(setting.getKey()).apply();
} else {
throw new IllegalStateException(
"Setting source=" + setting.getSource() + " is unitialized.");
}
}
public static Setting getLocationSetting(Context context) {
String defaultValue = context.getString(R.string.setting_none_value);
String[] values = null;
return new Setting(SOURCE_DEFAULT, TYPE_BOOLEAN, defaultValue, KEY_RECORD_LOCATION,
values, FLUSH_OFF);
}
public static Setting getPictureSizeBackSetting(Context context) {
String defaultValue = null;
String[] values = context.getResources().getStringArray(
R.array.pref_camera_picturesize_entryvalues);
return new Setting(SOURCE_DEFAULT, TYPE_STRING, defaultValue, KEY_PICTURE_SIZE_BACK,
values, FLUSH_OFF);
}
public static Setting getPictureSizeFrontSetting(Context context) {
String defaultValue = null;
String[] values = context.getResources().getStringArray(
R.array.pref_camera_picturesize_entryvalues);
return new Setting(SOURCE_DEFAULT, TYPE_STRING, defaultValue, KEY_PICTURE_SIZE_FRONT,
values, FLUSH_OFF);
}
public static Setting getDefaultCameraIdSetting(Context context,
SettingsCapabilities capabilities) {
String defaultValue = context.getString(R.string.pref_camera_id_default);
String[] values = null;
if (capabilities != null) {
values = capabilities.getSupportedCameraIds();
}
return new Setting(SOURCE_MODULE, TYPE_STRING, defaultValue, KEY_CAMERA_ID,
values, FLUSH_ON);
}
public static Setting getWhiteBalanceSetting(Context context) {
String defaultValue = context.getString(R.string.pref_camera_whitebalance_default);
String[] values = context.getResources().getStringArray(
R.array.pref_camera_whitebalance_entryvalues);
return new Setting(SOURCE_CAMERA, TYPE_STRING, defaultValue, KEY_WHITE_BALANCE,
values, FLUSH_OFF);
}
public static Setting getHdrSetting(Context context) {
String defaultValue = context.getString(R.string.pref_camera_hdr_default);
String[] values = context.getResources().getStringArray(
R.array.pref_camera_hdr_entryvalues);
return new Setting(SOURCE_GLOBAL, TYPE_STRING, defaultValue, KEY_CAMERA_HDR,
values, FLUSH_OFF);
}
public static Setting getHdrPlusSetting(Context context) {
String defaultValue = context.getString(R.string.pref_camera_hdr_plus_default);
String[] values = context.getResources().getStringArray(
R.array.pref_camera_hdr_plus_entryvalues);
return new Setting(SOURCE_GLOBAL, TYPE_STRING, defaultValue, KEY_CAMERA_HDR_PLUS,
values, FLUSH_OFF);
}
public static Setting getSceneModeSetting(Context context) {
String defaultValue = context.getString(R.string.pref_camera_scenemode_default);
String[] values = context.getResources().getStringArray(
R.array.pref_camera_scenemode_entryvalues);
return new Setting(SOURCE_CAMERA, TYPE_STRING, defaultValue, KEY_SCENE_MODE,
values, FLUSH_OFF);
}
public static Setting getFlashSetting(Context context) {
String defaultValue = context.getString(R.string.pref_camera_flashmode_default);
String[] values = context.getResources().getStringArray(
R.array.pref_camera_flashmode_entryvalues);
return new Setting(SOURCE_CAMERA, TYPE_STRING, defaultValue, KEY_FLASH_MODE,
values, FLUSH_OFF);
}
public static Setting getExposureSetting(Context context,
SettingsCapabilities capabilities) {
String defaultValue = context.getString(R.string.pref_exposure_default);
String[] values = null;
if (capabilities != null) {
values = capabilities.getSupportedExposureValues();
}
return new Setting(SOURCE_CAMERA, TYPE_STRING, defaultValue, KEY_EXPOSURE,
values, FLUSH_ON);
}
public static Setting getHintSetting(Context context) {
String defaultValue = context.getString(R.string.setting_on_value);
String[] values = null;
return new Setting(SOURCE_GLOBAL, TYPE_BOOLEAN, defaultValue,
KEY_CAMERA_FIRST_USE_HINT_SHOWN, values, FLUSH_OFF);
}
public static Setting getFocusModeSetting(Context context) {
String defaultValue = null;
String[] values = context.getResources().getStringArray(
R.array.pref_camera_focusmode_entryvalues);
return new Setting(SOURCE_CAMERA, TYPE_STRING, defaultValue, KEY_FOCUS_MODE,
values, FLUSH_OFF);
}
public static Setting getTimerSetting(Context context) {
String defaultValue = context.getString(R.string.pref_camera_timer_default);
String[] values = null; // TODO: get the values dynamically.
return new Setting(SOURCE_GLOBAL, TYPE_STRING, defaultValue, KEY_TIMER,
values, FLUSH_OFF);
}
public static Setting getTimerSoundSetting(Context context) {
String defaultValue = context.getString(R.string.pref_camera_timer_sound_default);
String[] values = context.getResources().getStringArray(
R.array.pref_camera_timer_sound_entryvalues);
return new Setting(SOURCE_GLOBAL, TYPE_STRING, defaultValue, KEY_TIMER_SOUND_EFFECTS,
values, FLUSH_OFF);
}
public static Setting getVideoQualityBackSetting(Context context) {
String defaultValue = context.getString(R.string.pref_video_quality_default);
String[] values = context.getResources().getStringArray(
R.array.pref_video_quality_entryvalues);
return new Setting(SOURCE_DEFAULT, TYPE_STRING, defaultValue, KEY_VIDEO_QUALITY_BACK,
values, FLUSH_OFF);
}
public static Setting getVideoQualityFrontSetting(Context context) {
String defaultValue = context.getString(R.string.pref_video_quality_default);
String[] values = context.getResources().getStringArray(
R.array.pref_video_quality_entryvalues);
return new Setting(SOURCE_DEFAULT, TYPE_STRING, defaultValue, KEY_VIDEO_QUALITY_FRONT,
values, FLUSH_OFF);
}
public static Setting getTimeLapseFrameIntervalSetting(Context context) {
String defaultValue = context.getString(
R.string.pref_video_time_lapse_frame_interval_default);
String[] values = context.getResources().getStringArray(
R.array.pref_video_time_lapse_frame_interval_entryvalues);
return new Setting(SOURCE_GLOBAL, TYPE_STRING, defaultValue,
KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL, values, FLUSH_OFF);
}
public static Setting getJpegQualitySetting(Context context) {
String defaultValue = context.getString(
R.string.pref_camera_jpeg_quality_normal);
String[] values = context.getResources().getStringArray(
R.array.pref_camera_jpeg_quality_entryvalues);
return new Setting(SOURCE_CAMERA, TYPE_STRING, defaultValue, KEY_JPEG_QUALITY,
values, FLUSH_OFF);
}
public static Setting getVideoFlashSetting(Context context) {
String defaultValue = context.getString(R.string.pref_camera_video_flashmode_default);
String[] values = context.getResources().getStringArray(
R.array.pref_camera_video_flashmode_entryvalues);
return new Setting(SOURCE_CAMERA, TYPE_STRING, defaultValue,
KEY_VIDEOCAMERA_FLASH_MODE, values, FLUSH_OFF);
}
public static Setting getVideoEffectSetting(Context context) {
String defaultValue = context.getString(R.string.pref_video_effect_default);
String[] values = context.getResources().getStringArray(
R.array.pref_video_effect_entryvalues);
return new Setting(SOURCE_GLOBAL, TYPE_STRING, defaultValue, KEY_VIDEO_EFFECT,
values, FLUSH_OFF);
}
public static Setting getHintVideoSetting(Context context) {
String defaultValue = context.getString(R.string.setting_on_value);
String[] values = null;
return new Setting(SOURCE_GLOBAL, TYPE_STRING, defaultValue,
KEY_VIDEO_FIRST_USE_HINT_SHOWN, values, FLUSH_OFF);
}
public static Setting getStartupModuleSetting(Context context) {
String defaultValue = context.getString(R.string.pref_camera_startup_index_default);
String[] values = null;
return new Setting(SOURCE_DEFAULT, TYPE_INTEGER, defaultValue,
KEY_STARTUP_MODULE_INDEX, values, FLUSH_OFF);
}
public static Setting getLastUsedCameraModule(Context context) {
String defaultValue = Integer.toString(context.getResources()
.getInteger(R.integer.camera_mode_photo));
return new Setting(SOURCE_DEFAULT, TYPE_INTEGER, defaultValue,
KEY_CAMERA_MODULE_LAST_USED, null, FLUSH_OFF);
}
public static Setting getPanoOrientationSetting(Context context) {
String defaultValue = context.getString(R.string.pano_orientation_horizontal);
String[] values = context.getResources().getStringArray(
R.array.pref_camera_pano_orientation_entryvalues);
return new Setting(SOURCE_GLOBAL, TYPE_STRING, defaultValue,
KEY_CAMERA_PANO_ORIENTATION, values, FLUSH_OFF);
}
public static Setting getGridLinesSetting(Context context) {
String defaultValue = context.getString(R.string.setting_off_value);
String[] values = context.getResources().getStringArray(
R.array.pref_camera_gridlines_entryvalues);
return new Setting(SOURCE_GLOBAL, TYPE_STRING, defaultValue,
KEY_CAMERA_GRID_LINES, values, FLUSH_OFF);
}
public static Setting getReleaseDialogLastShownVersionSetting(Context context) {
return new Setting(SOURCE_DEFAULT, TYPE_STRING, null,
KEY_RELEASE_DIALOG_LAST_SHOWN_VERSION, null, FLUSH_OFF);
}
public static Setting getFlashSupportedBackCameraSetting(Context context) {
String defaultValue = context.getString(R.string.setting_none_value);
return new Setting(SOURCE_GLOBAL, TYPE_BOOLEAN, defaultValue,
KEY_FLASH_SUPPORTED_BACK_CAMERA, null, FLUSH_OFF);
}
public static Setting getStrictUpgradeVersionSetting(Context context) {
String defaultValue = "0";
return new Setting(SOURCE_DEFAULT, TYPE_INTEGER, defaultValue,
KEY_STRICT_UPGRADE_VERSION, null, FLUSH_OFF);
}
public static Setting getRequestReturnHdrPlusSetting(Context context) {
String defaultValue = context.getString(R.string.setting_none_value);
return new Setting(SOURCE_MODULE, TYPE_BOOLEAN, VALUE_OFF,
KEY_REQUEST_RETURN_HDR_PLUS, null, FLUSH_OFF);
}
// Utilities.
/**
* Returns whether the camera has been set to back facing in settings.
*/
public boolean isCameraBackFacing() {
String cameraFacing = get(SETTING_CAMERA_ID);
String backFacing = mContext.getString(R.string.pref_camera_id_default);
return (Integer.parseInt(cameraFacing) == Integer.parseInt(backFacing));
}
/**
* Returns whether hdr plus mode is set on.
*/
public boolean isHdrPlusOn() {
String hdrOn = get(SettingsManager.SETTING_CAMERA_HDR);
return hdrOn.equals(SettingsManager.VALUE_ON);
}
/**
* Returns whether the app should return to hdr plus mode if possible.
*/
public boolean requestsReturnToHdrPlus() {
return getBoolean(SettingsManager.SETTING_REQUEST_RETURN_HDR_PLUS);
}
/**
* Returns whether grid lines are set on.
*/
public boolean areGridLinesOn() {
String gridLinesOn = get(SettingsManager.SETTING_CAMERA_GRID_LINES);
return gridLinesOn.equals(SettingsManager.VALUE_ON);
}
/**
* Returns whether pano orientation is horizontal.
*/
public boolean isPanoOrientationHorizontal() {
String orientation = get(SettingsManager.SETTING_CAMERA_PANO_ORIENTATION);
String horizontal = mContext.getString(R.string.pano_orientation_horizontal);
return orientation.equals(horizontal);
}
// TODO: refactor this into a separate utils module.
/**
* Get a String value from first the ListPreference, and if not found from
* the SettingsManager. This is a wrapper that adds backwards compatibility
* to views that rely on PreferenceGroups.
*/
public String getValueFromPreference(ListPreference pref) {
String value = pref.getValue();
if (value == null) {
Integer id = mSettingsCache.getId(pref.getKey());
if (id == null) {
return null;
}
value = get(id);
}
return value;
}
/**
* Set a String value first from the ListPreference, and if unable from the
* SettingsManager. This is a wrapper that adds backwards compatibility to
* views that rely on PreferenceGroups.
*/
public void setValueFromPreference(ListPreference pref, String value) {
boolean set = pref.setValue(value);
if (!set) {
Integer id = mSettingsCache.getId(pref.getKey());
if (id != null) {
set(id, value);
}
}
}
/**
* Set a String value first from the ListPreference based on a
* ListPreference index, and if unable use the ListPreference key to set the
* value using the SettingsManager. This is a wrapper that adds backwards
* compatibility to views that rely on PreferenceGroups.
*/
public void setValueIndexFromPreference(ListPreference pref, int index) {
boolean set = pref.setValueIndex(index);
if (!set) {
Integer id = mSettingsCache.getId(pref.getKey());
if (id != null) {
String value = pref.getValueAtIndex(index);
set(id, value);
}
}
}
/**
* Sets the settings for whether location recording should be enabled or
* not. Also makes sure to pass on the change to the location manager.
*/
public void setLocation(boolean on, LocationManager locationManager) {
setBoolean(SettingsManager.SETTING_RECORD_LOCATION, on);
locationManager.recordLocation(on);
}
/**
* Reads the current location recording settings and passes it on to the
* given location manager.
*/
public void syncLocationManager(LocationManager locationManager) {
boolean value = getBoolean(SettingsManager.SETTING_RECORD_LOCATION);
locationManager.recordLocation(value);
}
}