2 * Copyright (C) 2013 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.camera.settings;
19 import android.content.Context;
20 import android.content.SharedPreferences;
21 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
22 import android.preference.PreferenceManager;
23 import android.util.Log;
24 import android.util.SparseArray;
26 import com.android.camera.ListPreference;
27 import com.android.camera.app.AppController;
28 import com.android.camera.app.LocationManager;
29 import com.android.camera.util.CameraUtil;
30 import com.android.camera.util.SettingsHelper;
31 import com.android.camera2.R;
33 import java.util.ArrayList;
34 import java.util.List;
37 * SettingsManager class provides an api for getting and setting both global and
38 * local SharedPreferences.
40 public class SettingsManager {
41 private static final String TAG = "SettingsManager";
43 private final Context mContext;
44 private final SharedPreferences mDefaultSettings;
45 private final SettingsCache mSettingsCache;
46 private SharedPreferences mGlobalSettings;
47 private SharedPreferences mCameraSettings;
48 private final SparseArray<SharedPreferences> mModuleSettings = new SparseArray<SharedPreferences>();
49 private SettingsCapabilities mCapabilities;
51 private int mCameraId = -1;
52 private final AppController mAppController;
55 * General settings upgrade model:
57 * On app upgrade, there are three main ways Settings can be stale/incorrect:
58 * (1) if the type of a setting has changed.
59 * (2) if a set value is no longer a member of the set of possible values.
60 * (3) if the SharedPreferences backing file has changed for a setting.
62 * Recovery strategies:
63 * (1) catch the ClassCastException or NumberFormatException and try to do a
64 * type conversion, or reset the setting to whatever default is valid.
65 * (2) sanitize sets, and reset to default if set value is no longer valid.
66 * (3) use the default value by virtue of the setting not yet being in the
71 * There are some settings which shouldn't be reset to default on upgrade if
72 * possible. We provide a callback which is executed only on strict upgrade.
73 * This callback does special case upgrades to a subset of the settings. This
74 * contrasts with the general upgrade strategies, which happen lazily, once a
77 * Removing obsolete key/value pairs:
79 * This can be done in the strict upgrade callback. The strict upgrade callback
80 * should be idempotent, so it is important to leave removal code in the upgrade
81 * callback so the key/value pairs are removed even if a user skips a version.
83 public interface StrictUpgradeCallback {
85 * Will be executed in the SettingsManager constructor if the strict
86 * upgrade version counter has changed.
88 public void upgrade(SettingsManager settingsManager, int version);
92 * Increment this value whenever a new StrictUpgradeCallback needs to
93 * be executed. This defines upgrade behavior that should be executed
94 * strictly on app upgrades, when the upgrade behavior differs from the general,
95 * lazy upgrade strategies.
97 private static final int STRICT_UPGRADE_VERSION = 2;
100 * A List of OnSettingChangedListener's, maintained to compare to new
101 * listeners and prevent duplicate registering.
103 private final List<OnSettingChangedListener> mListeners = new ArrayList<OnSettingChangedListener>();
106 * A List of OnSharedPreferenceChangeListener's, maintained to hold pointers
107 * to actually registered listeners, so they can be unregistered.
109 private final List<OnSharedPreferenceChangeListener> mSharedPreferenceListeners = new ArrayList<OnSharedPreferenceChangeListener>();
111 public SettingsManager(Context context, AppController app, int nCameras,
112 StrictUpgradeCallback upgradeCallback) {
114 mAppController = app;
116 SettingsCache.ExtraSettings extraSettings = new SettingsHelper();
117 mSettingsCache = new SettingsCache(mContext, extraSettings);
119 mDefaultSettings = PreferenceManager.getDefaultSharedPreferences(context);
122 if (upgradeCallback != null) {
123 // Check for a strict version upgrade.
124 int version = getInt(SETTING_STRICT_UPGRADE_VERSION);
125 if (STRICT_UPGRADE_VERSION != version) {
126 upgradeCallback.upgrade(this, STRICT_UPGRADE_VERSION);
128 setInt(SETTING_STRICT_UPGRADE_VERSION, STRICT_UPGRADE_VERSION);
133 * Initialize global SharedPreferences.
135 private void initGlobal() {
136 String globalKey = mContext.getPackageName() + "_preferences_camera";
137 mGlobalSettings = mContext.getSharedPreferences(globalKey, Context.MODE_PRIVATE);
141 * Load and cache a module specific SharedPreferences.
143 public SharedPreferences getModulePreferences(int modeIndex) {
144 SharedPreferences sharedPreferences = mModuleSettings.get(modeIndex);
145 if (sharedPreferences == null) {
146 String moduleKey = mContext.getPackageName() + "_preferences_module_" + modeIndex;
147 sharedPreferences = mContext.getSharedPreferences(moduleKey, Context.MODE_PRIVATE);
148 mModuleSettings.put(modeIndex, sharedPreferences);
150 return sharedPreferences;
154 * Initialize SharedPreferences for other cameras.
156 public void changeCamera(int cameraId, SettingsCapabilities capabilities) {
157 mCapabilities = capabilities;
158 mSettingsCache.setCapabilities(mCapabilities);
160 if (cameraId == mCameraId) {
164 // We've changed camera ids, that means we need to flush the
165 // settings cache of settings dependent on SettingsCapabilities.
166 mSettingsCache.flush();
168 // Cache the camera id so we don't need to reload preferences
169 // if we're using the same camera.
170 mCameraId = cameraId;
172 String cameraKey = mContext.getPackageName() + "_preferences_" + cameraId;
173 mCameraSettings = mContext.getSharedPreferences(
174 cameraKey, Context.MODE_PRIVATE);
176 for (OnSharedPreferenceChangeListener listener : mSharedPreferenceListeners) {
177 mCameraSettings.registerOnSharedPreferenceChangeListener(listener);
182 * Interface with Camera Parameters and Modules.
184 public interface OnSettingChangedListener {
186 * Called every time a SharedPreference has been changed.
188 public void onSettingChanged(SettingsManager settingsManager, int setting);
191 private OnSharedPreferenceChangeListener getSharedPreferenceListener(
192 final OnSettingChangedListener listener) {
193 return new OnSharedPreferenceChangeListener() {
195 public void onSharedPreferenceChanged(
196 SharedPreferences sharedPreferences, String key) {
197 Integer settingId = mSettingsCache.getId(key);
198 if (settingId != null) {
199 listener.onSettingChanged(SettingsManager.this, settingId);
201 Log.w(TAG, "Setting id from key=" + key + " is null");
208 * Add an OnSettingChangedListener to the SettingsManager, which will
209 * execute onSettingsChanged when any SharedPreference has been updated.
211 public void addListener(final OnSettingChangedListener listener) {
212 if (listener == null) {
213 throw new IllegalArgumentException("OnSettingChangedListener cannot be null.");
216 if (mListeners.contains(listener)) {
220 mListeners.add(listener);
221 OnSharedPreferenceChangeListener sharedPreferenceListener =
222 getSharedPreferenceListener(listener);
223 mSharedPreferenceListeners.add(sharedPreferenceListener);
225 if (mGlobalSettings != null) {
226 mGlobalSettings.registerOnSharedPreferenceChangeListener(sharedPreferenceListener);
229 if (mCameraSettings != null) {
230 mCameraSettings.registerOnSharedPreferenceChangeListener(sharedPreferenceListener);
233 if (mDefaultSettings != null) {
234 mDefaultSettings.registerOnSharedPreferenceChangeListener(sharedPreferenceListener);
239 * Remove a specific SettingsListener. This should be done in onPause if a
240 * listener has been set.
242 public void removeListener(OnSettingChangedListener listener) {
243 if (listener == null) {
244 throw new IllegalArgumentException();
247 if (!mListeners.contains(listener)) {
251 int index = mListeners.indexOf(listener);
252 mListeners.remove(listener);
254 // Get the reference to the actual OnSharedPreferenceChangeListener
255 // that was registered.
256 OnSharedPreferenceChangeListener sharedPreferenceListener =
257 mSharedPreferenceListeners.get(index);
258 mSharedPreferenceListeners.remove(index);
260 if (mGlobalSettings != null) {
261 mGlobalSettings.unregisterOnSharedPreferenceChangeListener(
262 sharedPreferenceListener);
265 if (mCameraSettings != null) {
266 mCameraSettings.unregisterOnSharedPreferenceChangeListener(
267 sharedPreferenceListener);
270 if (mDefaultSettings != null) {
271 mDefaultSettings.unregisterOnSharedPreferenceChangeListener(
272 sharedPreferenceListener);
277 * Remove all OnSharedPreferenceChangedListener's. This should be done in
280 public void removeAllListeners() {
281 for (OnSharedPreferenceChangeListener listener : mSharedPreferenceListeners) {
282 if (mGlobalSettings != null) {
283 mGlobalSettings.unregisterOnSharedPreferenceChangeListener(listener);
286 if (mCameraSettings != null) {
287 mCameraSettings.unregisterOnSharedPreferenceChangeListener(listener);
290 if (mDefaultSettings != null) {
291 mDefaultSettings.unregisterOnSharedPreferenceChangeListener(listener);
294 mSharedPreferenceListeners.clear();
299 * SettingsCapabilities defines constraints around settings that need to be
300 * queried from external sources, like the camera parameters. This interface
301 * is camera api agnostic.
303 public interface SettingsCapabilities {
305 * Returns a dynamically calculated list of exposure values, based on
306 * the min and max exposure compensation supported by the camera device.
308 public String[] getSupportedExposureValues();
311 * Returns a list of camera ids based on the number of cameras available
314 public String[] getSupportedCameraIds();
318 * Get the camera id for which the SettingsManager has loaded camera
319 * specific preferences.
321 public int getRegisteredCameraId() {
325 // Manage individual settings.
326 public static final String VALUE_NONE = "none";
327 public static final String VALUE_ON = "on";
328 public static final String VALUE_OFF = "off";
330 public static final String TYPE_STRING = "string";
331 public static final String TYPE_BOOLEAN = "boolean";
332 public static final String TYPE_INTEGER = "integer";
334 public static final String SOURCE_DEFAULT = "default";
335 public static final String SOURCE_GLOBAL = "global";
336 public static final String SOURCE_CAMERA = "camera";
337 public static final String SOURCE_MODULE = "module";
339 public static final boolean FLUSH_ON = true;
340 public static final boolean FLUSH_OFF = false;
342 // For quick lookup from id to Setting.
343 public static final int SETTING_RECORD_LOCATION = 0;
344 public static final int SETTING_VIDEO_QUALITY_BACK = 1;
345 public static final int SETTING_VIDEO_QUALITY_FRONT = 2;
346 public static final int SETTING_VIDEO_TIME_LAPSE_FRAME_INTERVAL = 3;
347 public static final int SETTING_PICTURE_SIZE_BACK = 4;
348 public static final int SETTING_PICTURE_SIZE_FRONT = 5;
349 public static final int SETTING_JPEG_QUALITY = 6;
350 public static final int SETTING_FOCUS_MODE = 7;
351 public static final int SETTING_FLASH_MODE = 8;
352 public static final int SETTING_VIDEOCAMERA_FLASH_MODE = 9;
353 public static final int SETTING_WHITE_BALANCE = 10;
354 public static final int SETTING_SCENE_MODE = 11;
355 public static final int SETTING_EXPOSURE = 12;
356 public static final int SETTING_TIMER = 13;
357 public static final int SETTING_TIMER_SOUND_EFFECTS = 14;
358 public static final int SETTING_VIDEO_EFFECT = 15;
359 public static final int SETTING_CAMERA_ID = 16;
360 public static final int SETTING_CAMERA_HDR = 17;
361 public static final int SETTING_CAMERA_HDR_PLUS = 18;
362 public static final int SETTING_CAMERA_FIRST_USE_HINT_SHOWN = 19;
363 public static final int SETTING_VIDEO_FIRST_USE_HINT_SHOWN = 20;
364 public static final int SETTING_STARTUP_MODULE_INDEX = 21;
365 public static final int SETTING_SHIMMY_REMAINING_PLAY_TIMES_INDEX = 22;
366 public static final int SETTING_KEY_CAMERA_MODULE_LAST_USED_INDEX = 23;
367 public static final int SETTING_CAMERA_PANO_ORIENTATION = 24;
368 public static final int SETTING_CAMERA_GRID_LINES = 25;
369 public static final int SETTING_RELEASE_DIALOG_LAST_SHOWN_VERSION = 26;
370 public static final int SETTING_FLASH_SUPPORTED_BACK_CAMERA = 27;
371 public static final int SETTING_STRICT_UPGRADE_VERSION = 28;
372 public static final int SETTING_FILMSTRIP_PEEK_ANIM_REMAINING_PLAY_TIMES_INDEX = 29;
373 // A boolean for requesting to return to HDR plus
374 // as soon as possible, if a user requests a setting/mode option
375 // that forces them to leave HDR plus.
376 public static final int SETTING_REQUEST_RETURN_HDR_PLUS = 30;
378 // Shared preference keys.
379 public static final String KEY_RECORD_LOCATION = "pref_camera_recordlocation_key";
380 public static final String KEY_VIDEO_QUALITY_BACK = "pref_video_quality_back_key";
381 public static final String KEY_VIDEO_QUALITY_FRONT = "pref_video_quality_front_key";
382 public static final String KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL =
383 "pref_video_time_lapse_frame_interval_key";
384 public static final String KEY_PICTURE_SIZE_BACK = "pref_camera_picturesize_back_key";
385 public static final String KEY_PICTURE_SIZE_FRONT = "pref_camera_picturesize_front_key";
386 public static final String KEY_JPEG_QUALITY = "pref_camera_jpegquality_key";
387 public static final String KEY_FOCUS_MODE = "pref_camera_focusmode_key";
388 public static final String KEY_FLASH_MODE = "pref_camera_flashmode_key";
389 public static final String KEY_VIDEOCAMERA_FLASH_MODE = "pref_camera_video_flashmode_key";
390 public static final String KEY_WHITE_BALANCE = "pref_camera_whitebalance_key";
391 public static final String KEY_SCENE_MODE = "pref_camera_scenemode_key";
392 public static final String KEY_EXPOSURE = "pref_camera_exposure_key";
393 public static final String KEY_TIMER = "pref_camera_timer_key";
394 public static final String KEY_TIMER_SOUND_EFFECTS = "pref_camera_timer_sound_key";
395 public static final String KEY_VIDEO_EFFECT = "pref_video_effect_key";
396 public static final String KEY_CAMERA_ID = "pref_camera_id_key";
397 public static final String KEY_CAMERA_HDR = "pref_camera_hdr_key";
398 public static final String KEY_CAMERA_HDR_PLUS = "pref_camera_hdr_plus_key";
399 public static final String KEY_CAMERA_FIRST_USE_HINT_SHOWN =
400 "pref_camera_first_use_hint_shown_key";
401 public static final String KEY_VIDEO_FIRST_USE_HINT_SHOWN =
402 "pref_video_first_use_hint_shown_key";
403 public static final String KEY_STARTUP_MODULE_INDEX = "camera.startup_module";
404 public static final String KEY_SHIMMY_REMAINING_PLAY_TIMES =
405 "pref_shimmy_remaining_play_times";
406 public static final String KEY_CAMERA_MODULE_LAST_USED =
407 "pref_camera_module_last_used_index";
408 public static final String KEY_CAMERA_PANO_ORIENTATION = "pref_camera_pano_orientation";
409 public static final String KEY_CAMERA_GRID_LINES = "pref_camera_grid_lines";
410 public static final String KEY_RELEASE_DIALOG_LAST_SHOWN_VERSION =
411 "pref_release_dialog_last_shown_version";
412 public static final String KEY_FLASH_SUPPORTED_BACK_CAMERA =
413 "pref_flash_supported_back_camera";
414 public static final String KEY_STRICT_UPGRADE_VERSION = "pref_strict_upgrade_version";
415 public static final String KEY_FILMSTRIP_PEEK_ANIM_REMAINING_PLAY_TIMES =
416 "pref_filmstrip_peek_anim_remaining_play_times";
417 public static final String KEY_REQUEST_RETURN_HDR_PLUS = "pref_request_return_hdr_plus";
419 public static final int WHITE_BALANCE_DEFAULT_INDEX = 2;
422 * Defines a simple class for holding a the spec of a setting. This spec is
423 * used by the generic api methods to query and update a setting.
425 public static class Setting {
426 private final String mSource;
427 private final String mType;
428 private final String mDefault;
429 private final String mKey;
430 private final String[] mValues;
431 private final boolean mFlushOnCameraChange;
434 * A constructor used to store a setting's profile.
436 public Setting(String source, String type, String defaultValue, String key,
437 String[] values, boolean flushOnCameraChange) {
440 mDefault = defaultValue;
443 mFlushOnCameraChange = flushOnCameraChange;
447 * Returns the id of a SharedPreferences instance from which this
448 * Setting may be found. Possible values are {@link #SOURCE_DEFAULT},
449 * {@link #SOURCE_GLOBAL}, {@link #SOURCE_CAMERA}.
451 public String getSource() {
456 * Returns the type of the setting stored in SharedPreferences. Possible
457 * values are {@link #TYPE_STRING}, {@link #TYPE_INTEGER},
458 * {@link #TYPE_BOOLEAN}.
460 public String getType() {
465 * Returns the default value of this setting.
467 public String getDefault() {
472 * Returns the SharedPreferences key for this setting.
474 public String getKey() {
479 * Returns an array of possible String values for this setting. If this
480 * setting is not of type {@link #TYPE_STRING}, or it's not possible to
481 * generate the string values, this should return null;
483 public String[] getStringValues() {
488 * Returns whether the setting should be flushed from the cache when the
489 * camera device has changed.
491 public boolean isFlushedOnCameraChanged() {
492 return mFlushOnCameraChange;
497 * Get the SharedPreferences needed to query/update the setting.
499 public SharedPreferences getSettingSource(Setting setting) {
500 return getSettingSource(setting.getSource());
503 private SharedPreferences getSettingSource(String source) {
504 if (source.equals(SOURCE_DEFAULT)) {
505 return mDefaultSettings;
507 if (source.equals(SOURCE_GLOBAL)) {
508 return mGlobalSettings;
510 if (source.equals(SOURCE_CAMERA)) {
511 return mCameraSettings;
513 if (source.equals(SOURCE_MODULE)) {
514 int modeIndex = CameraUtil.getCameraModeParentModeId(
515 mAppController.getCurrentModuleIndex(), mAppController.getAndroidContext());
516 return getModulePreferences(modeIndex);
522 * Based on Setting id, finds the index of a Setting's String value in an
523 * array of possible String values. If the Setting is not of type String,
526 * TODO: make this a supported api call for all types.
529 public int getStringValueIndex(int id) {
530 Setting setting = mSettingsCache.get(id);
531 if (setting == null || !TYPE_STRING.equals(setting.getType())) {
534 return getStringValueIndex(setting.getStringValues(), get(id));
537 private int getStringValueIndex(String[] possibleValues, String value) {
539 if (possibleValues != null) {
540 for (int i = 0; i < possibleValues.length; i++) {
541 if (value.equals(possibleValues[i])) {
551 * Based on Setting id, sets a Setting's String value using the index into
552 * an array of possible String values. Fails to set a value if the index is
553 * out of bounds or the Setting is not of type String.
555 * @return Whether the value was set.
557 public boolean setStringValueIndex(int id, int index) {
558 Setting setting = mSettingsCache.get(id);
559 if (setting == null || setting.getType() != TYPE_STRING) {
563 String[] possibleValues = setting.getStringValues();
564 if (possibleValues != null) {
565 if (index >= 0 && index < possibleValues.length) {
566 set(id, possibleValues[index]);
574 * Returns whether this Setting was last set as a String.
576 private boolean isString(int id, String source) {
577 Setting setting = mSettingsCache.get(id);
578 SharedPreferences preferences = getSettingSource(source);
580 preferences.getString(setting.getKey(), null);
582 } catch (ClassCastException e) {
588 * Returns whether this Setting was last set as a boolean.
590 private boolean isBoolean(int id, String source) {
591 Setting setting = mSettingsCache.get(id);
592 SharedPreferences preferences = getSettingSource(source);
594 preferences.getBoolean(setting.getKey(), false);
596 } catch (ClassCastException e) {
602 * Returns whether this Setting was last set as an Integer.
604 private boolean isInteger(int id, String source) {
605 Setting setting = mSettingsCache.get(id);
606 SharedPreferences preferences = getSettingSource(source);
608 preferences.getInt(setting.getKey(), 0);
610 } catch (NumberFormatException e) {
616 * Recover a Setting by converting it to a String if the type
617 * is known and the type conversion is successful, otherwise
618 * reset to the default.
620 private String recoverToString(int id, String source) {
623 if (isBoolean(id, source)) {
624 value = (getBoolean(id, source) ? VALUE_ON : VALUE_OFF);
625 } else if (isInteger(id, source)) {
626 value = Integer.toString(getInt(id, source));
628 throw new Exception();
630 } catch (Exception e) {
631 value = mSettingsCache.get(id).getDefault();
633 set(id, source, value);
638 * Recover a Setting by converting it to a boolean if the type
639 * is known and the type conversion is successful, otherwise
640 * reset to the default.
642 private boolean recoverToBoolean(int id, String source) {
645 if (isString(id, source)) {
646 value = VALUE_ON.equals(get(id, source));
647 } else if (isInteger(id, source)) {
648 value = getInt(id, source) != 0;
650 throw new Exception();
652 } catch (Exception e) {
653 value = VALUE_ON.equals(mSettingsCache.get(id).getDefault());
655 setBoolean(id, source, value);
660 * Recover a Setting by converting it to an Integer if the type
661 * is known and the type conversion is successful, otherwise
662 * reset to the default.
664 private int recoverToInteger(int id, String source) {
667 if (isString(id, source)) {
668 value = Integer.parseInt(get(id, source));
669 } else if (isBoolean(id, source)) {
670 value = getBoolean(id, source) ? 1 : 0;
672 throw new Exception();
674 } catch (Exception e) {
675 value = Integer.parseInt(mSettingsCache.get(id).getDefault());
682 * Check if a String value is in the set of possible values for a Setting.
683 * We only keep track of possible values for String types for now.
685 private String sanitize(Setting setting, String value) {
686 if (setting.getStringValues() != null &&
687 getStringValueIndex(setting.getStringValues(), value) < 0) {
688 // If the set of possible values is not empty, and the value
689 // is not in the set of possible values, use the default, because
690 // the set of possible values probably changed.
691 return setting.getDefault();
697 * Get a Setting's String value based on Setting id.
699 // TODO: rename to something more descriptive like getString.
700 public String get(int id) {
701 Setting setting = mSettingsCache.get(id);
702 return get(id, setting.getSource());
706 * Get a Setting's String value based on Setting id and a source file id.
708 public String get(int id, String source) {
709 Setting setting = mSettingsCache.get(id);
710 SharedPreferences preferences = getSettingSource(source);
711 if (preferences != null) {
713 String value = preferences.getString(setting.getKey(), setting.getDefault());
714 return sanitize(setting, value);
715 } catch (ClassCastException e) {
716 // If the api defines this Setting as a String, but the
717 // last set saved it as a different type, try to recover
718 // the value, but if impossible reset to default.
719 return recoverToString(id, source);
722 throw new IllegalStateException(
723 "Setting source=" + source + " is unitialized.");
728 * Get a Setting's boolean value based on Setting id.
730 public boolean getBoolean(int id) {
731 Setting setting = mSettingsCache.get(id);
732 return getBoolean(id, setting.getSource());
736 * Get a Setting's boolean value based on a Setting id and a source file id.
738 public boolean getBoolean(int id, String source) {
739 Setting setting = mSettingsCache.get(id);
740 SharedPreferences preferences = getSettingSource(source);
741 boolean defaultValue = VALUE_ON.equals(setting.getDefault());
742 if (preferences != null) {
744 return preferences.getBoolean(setting.getKey(), defaultValue);
745 } catch (ClassCastException e) {
746 // If the api defines this Setting as a boolean, but the
747 // last set saved it as a different type, try to recover
748 // the value, but if impossible reset to default.
749 return recoverToBoolean(id, source);
752 throw new IllegalStateException(
753 "Setting source=" + source + " is unitialized.");
758 * Get a Setting's int value based on Setting id.
760 public int getInt(int id) {
761 Setting setting = mSettingsCache.get(id);
762 return getInt(id, setting.getSource());
766 * Get a Setting's int value based on Setting id and a source file id.
768 public int getInt(int id, String source) {
769 Setting setting = mSettingsCache.get(id);
770 SharedPreferences preferences = getSettingSource(source);
771 int defaultValue = Integer.parseInt(setting.getDefault());
772 if (preferences != null) {
774 return preferences.getInt(setting.getKey(), defaultValue);
775 } catch (NumberFormatException e) {
776 // If the api defines this Setting as an Integer, but the
777 // last set saved it as a different type, try to recover
778 // the value, but if impossible reset to default.
779 return recoverToInteger(id, source);
782 throw new IllegalStateException(
783 "Setting source=" + source + " is unitialized.");
788 * Set a Setting with a String value based on Setting id.
790 // TODO: rename to something more descriptive.
791 public void set(int id, String value) {
792 Setting setting = mSettingsCache.get(id);
793 set(id, setting.getSource(), value);
797 * Set a Setting with a String value based on Setting id and a source file id.
799 public void set(int id, String source, String value) {
800 Setting setting = mSettingsCache.get(id);
801 value = sanitize(setting, value);
802 SharedPreferences preferences = getSettingSource(source);
803 if (preferences != null) {
804 preferences.edit().putString(setting.getKey(), value).apply();
806 throw new IllegalStateException(
807 "Setting source=" + source + " is unitialized.");
812 * Set a Setting with a boolean value based on Setting id.
814 public void setBoolean(int id, boolean value) {
815 Setting setting = mSettingsCache.get(id);
816 setBoolean(id, setting.getSource(), value);
819 * Set a Setting with a boolean value based on Setting id and a source file id.
821 public void setBoolean(int id, String source, boolean value) {
822 Setting setting = mSettingsCache.get(id);
823 SharedPreferences preferences = getSettingSource(source);
824 if (preferences != null) {
825 preferences.edit().putBoolean(setting.getKey(), value).apply();
827 throw new IllegalStateException(
828 "Setting source=" + source + " is unitialized.");
833 * Set a Setting with an int value based on Setting id.
835 public void setInt(int id, int value) {
836 Setting setting = mSettingsCache.get(id);
837 setInt(id, setting.getSource(), value);
841 * Set a Setting with an int value based on Setting id and a source file id.
843 public void setInt(int id, String source, int value) {
844 Setting setting = mSettingsCache.get(id);
845 SharedPreferences preferences = getSettingSource(source);
846 if (preferences != null) {
847 preferences.edit().putInt(setting.getKey(), value).apply();
849 throw new IllegalStateException(
850 "Setting source=" + source + " is unitialized.");
855 * Check if a Setting has ever been set based on Setting id.
857 public boolean isSet(int id) {
858 Setting setting = mSettingsCache.get(id);
859 return isSet(id, setting.getSource());
863 * Check if a Setting has ever been set based on Setting id and a source file id.
865 public boolean isSet(int id, String source) {
866 Setting setting = mSettingsCache.get(id);
867 SharedPreferences preferences = getSettingSource(source);
868 if (preferences != null) {
869 return preferences.contains(setting.getKey());
871 throw new IllegalStateException(
872 "Setting source=" + setting.getSource() + " is unitialized.");
877 * Set a Setting to its default value based on Setting id.
879 public void setDefault(int id) {
880 Setting setting = mSettingsCache.get(id);
881 SharedPreferences preferences = getSettingSource(setting);
882 if (preferences != null) {
883 preferences.edit().putString(setting.getKey(), setting.getDefault());
885 throw new IllegalStateException(
886 "Setting source=" + setting.getSource() + " is unitialized.");
891 * Check if a Setting is set to its default value.
893 public boolean isDefault(int id) {
894 Setting setting = mSettingsCache.get(id);
895 SharedPreferences preferences = getSettingSource(setting);
896 if (preferences != null) {
897 String type = setting.getType();
898 if (TYPE_STRING.equals(type)) {
899 String value = get(id);
900 return (value.equals(setting.getDefault()));
901 } else if (TYPE_BOOLEAN.equals(type)) {
902 boolean value = getBoolean(id);
903 boolean defaultValue = VALUE_ON.equals(setting.getDefault());
904 return (value == defaultValue);
905 } else if (TYPE_INTEGER.equals(type)) {
906 int value = getInt(id);
907 int defaultValue = Integer.parseInt(setting.getDefault());
908 return (value == defaultValue);
910 throw new IllegalArgumentException("Type " + type + " is not known.");
913 throw new IllegalStateException(
914 "Setting source=" + setting.getSource() + " is unitialized.");
919 * Remove a Setting from SharedPreferences.
921 public void remove(int id) {
922 Setting setting = mSettingsCache.get(id);
923 SharedPreferences preferences = getSettingSource(setting);
924 if (preferences != null) {
925 preferences.edit().remove(setting.getKey()).apply();
927 throw new IllegalStateException(
928 "Setting source=" + setting.getSource() + " is unitialized.");
932 public static Setting getLocationSetting(Context context) {
933 String defaultValue = context.getString(R.string.setting_none_value);
934 String[] values = null;
935 return new Setting(SOURCE_DEFAULT, TYPE_BOOLEAN, defaultValue, KEY_RECORD_LOCATION,
939 public static Setting getPictureSizeBackSetting(Context context) {
940 String defaultValue = null;
941 String[] values = context.getResources().getStringArray(
942 R.array.pref_camera_picturesize_entryvalues);
943 return new Setting(SOURCE_DEFAULT, TYPE_STRING, defaultValue, KEY_PICTURE_SIZE_BACK,
947 public static Setting getPictureSizeFrontSetting(Context context) {
948 String defaultValue = null;
949 String[] values = context.getResources().getStringArray(
950 R.array.pref_camera_picturesize_entryvalues);
951 return new Setting(SOURCE_DEFAULT, TYPE_STRING, defaultValue, KEY_PICTURE_SIZE_FRONT,
955 public static Setting getDefaultCameraIdSetting(Context context,
956 SettingsCapabilities capabilities) {
957 String defaultValue = context.getString(R.string.pref_camera_id_default);
958 String[] values = null;
959 if (capabilities != null) {
960 values = capabilities.getSupportedCameraIds();
962 return new Setting(SOURCE_MODULE, TYPE_STRING, defaultValue, KEY_CAMERA_ID,
966 public static Setting getWhiteBalanceSetting(Context context) {
967 String defaultValue = context.getString(R.string.pref_camera_whitebalance_default);
968 String[] values = context.getResources().getStringArray(
969 R.array.pref_camera_whitebalance_entryvalues);
970 return new Setting(SOURCE_CAMERA, TYPE_STRING, defaultValue, KEY_WHITE_BALANCE,
974 public static Setting getHdrSetting(Context context) {
975 String defaultValue = context.getString(R.string.pref_camera_hdr_default);
976 String[] values = context.getResources().getStringArray(
977 R.array.pref_camera_hdr_entryvalues);
978 return new Setting(SOURCE_GLOBAL, TYPE_STRING, defaultValue, KEY_CAMERA_HDR,
982 public static Setting getHdrPlusSetting(Context context) {
983 String defaultValue = context.getString(R.string.pref_camera_hdr_plus_default);
984 String[] values = context.getResources().getStringArray(
985 R.array.pref_camera_hdr_plus_entryvalues);
986 return new Setting(SOURCE_GLOBAL, TYPE_STRING, defaultValue, KEY_CAMERA_HDR_PLUS,
990 public static Setting getSceneModeSetting(Context context) {
991 String defaultValue = context.getString(R.string.pref_camera_scenemode_default);
992 String[] values = context.getResources().getStringArray(
993 R.array.pref_camera_scenemode_entryvalues);
994 return new Setting(SOURCE_CAMERA, TYPE_STRING, defaultValue, KEY_SCENE_MODE,
998 public static Setting getFlashSetting(Context context) {
999 String defaultValue = context.getString(R.string.pref_camera_flashmode_default);
1000 String[] values = context.getResources().getStringArray(
1001 R.array.pref_camera_flashmode_entryvalues);
1002 return new Setting(SOURCE_CAMERA, TYPE_STRING, defaultValue, KEY_FLASH_MODE,
1006 public static Setting getExposureSetting(Context context,
1007 SettingsCapabilities capabilities) {
1008 String defaultValue = context.getString(R.string.pref_exposure_default);
1009 String[] values = null;
1010 if (capabilities != null) {
1011 values = capabilities.getSupportedExposureValues();
1013 return new Setting(SOURCE_CAMERA, TYPE_STRING, defaultValue, KEY_EXPOSURE,
1017 public static Setting getHintSetting(Context context) {
1018 String defaultValue = context.getString(R.string.setting_on_value);
1019 String[] values = null;
1020 return new Setting(SOURCE_GLOBAL, TYPE_BOOLEAN, defaultValue,
1021 KEY_CAMERA_FIRST_USE_HINT_SHOWN, values, FLUSH_OFF);
1024 public static Setting getFocusModeSetting(Context context) {
1025 String defaultValue = null;
1026 String[] values = context.getResources().getStringArray(
1027 R.array.pref_camera_focusmode_entryvalues);
1028 return new Setting(SOURCE_CAMERA, TYPE_STRING, defaultValue, KEY_FOCUS_MODE,
1032 public static Setting getTimerSetting(Context context) {
1033 String defaultValue = context.getString(R.string.pref_camera_timer_default);
1034 String[] values = null; // TODO: get the values dynamically.
1035 return new Setting(SOURCE_GLOBAL, TYPE_STRING, defaultValue, KEY_TIMER,
1039 public static Setting getTimerSoundSetting(Context context) {
1040 String defaultValue = context.getString(R.string.pref_camera_timer_sound_default);
1041 String[] values = context.getResources().getStringArray(
1042 R.array.pref_camera_timer_sound_entryvalues);
1043 return new Setting(SOURCE_GLOBAL, TYPE_STRING, defaultValue, KEY_TIMER_SOUND_EFFECTS,
1047 public static Setting getVideoQualityBackSetting(Context context) {
1048 String defaultValue = context.getString(R.string.pref_video_quality_default);
1049 String[] values = context.getResources().getStringArray(
1050 R.array.pref_video_quality_entryvalues);
1051 return new Setting(SOURCE_DEFAULT, TYPE_STRING, defaultValue, KEY_VIDEO_QUALITY_BACK,
1055 public static Setting getVideoQualityFrontSetting(Context context) {
1056 String defaultValue = context.getString(R.string.pref_video_quality_default);
1057 String[] values = context.getResources().getStringArray(
1058 R.array.pref_video_quality_entryvalues);
1059 return new Setting(SOURCE_DEFAULT, TYPE_STRING, defaultValue, KEY_VIDEO_QUALITY_FRONT,
1063 public static Setting getTimeLapseFrameIntervalSetting(Context context) {
1064 String defaultValue = context.getString(
1065 R.string.pref_video_time_lapse_frame_interval_default);
1066 String[] values = context.getResources().getStringArray(
1067 R.array.pref_video_time_lapse_frame_interval_entryvalues);
1068 return new Setting(SOURCE_GLOBAL, TYPE_STRING, defaultValue,
1069 KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL, values, FLUSH_OFF);
1072 public static Setting getJpegQualitySetting(Context context) {
1073 String defaultValue = context.getString(
1074 R.string.pref_camera_jpeg_quality_normal);
1075 String[] values = context.getResources().getStringArray(
1076 R.array.pref_camera_jpeg_quality_entryvalues);
1077 return new Setting(SOURCE_CAMERA, TYPE_STRING, defaultValue, KEY_JPEG_QUALITY,
1081 public static Setting getVideoFlashSetting(Context context) {
1082 String defaultValue = context.getString(R.string.pref_camera_video_flashmode_default);
1083 String[] values = context.getResources().getStringArray(
1084 R.array.pref_camera_video_flashmode_entryvalues);
1085 return new Setting(SOURCE_CAMERA, TYPE_STRING, defaultValue,
1086 KEY_VIDEOCAMERA_FLASH_MODE, values, FLUSH_OFF);
1089 public static Setting getVideoEffectSetting(Context context) {
1090 String defaultValue = context.getString(R.string.pref_video_effect_default);
1091 String[] values = context.getResources().getStringArray(
1092 R.array.pref_video_effect_entryvalues);
1093 return new Setting(SOURCE_GLOBAL, TYPE_STRING, defaultValue, KEY_VIDEO_EFFECT,
1097 public static Setting getHintVideoSetting(Context context) {
1098 String defaultValue = context.getString(R.string.setting_on_value);
1099 String[] values = null;
1100 return new Setting(SOURCE_GLOBAL, TYPE_STRING, defaultValue,
1101 KEY_VIDEO_FIRST_USE_HINT_SHOWN, values, FLUSH_OFF);
1104 public static Setting getStartupModuleSetting(Context context) {
1105 String defaultValue = context.getString(R.string.pref_camera_startup_index_default);
1106 String[] values = null;
1107 return new Setting(SOURCE_DEFAULT, TYPE_INTEGER, defaultValue,
1108 KEY_STARTUP_MODULE_INDEX, values, FLUSH_OFF);
1111 public static Setting getShimmyRemainingTimesSetting(Context context) {
1112 String defaultValue = context.getString(R.string.pref_shimmy_play_times);
1113 return new Setting(SOURCE_DEFAULT, TYPE_INTEGER, defaultValue,
1114 KEY_SHIMMY_REMAINING_PLAY_TIMES, null, FLUSH_OFF);
1117 public static Setting getLastUsedCameraModule(Context context) {
1118 String defaultValue = Integer.toString(context.getResources()
1119 .getInteger(R.integer.camera_mode_photo));
1120 return new Setting(SOURCE_DEFAULT, TYPE_INTEGER, defaultValue,
1121 KEY_CAMERA_MODULE_LAST_USED, null, FLUSH_OFF);
1124 public static Setting getPanoOrientationSetting(Context context) {
1125 String defaultValue = context.getString(R.string.pano_orientation_horizontal);
1126 String[] values = context.getResources().getStringArray(
1127 R.array.pref_camera_pano_orientation_entryvalues);
1128 return new Setting(SOURCE_GLOBAL, TYPE_STRING, defaultValue,
1129 KEY_CAMERA_PANO_ORIENTATION, values, FLUSH_OFF);
1132 public static Setting getGridLinesSetting(Context context) {
1133 String defaultValue = context.getString(R.string.setting_off_value);
1134 String[] values = context.getResources().getStringArray(
1135 R.array.pref_camera_gridlines_entryvalues);
1136 return new Setting(SOURCE_GLOBAL, TYPE_STRING, defaultValue,
1137 KEY_CAMERA_GRID_LINES, values, FLUSH_OFF);
1140 public static Setting getReleaseDialogLastShownVersionSetting(Context context) {
1141 return new Setting(SOURCE_DEFAULT, TYPE_STRING, null,
1142 KEY_RELEASE_DIALOG_LAST_SHOWN_VERSION, null, FLUSH_OFF);
1145 public static Setting getFlashSupportedBackCameraSetting(Context context) {
1146 String defaultValue = context.getString(R.string.setting_none_value);
1147 return new Setting(SOURCE_GLOBAL, TYPE_BOOLEAN, defaultValue,
1148 KEY_FLASH_SUPPORTED_BACK_CAMERA, null, FLUSH_OFF);
1151 public static Setting getStrictUpgradeVersionSetting(Context context) {
1152 String defaultValue = "0";
1153 return new Setting(SOURCE_DEFAULT, TYPE_INTEGER, defaultValue,
1154 KEY_STRICT_UPGRADE_VERSION, null, FLUSH_OFF);
1157 public static Setting getPeekAnimRemainingTimesSetting(Context context) {
1158 String defaultValue = context.getString(R.string.pref_filmstrip_peek_anim_play_times);
1159 return new Setting(SOURCE_DEFAULT, TYPE_INTEGER, defaultValue,
1160 KEY_FILMSTRIP_PEEK_ANIM_REMAINING_PLAY_TIMES, null, FLUSH_OFF);
1163 public static Setting getRequestReturnHdrPlusSetting(Context context) {
1164 String defaultValue = context.getString(R.string.setting_none_value);
1165 return new Setting(SOURCE_MODULE, TYPE_BOOLEAN, VALUE_OFF,
1166 KEY_REQUEST_RETURN_HDR_PLUS, null, FLUSH_OFF);
1172 * Returns whether the camera has been set to back facing in settings.
1174 public boolean isCameraBackFacing() {
1175 String cameraFacing = get(SETTING_CAMERA_ID);
1176 String backFacing = mContext.getString(R.string.pref_camera_id_default);
1177 return (Integer.parseInt(cameraFacing) == Integer.parseInt(backFacing));
1181 * Returns whether hdr plus mode is set on.
1183 public boolean isHdrPlusOn() {
1184 String hdrOn = get(SettingsManager.SETTING_CAMERA_HDR);
1185 return hdrOn.equals(SettingsManager.VALUE_ON);
1189 * Returns whether the app should return to hdr plus mode if possible.
1191 public boolean requestsReturnToHdrPlus() {
1192 return getBoolean(SettingsManager.SETTING_REQUEST_RETURN_HDR_PLUS);
1196 * Returns whether grid lines are set on.
1198 public boolean areGridLinesOn() {
1199 String gridLinesOn = get(SettingsManager.SETTING_CAMERA_GRID_LINES);
1200 return gridLinesOn.equals(SettingsManager.VALUE_ON);
1204 * Returns whether pano orientation is horizontal.
1206 public boolean isPanoOrientationHorizontal() {
1207 String orientation = get(SettingsManager.SETTING_CAMERA_PANO_ORIENTATION);
1208 String horizontal = mContext.getString(R.string.pano_orientation_horizontal);
1209 return orientation.equals(horizontal);
1212 // TODO: refactor this into a separate utils module.
1215 * Get a String value from first the ListPreference, and if not found from
1216 * the SettingsManager. This is a wrapper that adds backwards compatibility
1217 * to views that rely on PreferenceGroups.
1219 public String getValueFromPreference(ListPreference pref) {
1220 String value = pref.getValue();
1221 if (value == null) {
1222 Integer id = mSettingsCache.getId(pref.getKey());
1232 * Set a String value first from the ListPreference, and if unable from the
1233 * SettingsManager. This is a wrapper that adds backwards compatibility to
1234 * views that rely on PreferenceGroups.
1236 public void setValueFromPreference(ListPreference pref, String value) {
1237 boolean set = pref.setValue(value);
1239 Integer id = mSettingsCache.getId(pref.getKey());
1247 * Set a String value first from the ListPreference based on a
1248 * ListPreference index, and if unable use the ListPreference key to set the
1249 * value using the SettingsManager. This is a wrapper that adds backwards
1250 * compatibility to views that rely on PreferenceGroups.
1252 public void setValueIndexFromPreference(ListPreference pref, int index) {
1253 boolean set = pref.setValueIndex(index);
1255 Integer id = mSettingsCache.getId(pref.getKey());
1257 String value = pref.getValueAtIndex(index);
1264 * Sets the settings for whether location recording should be enabled or
1265 * not. Also makes sure to pass on the change to the location manager.
1267 public void setLocation(boolean on, LocationManager locationManager) {
1268 setBoolean(SettingsManager.SETTING_RECORD_LOCATION, on);
1269 locationManager.recordLocation(on);
1273 * Reads the current location recording settings and passes it on to the
1274 * given location manager.
1276 public void syncLocationManager(LocationManager locationManager) {
1277 boolean value = getBoolean(SettingsManager.SETTING_RECORD_LOCATION);
1278 locationManager.recordLocation(value);