• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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.sdkstats;
18 
19 import com.android.prefs.AndroidLocation;
20 import com.android.prefs.AndroidLocation.AndroidLocationException;
21 
22 import org.eclipse.jface.preference.PreferenceStore;
23 
24 import java.io.File;
25 import java.io.FileOutputStream;
26 import java.io.IOException;
27 import java.util.Random;
28 
29 /**
30  * Manages persistence settings for DDMS.
31  *
32  * For convenience, this also stores persistence settings related to the "server stats" ping
33  * as well as some ADT settings that are SDK specific but not workspace specific.
34  */
35 public class DdmsPreferenceStore {
36 
37     public  final static String PING_OPT_IN = "pingOptIn";          //$NON-NLS-1$
38     private final static String PING_TIME   = "pingTime";           //$NON-NLS-1$
39     private final static String PING_ID     = "pingId";             //$NON-NLS-1$
40 
41     private final static String ADT_USED = "adtUsed";               //$NON-NLS-1$
42     private final static String LAST_SDK_PATH = "lastSdkPath";      //$NON-NLS-1$
43 
44     /**
45      * PreferenceStore for DDMS.
46      * Creation and usage must be synchronized on {@code DdmsPreferenceStore.class}.
47      * Don't use it directly, instead retrieve it via {@link #getPreferenceStore()}.
48      */
49     private static volatile PreferenceStore sPrefStore;
50 
DdmsPreferenceStore()51     public DdmsPreferenceStore() {
52     }
53 
54     /**
55      * Returns the DDMS {@link PreferenceStore}.
56      * This keeps a static reference on the store, so consequent calls will
57      * return always the same store.
58      */
getPreferenceStore()59     public PreferenceStore getPreferenceStore() {
60         synchronized (DdmsPreferenceStore.class) {
61             if (sPrefStore == null) {
62                 // get the location of the preferences
63                 String homeDir = null;
64                 try {
65                     homeDir = AndroidLocation.getFolder();
66                 } catch (AndroidLocationException e1) {
67                     // pass, we'll do a dummy store since homeDir is null
68                 }
69 
70                 if (homeDir == null) {
71                     sPrefStore = new PreferenceStore();
72                     return sPrefStore;
73                 }
74 
75                 assert homeDir != null;
76 
77                 String rcFileName = homeDir + "ddms.cfg";                       //$NON-NLS-1$
78 
79                 // also look for an old pref file in the previous location
80                 String oldPrefPath = System.getProperty("user.home")            //$NON-NLS-1$
81                     + File.separator + ".ddmsrc";                               //$NON-NLS-1$
82                 File oldPrefFile = new File(oldPrefPath);
83                 if (oldPrefFile.isFile()) {
84                     try {
85                         PreferenceStore oldStore = new PreferenceStore(oldPrefPath);
86                         oldStore.load();
87 
88                         oldStore.save(new FileOutputStream(rcFileName), "");    //$NON-NLS-1$
89                         oldPrefFile.delete();
90 
91                         PreferenceStore newStore = new PreferenceStore(rcFileName);
92                         newStore.load();
93                         sPrefStore = newStore;
94                     } catch (IOException e) {
95                         // create a new empty store.
96                         sPrefStore = new PreferenceStore(rcFileName);
97                     }
98                 } else {
99                     sPrefStore = new PreferenceStore(rcFileName);
100 
101                     try {
102                         sPrefStore.load();
103                     } catch (IOException e) {
104                         System.err.println("Error Loading DDMS Preferences");
105                     }
106                 }
107             }
108 
109             assert sPrefStore != null;
110             return sPrefStore;
111         }
112     }
113 
114     /**
115      * Save the prefs to the config file.
116      */
save()117     public void save() {
118         PreferenceStore prefs = getPreferenceStore();
119         synchronized (DdmsPreferenceStore.class) {
120             try {
121                 prefs.save();
122             }
123             catch (IOException ioe) {
124                 // FIXME com.android.dmmlib.Log.w("ddms", "Failed saving prefs file: " + ioe.getMessage());
125             }
126         }
127     }
128 
129     // ---- Utility methods to access some specific prefs ----
130 
131     /**
132      * Indicates whether the ping ID is set.
133      * This should be true when {@link #isPingOptIn()} is true.
134      *
135      * @return true if a ping ID is set, which means the user gave permission
136      *              to use the ping service.
137      */
hasPingId()138     public boolean hasPingId() {
139         PreferenceStore prefs = getPreferenceStore();
140         synchronized (DdmsPreferenceStore.class) {
141             return prefs != null && prefs.contains(PING_ID);
142         }
143     }
144 
145     /**
146      * Retrieves the current ping ID, if set.
147      * To know if the ping ID is set, use {@link #hasPingId()}.
148      * <p/>
149      * There is no magic value reserved for "missing ping id or invalid store".
150      * The only proper way to know if the ping id is missing is to use {@link #hasPingId()}.
151      */
getPingId()152     public long getPingId() {
153         PreferenceStore prefs = getPreferenceStore();
154         synchronized (DdmsPreferenceStore.class) {
155             // Note: getLong() returns 0L if the ID is missing so we do that too when
156             // there's no store.
157             return prefs == null ? 0L : prefs.getLong(PING_ID);
158         }
159     }
160 
161     /**
162      * Generates a new random ping ID and saves it in the preference store.
163      *
164      * @return The new ping ID.
165      */
generateNewPingId()166     public long generateNewPingId() {
167         PreferenceStore prefs = getPreferenceStore();
168 
169         Random rnd = new Random();
170         long id = rnd.nextLong();
171 
172         synchronized (DdmsPreferenceStore.class) {
173             prefs.setValue(PING_ID, id);
174             try {
175                 prefs.save();
176             } catch (IOException e) {
177                 /* ignore exceptions while saving preferences */
178             }
179         }
180 
181         return id;
182     }
183 
184     /**
185      * Returns the "ping opt in" value from the preference store.
186      * This would be true if there's a valid preference store and
187      * the user opted for sending ping statistics.
188      */
isPingOptIn()189     public boolean isPingOptIn() {
190         PreferenceStore prefs = getPreferenceStore();
191         synchronized (DdmsPreferenceStore.class) {
192             return prefs != null && prefs.contains(PING_OPT_IN);
193         }
194     }
195 
196     /**
197      * Saves the "ping opt in" value in the preference store.
198      *
199      * @param optIn The new user opt-in value.
200      */
setPingOptIn(boolean optIn)201     public void setPingOptIn(boolean optIn) {
202         PreferenceStore prefs = getPreferenceStore();
203 
204         synchronized (DdmsPreferenceStore.class) {
205             prefs.setValue(PING_OPT_IN, optIn);
206             try {
207                 prefs.save();
208             } catch (IOException e) {
209                 /* ignore exceptions while saving preferences */
210             }
211         }
212     }
213 
214     /**
215      * Retrieves the ping time for the given app from the preference store.
216      * Callers should use {@link System#currentTimeMillis()} for time stamps.
217      *
218      * @param app The app name identifier.
219      * @return 0L if we don't have a preference store or there was no time
220      *  recorded in the store for the requested app. Otherwise the time stamp
221      *  from the store.
222      */
getPingTime(String app)223     public long getPingTime(String app) {
224         PreferenceStore prefs = getPreferenceStore();
225         String timePref = PING_TIME + "." + app;  //$NON-NLS-1$
226         synchronized (DdmsPreferenceStore.class) {
227             return prefs == null ? 0 : prefs.getLong(timePref);
228         }
229     }
230 
231     /**
232      * Sets the ping time for the given app from the preference store.
233      * Callers should use {@link System#currentTimeMillis()} for time stamps.
234      *
235      * @param app The app name identifier.
236      * @param timeStamp The time stamp from the store.
237      *                   0L is a special value that should not be used.
238      */
setPingTime(String app, long timeStamp)239     public void setPingTime(String app, long timeStamp) {
240         PreferenceStore prefs = getPreferenceStore();
241         String timePref = PING_TIME + "." + app;  //$NON-NLS-1$
242         synchronized (DdmsPreferenceStore.class) {
243             prefs.setValue(timePref, timeStamp);
244             try {
245                 prefs.save();
246             } catch (IOException ioe) {
247                 /* ignore exceptions while saving preferences */
248             }
249         }
250     }
251 
252     /**
253      * True if this is the first time the users runs ADT, which is detected by
254      * the lack of the setting set using {@link #setAdtUsed(boolean)}
255      * or this value being set to true.
256      *
257      * @return true if ADT has been used  before
258      *
259      * @see #setAdtUsed(boolean)
260      */
isAdtUsed()261     public boolean isAdtUsed() {
262         PreferenceStore prefs = getPreferenceStore();
263         synchronized (DdmsPreferenceStore.class) {
264             if (prefs == null || !prefs.contains(ADT_USED)) {
265                 return false;
266             }
267             return prefs.getBoolean(ADT_USED);
268         }
269     }
270 
271     /**
272      * Sets whether the ADT startup wizard has been shown.
273      * ADT sets first to false once the welcome wizard has been shown once.
274      *
275      * @param used true if ADT has been used
276      */
setAdtUsed(boolean used)277     public void setAdtUsed(boolean used) {
278         PreferenceStore prefs = getPreferenceStore();
279         synchronized (DdmsPreferenceStore.class) {
280             prefs.setValue(ADT_USED, used);
281             try {
282                 prefs.save();
283             } catch (IOException ioe) {
284                 /* ignore exceptions while saving preferences */
285             }
286         }
287     }
288 
289     /**
290      * Retrieves the last SDK OS path.
291      * <p/>
292      * This is just an information value, the path may not exist, may not
293      * even be on an existing file system and/or may not point to an SDK
294      * anymore.
295      *
296      * @return The last SDK OS path from the preference store, or null if
297      *  there is no store or an empty string if it is not defined.
298      */
getLastSdkPath()299     public String getLastSdkPath() {
300         PreferenceStore prefs = getPreferenceStore();
301         synchronized (DdmsPreferenceStore.class) {
302             return prefs == null ? null : prefs.getString(LAST_SDK_PATH);
303         }
304     }
305 
306     /**
307      * Sets the last SDK OS path.
308      *
309      * @param osSdkPath The SDK OS Path. Can be null or empty.
310      */
setLastSdkPath(String osSdkPath)311     public void setLastSdkPath(String osSdkPath) {
312         PreferenceStore prefs = getPreferenceStore();
313         synchronized (DdmsPreferenceStore.class) {
314             prefs.setValue(LAST_SDK_PATH, osSdkPath);
315             try {
316                 prefs.save();
317             } catch (IOException ioe) {
318                 /* ignore exceptions while saving preferences */
319             }
320         }
321     }
322 }
323