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 
ComboPreferences(Context context)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 
get(Context context)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.
setLocalId(Context context, int cameraId)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 
getGlobal()63     public SharedPreferences getGlobal() {
64         return mPrefGlobal;
65     }
66 
getLocal()67     public SharedPreferences getLocal() {
68         return mPrefLocal;
69     }
70 
getAll()71     public Map<String, ?> getAll() {
72         throw new UnsupportedOperationException(); // Can be implemented if needed.
73     }
74 
isGlobal(String key)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 
getString(String key, String defValue)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 
getInt(String key, int defValue)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 
getLong(String key, long defValue)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 
getFloat(String key, float defValue)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 
getBoolean(String key, boolean defValue)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.
getStringSet(String key, Set<String> defValues)125     public Set<String> getStringSet(String key, Set<String> defValues) {
126         throw new UnsupportedOperationException();
127     }
128 
contains(String key)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 
MyEditor()139         MyEditor() {
140             mEditorGlobal = mPrefGlobal.edit();
141             mEditorLocal = mPrefLocal.edit();
142         }
143 
commit()144         public boolean commit() {
145             boolean result1 = mEditorGlobal.commit();
146             boolean result2 = mEditorLocal.commit();
147             return result1 && result2;
148         }
149 
apply()150         public void apply() {
151             mEditorGlobal.apply();
152             mEditorLocal.apply();
153         }
154 
155         // Note: clear() and remove() affects both local and global preferences.
clear()156         public Editor clear() {
157             mEditorGlobal.clear();
158             mEditorLocal.clear();
159             return this;
160         }
161 
remove(String key)162         public Editor remove(String key) {
163             mEditorGlobal.remove(key);
164             mEditorLocal.remove(key);
165             return this;
166         }
167 
putString(String key, String value)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 
putInt(String key, int value)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 
putLong(String key, long value)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 
putFloat(String key, float value)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 
putBoolean(String key, boolean value)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.
putStringSet(String key, Set<String> values)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.
edit()221     public Editor edit() {
222         return new MyEditor();
223     }
224 
registerOnSharedPreferenceChangeListener( OnSharedPreferenceChangeListener listener)225     public void registerOnSharedPreferenceChangeListener(
226             OnSharedPreferenceChangeListener listener) {
227         mListeners.add(listener);
228     }
229 
unregisterOnSharedPreferenceChangeListener( OnSharedPreferenceChangeListener listener)230     public void unregisterOnSharedPreferenceChangeListener(
231             OnSharedPreferenceChangeListener listener) {
232         mListeners.remove(listener);
233     }
234 
onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)235     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
236             String key) {
237         for (OnSharedPreferenceChangeListener listener : mListeners) {
238             listener.onSharedPreferenceChanged(this, key);
239         }
240     }
241 }
242