1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 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 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 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. 15 */ 16 17 package com.android.camera; 18 19 import android.content.Context; 20 import android.content.SharedPreferences; 21 import android.content.SharedPreferences.OnSharedPreferenceChangeListener; 22 import android.preference.PreferenceManager; 23 24 import java.util.Map; 25 import java.util.Set; 26 import java.util.WeakHashMap; 27 import java.util.concurrent.CopyOnWriteArrayList; 28 29 public class ComboPreferences implements SharedPreferences, OnSharedPreferenceChangeListener { 30 private SharedPreferences mPrefGlobal; // global preferences 31 private SharedPreferences mPrefLocal; // per-camera preferences 32 private CopyOnWriteArrayList<OnSharedPreferenceChangeListener> mListeners; 33 private static WeakHashMap<Context, ComboPreferences> sMap = 34 new WeakHashMap<Context, ComboPreferences>(); 35 36 public ComboPreferences(Context context) { 37 mPrefGlobal = PreferenceManager.getDefaultSharedPreferences(context); 38 mPrefGlobal.registerOnSharedPreferenceChangeListener(this); 39 synchronized (sMap) { 40 sMap.put(context, this); 41 } 42 mListeners = new CopyOnWriteArrayList<OnSharedPreferenceChangeListener>(); 43 } 44 45 public static ComboPreferences get(Context context) { 46 synchronized (sMap) { 47 return sMap.get(context); 48 } 49 } 50 51 // Sets the camera id and reads its preferences. Each camera has its own 52 // preferences. 53 public void setLocalId(Context context, int cameraId) { 54 String prefName = context.getPackageName() + "_preferences_" + cameraId; 55 if (mPrefLocal != null) { 56 mPrefLocal.unregisterOnSharedPreferenceChangeListener(this); 57 } 58 mPrefLocal = context.getSharedPreferences( 59 prefName, Context.MODE_PRIVATE); 60 mPrefLocal.registerOnSharedPreferenceChangeListener(this); 61 } 62 63 public SharedPreferences getGlobal() { 64 return mPrefGlobal; 65 } 66 67 public SharedPreferences getLocal() { 68 return mPrefLocal; 69 } 70 71 public Map<String, ?> getAll() { 72 throw new UnsupportedOperationException(); // Can be implemented if needed. 73 } 74 75 private static boolean isGlobal(String key) { 76 return key.equals(CameraSettings.KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL) 77 || key.equals(CameraSettings.KEY_CAMERA_ID) 78 || key.equals(CameraSettings.KEY_RECORD_LOCATION) 79 || key.equals(CameraSettings.KEY_TAP_TO_FOCUS_PROMPT_SHOWN) 80 || key.equals(CameraSettings.KEY_VIDEO_EFFECT); 81 } 82 83 public String getString(String key, String defValue) { 84 if (isGlobal(key) || !mPrefLocal.contains(key)) { 85 return mPrefGlobal.getString(key, defValue); 86 } else { 87 return mPrefLocal.getString(key, defValue); 88 } 89 } 90 91 public int getInt(String key, int defValue) { 92 if (isGlobal(key) || !mPrefLocal.contains(key)) { 93 return mPrefGlobal.getInt(key, defValue); 94 } else { 95 return mPrefLocal.getInt(key, defValue); 96 } 97 } 98 99 public long getLong(String key, long defValue) { 100 if (isGlobal(key) || !mPrefLocal.contains(key)) { 101 return mPrefGlobal.getLong(key, defValue); 102 } else { 103 return mPrefLocal.getLong(key, defValue); 104 } 105 } 106 107 public float getFloat(String key, float defValue) { 108 if (isGlobal(key) || !mPrefLocal.contains(key)) { 109 return mPrefGlobal.getFloat(key, defValue); 110 } else { 111 return mPrefLocal.getFloat(key, defValue); 112 } 113 } 114 115 public boolean getBoolean(String key, boolean defValue) { 116 if (isGlobal(key) || !mPrefLocal.contains(key)) { 117 return mPrefGlobal.getBoolean(key, defValue); 118 } else { 119 return mPrefLocal.getBoolean(key, defValue); 120 } 121 } 122 123 // This method is not used. 124 public Set<String> getStringSet(String key, Set<String> defValues) { 125 throw new UnsupportedOperationException(); 126 } 127 128 public boolean contains(String key) { 129 if (mPrefLocal.contains(key)) return true; 130 if (mPrefGlobal.contains(key)) return true; 131 return false; 132 } 133 134 private class MyEditor implements Editor { 135 private Editor mEditorGlobal; 136 private Editor mEditorLocal; 137 138 MyEditor() { 139 mEditorGlobal = mPrefGlobal.edit(); 140 mEditorLocal = mPrefLocal.edit(); 141 } 142 143 public boolean commit() { 144 boolean result1 = mEditorGlobal.commit(); 145 boolean result2 = mEditorLocal.commit(); 146 return result1 && result2; 147 } 148 149 public void apply() { 150 mEditorGlobal.apply(); 151 mEditorLocal.apply(); 152 } 153 154 // Note: clear() and remove() affects both local and global preferences. 155 public Editor clear() { 156 mEditorGlobal.clear(); 157 mEditorLocal.clear(); 158 return this; 159 } 160 161 public Editor remove(String key) { 162 mEditorGlobal.remove(key); 163 mEditorLocal.remove(key); 164 return this; 165 } 166 167 public Editor putString(String key, String value) { 168 if (isGlobal(key)) { 169 mEditorGlobal.putString(key, value); 170 } else { 171 mEditorLocal.putString(key, value); 172 } 173 return this; 174 } 175 176 public Editor putInt(String key, int value) { 177 if (isGlobal(key)) { 178 mEditorGlobal.putInt(key, value); 179 } else { 180 mEditorLocal.putInt(key, value); 181 } 182 return this; 183 } 184 185 public Editor putLong(String key, long value) { 186 if (isGlobal(key)) { 187 mEditorGlobal.putLong(key, value); 188 } else { 189 mEditorLocal.putLong(key, value); 190 } 191 return this; 192 } 193 194 public Editor putFloat(String key, float value) { 195 if (isGlobal(key)) { 196 mEditorGlobal.putFloat(key, value); 197 } else { 198 mEditorLocal.putFloat(key, value); 199 } 200 return this; 201 } 202 203 public Editor putBoolean(String key, boolean value) { 204 if (isGlobal(key)) { 205 mEditorGlobal.putBoolean(key, value); 206 } else { 207 mEditorLocal.putBoolean(key, value); 208 } 209 return this; 210 } 211 212 // This method is not used. 213 public Editor putStringSet(String key, Set<String> values) { 214 throw new UnsupportedOperationException(); 215 } 216 } 217 218 // Note the remove() and clear() of the returned Editor may not work as 219 // expected because it doesn't touch the global preferences at all. 220 public Editor edit() { 221 return new MyEditor(); 222 } 223 224 public void registerOnSharedPreferenceChangeListener( 225 OnSharedPreferenceChangeListener listener) { 226 mListeners.add(listener); 227 } 228 229 public void unregisterOnSharedPreferenceChangeListener( 230 OnSharedPreferenceChangeListener listener) { 231 mListeners.remove(listener); 232 } 233 234 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, 235 String key) { 236 for (OnSharedPreferenceChangeListener listener : mListeners) { 237 listener.onSharedPreferenceChanged(this, key); 238 } 239 } 240 } 241