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_CAMERA_FIRST_USE_HINT_SHOWN) 80 || key.equals(CameraSettings.KEY_VIDEO_FIRST_USE_HINT_SHOWN) 81 || key.equals(CameraSettings.KEY_VIDEO_EFFECT); 82 } 83 84 public String getString(String key, String defValue) { 85 if (isGlobal(key) || !mPrefLocal.contains(key)) { 86 return mPrefGlobal.getString(key, defValue); 87 } else { 88 return mPrefLocal.getString(key, defValue); 89 } 90 } 91 92 public int getInt(String key, int defValue) { 93 if (isGlobal(key) || !mPrefLocal.contains(key)) { 94 return mPrefGlobal.getInt(key, defValue); 95 } else { 96 return mPrefLocal.getInt(key, defValue); 97 } 98 } 99 100 public long getLong(String key, long defValue) { 101 if (isGlobal(key) || !mPrefLocal.contains(key)) { 102 return mPrefGlobal.getLong(key, defValue); 103 } else { 104 return mPrefLocal.getLong(key, defValue); 105 } 106 } 107 108 public float getFloat(String key, float defValue) { 109 if (isGlobal(key) || !mPrefLocal.contains(key)) { 110 return mPrefGlobal.getFloat(key, defValue); 111 } else { 112 return mPrefLocal.getFloat(key, defValue); 113 } 114 } 115 116 public boolean getBoolean(String key, boolean defValue) { 117 if (isGlobal(key) || !mPrefLocal.contains(key)) { 118 return mPrefGlobal.getBoolean(key, defValue); 119 } else { 120 return mPrefLocal.getBoolean(key, defValue); 121 } 122 } 123 124 // This method is not used. 125 public Set<String> getStringSet(String key, Set<String> defValues) { 126 throw new UnsupportedOperationException(); 127 } 128 129 public boolean contains(String key) { 130 if (mPrefLocal.contains(key)) return true; 131 if (mPrefGlobal.contains(key)) return true; 132 return false; 133 } 134 135 private class MyEditor implements Editor { 136 private Editor mEditorGlobal; 137 private Editor mEditorLocal; 138 139 MyEditor() { 140 mEditorGlobal = mPrefGlobal.edit(); 141 mEditorLocal = mPrefLocal.edit(); 142 } 143 144 public boolean commit() { 145 boolean result1 = mEditorGlobal.commit(); 146 boolean result2 = mEditorLocal.commit(); 147 return result1 && result2; 148 } 149 150 public void apply() { 151 mEditorGlobal.apply(); 152 mEditorLocal.apply(); 153 } 154 155 // Note: clear() and remove() affects both local and global preferences. 156 public Editor clear() { 157 mEditorGlobal.clear(); 158 mEditorLocal.clear(); 159 return this; 160 } 161 162 public Editor remove(String key) { 163 mEditorGlobal.remove(key); 164 mEditorLocal.remove(key); 165 return this; 166 } 167 168 public Editor putString(String key, String value) { 169 if (isGlobal(key)) { 170 mEditorGlobal.putString(key, value); 171 } else { 172 mEditorLocal.putString(key, value); 173 } 174 return this; 175 } 176 177 public Editor putInt(String key, int value) { 178 if (isGlobal(key)) { 179 mEditorGlobal.putInt(key, value); 180 } else { 181 mEditorLocal.putInt(key, value); 182 } 183 return this; 184 } 185 186 public Editor putLong(String key, long value) { 187 if (isGlobal(key)) { 188 mEditorGlobal.putLong(key, value); 189 } else { 190 mEditorLocal.putLong(key, value); 191 } 192 return this; 193 } 194 195 public Editor putFloat(String key, float value) { 196 if (isGlobal(key)) { 197 mEditorGlobal.putFloat(key, value); 198 } else { 199 mEditorLocal.putFloat(key, value); 200 } 201 return this; 202 } 203 204 public Editor putBoolean(String key, boolean value) { 205 if (isGlobal(key)) { 206 mEditorGlobal.putBoolean(key, value); 207 } else { 208 mEditorLocal.putBoolean(key, value); 209 } 210 return this; 211 } 212 213 // This method is not used. 214 public Editor putStringSet(String key, Set<String> values) { 215 throw new UnsupportedOperationException(); 216 } 217 } 218 219 // Note the remove() and clear() of the returned Editor may not work as 220 // expected because it doesn't touch the global preferences at all. 221 public Editor edit() { 222 return new MyEditor(); 223 } 224 225 public void registerOnSharedPreferenceChangeListener( 226 OnSharedPreferenceChangeListener listener) { 227 mListeners.add(listener); 228 } 229 230 public void unregisterOnSharedPreferenceChangeListener( 231 OnSharedPreferenceChangeListener listener) { 232 mListeners.remove(listener); 233 } 234 235 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, 236 String key) { 237 for (OnSharedPreferenceChangeListener listener : mListeners) { 238 listener.onSharedPreferenceChanged(this, key); 239 } 240 } 241 } 242