1 /*
2  * Copyright (C) 2017 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 package com.android.wallpaper.module;
17 
18 import android.app.backup.BackupManager;
19 import android.content.Context;
20 import android.content.SharedPreferences;
21 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
22 import android.text.TextUtils;
23 import android.util.Log;
24 
25 import androidx.annotation.NonNull;
26 import androidx.annotation.Nullable;
27 
28 import com.android.wallpaper.module.WallpaperPersister.Destination;
29 import com.android.wallpaper.module.WallpaperPreferenceKeys.NoBackupKeys;
30 
31 import org.json.JSONArray;
32 import org.json.JSONException;
33 
34 import java.io.File;
35 import java.text.SimpleDateFormat;
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.Calendar;
39 import java.util.Date;
40 import java.util.List;
41 import java.util.Locale;
42 import java.util.TimeZone;
43 
44 /**
45  * Default implementation that writes to and reads from SharedPreferences.
46  */
47 public class DefaultWallpaperPreferences implements WallpaperPreferences {
48     public static final String PREFS_NAME = "wallpaper";
49     public static final String NO_BACKUP_PREFS_NAME = "wallpaper-nobackup";
50 
51     private static final String TAG = "DefaultWPPreferences";
52 
53     protected SharedPreferences mSharedPrefs;
54     protected SharedPreferences mNoBackupPrefs;
55     protected Context mContext;
56 
57     // Keep a strong reference to this OnSharedPreferenceChangeListener to prevent the listener from
58     // being garbage collected because SharedPreferences only holds a weak reference.
59     private OnSharedPreferenceChangeListener mSharedPrefsChangedListener;
60 
DefaultWallpaperPreferences(Context context)61     public DefaultWallpaperPreferences(Context context) {
62         mSharedPrefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
63         mNoBackupPrefs = context.getSharedPreferences(NO_BACKUP_PREFS_NAME, Context.MODE_PRIVATE);
64         if (mNoBackupPrefs.getAll().isEmpty() && !mSharedPrefs.getAll().isEmpty()) {
65             upgradePrefs();
66         }
67         mContext = context.getApplicationContext();
68 
69         // Register a prefs changed listener so that all prefs changes trigger a backup event.
70         final BackupManager backupManager = new BackupManager(context);
71         mSharedPrefsChangedListener = (sharedPreferences, key) -> backupManager.dataChanged();
72         mSharedPrefs.registerOnSharedPreferenceChangeListener(mSharedPrefsChangedListener);
73     }
74 
75     /**
76      * Move {@link NoBackupKeys} preferences that might have been in mSharedPrefs from previous
77      * versions of the app into mNoBackupPrefs.
78      */
upgradePrefs()79     private void upgradePrefs() {
80         SharedPreferences.Editor editor = mNoBackupPrefs.edit();
81         if (mSharedPrefs.contains(
82                 NoBackupKeys.KEY_HOME_WALLPAPER_BASE_IMAGE_URL)) {
83             editor.putString(NoBackupKeys.KEY_HOME_WALLPAPER_BASE_IMAGE_URL,
84                     mSharedPrefs.getString(NoBackupKeys.KEY_HOME_WALLPAPER_BASE_IMAGE_URL, null));
85         }
86         if (mSharedPrefs.contains(NoBackupKeys.KEY_HOME_WALLPAPER_MANAGER_ID)) {
87             editor.putInt(NoBackupKeys.KEY_HOME_WALLPAPER_MANAGER_ID,
88                     mSharedPrefs.getInt(NoBackupKeys.KEY_HOME_WALLPAPER_MANAGER_ID, 0));
89         }
90         if (mSharedPrefs.contains(NoBackupKeys.KEY_HOME_WALLPAPER_REMOTE_ID)) {
91             editor.putString(NoBackupKeys.KEY_HOME_WALLPAPER_REMOTE_ID,
92                     mSharedPrefs.getString(NoBackupKeys.KEY_HOME_WALLPAPER_REMOTE_ID, null));
93         }
94         if (mSharedPrefs.contains(
95                 NoBackupKeys.KEY_HOME_WALLPAPER_BACKING_FILE)) {
96             editor.putString(NoBackupKeys.KEY_HOME_WALLPAPER_BACKING_FILE,
97                     mSharedPrefs.getString(NoBackupKeys.KEY_HOME_WALLPAPER_BACKING_FILE, null));
98         }
99         if (mSharedPrefs.contains(NoBackupKeys.KEY_LOCK_WALLPAPER_MANAGER_ID)) {
100             editor.putInt(NoBackupKeys.KEY_LOCK_WALLPAPER_MANAGER_ID,
101                     mSharedPrefs.getInt(NoBackupKeys.KEY_LOCK_WALLPAPER_MANAGER_ID, 0));
102         }
103         if (mSharedPrefs.contains(
104                 NoBackupKeys.KEY_LOCK_WALLPAPER_BACKING_FILE)) {
105             editor.putString(NoBackupKeys.KEY_LOCK_WALLPAPER_BACKING_FILE,
106                     mSharedPrefs.getString(NoBackupKeys.KEY_LOCK_WALLPAPER_BACKING_FILE, null));
107         }
108         if (mSharedPrefs.contains(NoBackupKeys.KEY_DAILY_ROTATION_TIMESTAMPS)) {
109             editor.putString(NoBackupKeys.KEY_DAILY_ROTATION_TIMESTAMPS,
110                     mSharedPrefs.getString(NoBackupKeys.KEY_DAILY_ROTATION_TIMESTAMPS, null));
111         }
112         if (mSharedPrefs.contains(
113                 NoBackupKeys.KEY_DAILY_WALLPAPER_ENABLED_TIMESTAMP)) {
114             editor.putLong(NoBackupKeys.KEY_DAILY_WALLPAPER_ENABLED_TIMESTAMP,
115                     mSharedPrefs.getLong(NoBackupKeys.KEY_DAILY_WALLPAPER_ENABLED_TIMESTAMP, -1));
116         }
117         if (mSharedPrefs.contains(NoBackupKeys.KEY_LAST_DAILY_LOG_TIMESTAMP)) {
118             editor.putLong(NoBackupKeys.KEY_LAST_DAILY_LOG_TIMESTAMP,
119                     mSharedPrefs.getLong(NoBackupKeys.KEY_LAST_DAILY_LOG_TIMESTAMP, 0));
120         }
121         if (mSharedPrefs.contains(NoBackupKeys.KEY_LAST_APP_ACTIVE_TIMESTAMP)) {
122             editor.putLong(NoBackupKeys.KEY_LAST_APP_ACTIVE_TIMESTAMP,
123                     mSharedPrefs.getLong(NoBackupKeys.KEY_LAST_APP_ACTIVE_TIMESTAMP, 0));
124         }
125         if (mSharedPrefs.contains(NoBackupKeys.KEY_LAST_ROTATION_STATUS)) {
126             editor.putInt(NoBackupKeys.KEY_LAST_ROTATION_STATUS,
127                     mSharedPrefs.getInt(NoBackupKeys.KEY_LAST_ROTATION_STATUS, -1));
128         }
129         if (mSharedPrefs.contains(NoBackupKeys.KEY_LAST_ROTATION_STATUS_TIMESTAMP)) {
130             editor.putLong(NoBackupKeys.KEY_LAST_ROTATION_STATUS_TIMESTAMP,
131                     mSharedPrefs.getLong(NoBackupKeys.KEY_LAST_ROTATION_STATUS_TIMESTAMP, 0));
132         }
133         if (mSharedPrefs.contains(NoBackupKeys.KEY_LAST_SYNC_TIMESTAMP)) {
134             editor.putLong(NoBackupKeys.KEY_LAST_SYNC_TIMESTAMP,
135                     mSharedPrefs.getLong(NoBackupKeys.KEY_LAST_SYNC_TIMESTAMP, 0));
136         }
137         if (mSharedPrefs.contains(NoBackupKeys.KEY_PENDING_WALLPAPER_SET_STATUS)) {
138             editor.putInt(NoBackupKeys.KEY_PENDING_WALLPAPER_SET_STATUS,
139                     mSharedPrefs.getInt(NoBackupKeys.KEY_PENDING_WALLPAPER_SET_STATUS,
140                             WALLPAPER_SET_NOT_PENDING));
141         }
142         if (mSharedPrefs.contains(NoBackupKeys.KEY_PENDING_DAILY_WALLPAPER_UPDATE_STATUS)) {
143             editor.putInt(NoBackupKeys.KEY_PENDING_DAILY_WALLPAPER_UPDATE_STATUS,
144                     mSharedPrefs.getInt(NoBackupKeys.KEY_PENDING_DAILY_WALLPAPER_UPDATE_STATUS,
145                             DAILY_WALLPAPER_UPDATE_NOT_PENDING));
146         }
147         if (mSharedPrefs.contains(NoBackupKeys.KEY_NUM_DAYS_DAILY_ROTATION_FAILED)) {
148             editor.putInt(NoBackupKeys.KEY_NUM_DAYS_DAILY_ROTATION_FAILED,
149                     mSharedPrefs.getInt(NoBackupKeys.KEY_NUM_DAYS_DAILY_ROTATION_FAILED, 0));
150         }
151         if (mSharedPrefs.contains(NoBackupKeys.KEY_NUM_DAYS_DAILY_ROTATION_NOT_ATTEMPTED)) {
152             editor.putInt(NoBackupKeys.KEY_NUM_DAYS_DAILY_ROTATION_NOT_ATTEMPTED,
153                     mSharedPrefs.getInt(NoBackupKeys.KEY_NUM_DAYS_DAILY_ROTATION_NOT_ATTEMPTED, 0));
154         }
155         if (mSharedPrefs.contains(NoBackupKeys.KEY_HOME_WALLPAPER_PACKAGE_NAME)) {
156             editor.putString(NoBackupKeys.KEY_HOME_WALLPAPER_PACKAGE_NAME,
157                     mSharedPrefs.getString(NoBackupKeys.KEY_HOME_WALLPAPER_PACKAGE_NAME, null));
158         }
159         if (mSharedPrefs.contains(NoBackupKeys.KEY_HOME_WALLPAPER_SERVICE_NAME)) {
160             editor.putString(NoBackupKeys.KEY_HOME_WALLPAPER_SERVICE_NAME,
161                     mSharedPrefs.getString(NoBackupKeys.KEY_HOME_WALLPAPER_SERVICE_NAME, null));
162         }
163 
164         editor.apply();
165     }
166 
getResIdPersistedByName(String key, String type)167     private int getResIdPersistedByName(String key, String type) {
168         String resName = mSharedPrefs.getString(key, null);
169         if (resName == null) {
170             return 0;
171         }
172         return mContext.getResources().getIdentifier(resName, type,
173                 mContext.getPackageName());
174     }
175 
persistResIdByName(String key, int resId)176     private void persistResIdByName(String key, int resId) {
177         String resName = mContext.getResources().getResourceName(resId);
178         mSharedPrefs.edit().putString(key, resName).apply();
179     }
180 
181     @Override
getWallpaperPresentationMode()182     public int getWallpaperPresentationMode() {
183         @PresentationMode
184         int homeWallpaperPresentationMode = mSharedPrefs.getInt(
185                 WallpaperPreferenceKeys.KEY_WALLPAPER_PRESENTATION_MODE,
186                 WallpaperPreferences.PRESENTATION_MODE_STATIC);
187         return homeWallpaperPresentationMode;
188     }
189 
190     @Override
setWallpaperPresentationMode(@resentationMode int presentationMode)191     public void setWallpaperPresentationMode(@PresentationMode int presentationMode) {
192         mSharedPrefs.edit().putInt(
193                 WallpaperPreferenceKeys.KEY_WALLPAPER_PRESENTATION_MODE, presentationMode).apply();
194     }
195 
196     @Override
getHomeWallpaperAttributions()197     public List<String> getHomeWallpaperAttributions() {
198         return Arrays.asList(
199                 mSharedPrefs.getString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_1, null),
200                 mSharedPrefs.getString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_2, null),
201                 mSharedPrefs.getString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_3, null));
202 
203     }
204 
205     @Override
setHomeWallpaperAttributions(List<String> attributions)206     public void setHomeWallpaperAttributions(List<String> attributions) {
207         SharedPreferences.Editor editor = mSharedPrefs.edit();
208         if (attributions.size() > 0) {
209             editor.putString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_1,
210                     attributions.get(0));
211         }
212         if (attributions.size() > 1) {
213             editor.putString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_2,
214                     attributions.get(1));
215         }
216         if (attributions.size() > 2) {
217             editor.putString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_3,
218                     attributions.get(2));
219         }
220         editor.apply();
221     }
222 
223     @Override
224     @Nullable
getHomeWallpaperActionUrl()225     public String getHomeWallpaperActionUrl() {
226         return mSharedPrefs.getString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ACTION_URL, null);
227     }
228 
229     @Override
setHomeWallpaperActionUrl(String actionUrl)230     public void setHomeWallpaperActionUrl(String actionUrl) {
231         mSharedPrefs.edit().putString(
232                 WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ACTION_URL, actionUrl).apply();
233     }
234 
235     @Override
getHomeWallpaperActionLabelRes()236     public int getHomeWallpaperActionLabelRes() {
237         // We need to store and read the resource names as their ids could change from build to
238         // build and we might end up reading the wrong id
239         return getResIdPersistedByName(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ACTION_LABEL_RES,
240                 "string");
241     }
242 
243     @Override
setHomeWallpaperActionLabelRes(int resId)244     public void setHomeWallpaperActionLabelRes(int resId) {
245         persistResIdByName(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ACTION_LABEL_RES, resId);
246     }
247 
248     @Override
getHomeWallpaperActionIconRes()249     public int getHomeWallpaperActionIconRes() {
250         return getResIdPersistedByName(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ACTION_ICON_RES,
251                 "drawable");
252     }
253 
254     @Override
setHomeWallpaperActionIconRes(int resId)255     public void setHomeWallpaperActionIconRes(int resId) {
256         persistResIdByName(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ACTION_ICON_RES, resId);
257     }
258 
259     @Override
getHomeWallpaperBaseImageUrl()260     public String getHomeWallpaperBaseImageUrl() {
261         return mNoBackupPrefs.getString(
262                 NoBackupKeys.KEY_HOME_WALLPAPER_BASE_IMAGE_URL, null);
263     }
264 
265     @Override
setHomeWallpaperBaseImageUrl(String baseImageUrl)266     public void setHomeWallpaperBaseImageUrl(String baseImageUrl) {
267         mNoBackupPrefs.edit().putString(
268                 NoBackupKeys.KEY_HOME_WALLPAPER_BASE_IMAGE_URL, baseImageUrl)
269                 .apply();
270     }
271 
272     @Override
273     @Nullable
getHomeWallpaperCollectionId()274     public String getHomeWallpaperCollectionId() {
275         return mSharedPrefs.getString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_COLLECTION_ID,
276                 null);
277     }
278 
279     @Override
setHomeWallpaperCollectionId(String collectionId)280     public void setHomeWallpaperCollectionId(String collectionId) {
281         mSharedPrefs.edit().putString(
282                 WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_COLLECTION_ID, collectionId).apply();
283     }
284 
285     @Override
286     @Nullable
getHomeWallpaperBackingFileName()287     public String getHomeWallpaperBackingFileName() {
288         return mNoBackupPrefs.getString(
289                 NoBackupKeys.KEY_HOME_WALLPAPER_BACKING_FILE, null);
290     }
291 
292     @Override
setHomeWallpaperBackingFileName(String fileName)293     public void setHomeWallpaperBackingFileName(String fileName) {
294         mNoBackupPrefs.edit().putString(
295                 NoBackupKeys.KEY_HOME_WALLPAPER_BACKING_FILE, fileName).apply();
296     }
297 
298     @Override
getHomeWallpaperHashCode()299     public long getHomeWallpaperHashCode() {
300         return mSharedPrefs.getLong(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_HASH_CODE, 0);
301     }
302 
303     @Override
setHomeWallpaperHashCode(long hashCode)304     public void setHomeWallpaperHashCode(long hashCode) {
305         mSharedPrefs.edit().putLong(
306                 WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_HASH_CODE, hashCode).apply();
307     }
308 
309     @Override
clearHomeWallpaperMetadata()310     public void clearHomeWallpaperMetadata() {
311         String homeWallpaperBackingFileName = getHomeWallpaperBackingFileName();
312         if (!TextUtils.isEmpty(homeWallpaperBackingFileName)) {
313             new File(homeWallpaperBackingFileName).delete();
314         }
315         mSharedPrefs.edit()
316                 .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_1)
317                 .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_2)
318                 .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_3)
319                 .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ACTION_URL)
320                 .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ACTION_LABEL_RES)
321                 .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ACTION_ICON_RES)
322                 .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_HASH_CODE)
323                 .apply();
324 
325         mNoBackupPrefs.edit()
326                 .remove(NoBackupKeys.KEY_HOME_WALLPAPER_PACKAGE_NAME)
327                 .remove(NoBackupKeys.KEY_HOME_WALLPAPER_MANAGER_ID)
328                 .remove(NoBackupKeys.KEY_HOME_WALLPAPER_REMOTE_ID)
329                 .remove(NoBackupKeys.KEY_HOME_WALLPAPER_SERVICE_NAME)
330                 .remove(NoBackupKeys.KEY_HOME_WALLPAPER_BASE_IMAGE_URL)
331                 .remove(NoBackupKeys.KEY_HOME_WALLPAPER_BACKING_FILE)
332                 .apply();
333     }
334 
335     @Override
getHomeWallpaperPackageName()336     public String getHomeWallpaperPackageName() {
337         return mNoBackupPrefs.getString(
338                 NoBackupKeys.KEY_HOME_WALLPAPER_PACKAGE_NAME, null);
339     }
340 
341     @Override
setHomeWallpaperPackageName(String packageName)342     public void setHomeWallpaperPackageName(String packageName) {
343         mNoBackupPrefs.edit().putString(
344                 NoBackupKeys.KEY_HOME_WALLPAPER_PACKAGE_NAME, packageName)
345                 .apply();
346     }
347 
348     @Override
getHomeWallpaperServiceName()349     public String getHomeWallpaperServiceName() {
350         return mNoBackupPrefs.getString(
351                 NoBackupKeys.KEY_HOME_WALLPAPER_SERVICE_NAME, null);
352     }
353 
354     @Override
setHomeWallpaperServiceName(@onNull String serviceName)355     public void setHomeWallpaperServiceName(@NonNull String serviceName) {
356         mNoBackupPrefs.edit().putString(
357                 NoBackupKeys.KEY_HOME_WALLPAPER_SERVICE_NAME, serviceName)
358                 .apply();
359         setFirstWallpaperApplyDateIfNeeded();
360     }
361 
362     @Override
getHomeWallpaperManagerId()363     public int getHomeWallpaperManagerId() {
364         return mNoBackupPrefs.getInt(
365                 NoBackupKeys.KEY_HOME_WALLPAPER_MANAGER_ID, 0);
366     }
367 
368     @Override
setHomeWallpaperManagerId(int homeWallpaperId)369     public void setHomeWallpaperManagerId(int homeWallpaperId) {
370         mNoBackupPrefs.edit().putInt(
371                 NoBackupKeys.KEY_HOME_WALLPAPER_MANAGER_ID, homeWallpaperId)
372                 .apply();
373     }
374 
375     @Nullable
376     @Override
getHomeWallpaperRemoteId()377     public String getHomeWallpaperRemoteId() {
378         return mNoBackupPrefs.getString(
379                 NoBackupKeys.KEY_HOME_WALLPAPER_REMOTE_ID, null);
380     }
381 
382     @Override
setHomeWallpaperRemoteId(@ullable String wallpaperRemoteId)383     public void setHomeWallpaperRemoteId(@Nullable String wallpaperRemoteId) {
384         mNoBackupPrefs.edit().putString(
385                 NoBackupKeys.KEY_HOME_WALLPAPER_REMOTE_ID, wallpaperRemoteId)
386                 .apply();
387         setFirstWallpaperApplyDateIfNeeded();
388     }
389 
390     @Override
getLockWallpaperAttributions()391     public List<String> getLockWallpaperAttributions() {
392         return Arrays.asList(
393                 mSharedPrefs.getString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_1, null),
394                 mSharedPrefs.getString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_2, null),
395                 mSharedPrefs.getString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_3, null));
396 
397     }
398 
399     @Override
setLockWallpaperAttributions(List<String> attributions)400     public void setLockWallpaperAttributions(List<String> attributions) {
401         SharedPreferences.Editor editor = mSharedPrefs.edit();
402         if (attributions.size() > 0) {
403             editor.putString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_1,
404                     attributions.get(0));
405         }
406         if (attributions.size() > 1) {
407             editor.putString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_2,
408                     attributions.get(1));
409         }
410         if (attributions.size() > 2) {
411             editor.putString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_3,
412                     attributions.get(2));
413         }
414         editor.apply();
415     }
416 
417     @Override
418     @Nullable
getLockWallpaperActionUrl()419     public String getLockWallpaperActionUrl() {
420         return mSharedPrefs.getString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ACTION_URL, null);
421     }
422 
423     @Override
setLockWallpaperActionUrl(String actionUrl)424     public void setLockWallpaperActionUrl(String actionUrl) {
425         mSharedPrefs.edit().putString(
426                 WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ACTION_URL, actionUrl).apply();
427     }
428 
429     @Override
getLockWallpaperActionLabelRes()430     public int getLockWallpaperActionLabelRes() {
431         // We need to store and read the resource names as their ids could change from build to
432         // build and we might end up reading the wrong id
433         return getResIdPersistedByName(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ACTION_LABEL_RES,
434                 "string");
435     }
436 
437     @Override
setLockWallpaperActionLabelRes(int resId)438     public void setLockWallpaperActionLabelRes(int resId) {
439         persistResIdByName(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ACTION_LABEL_RES, resId);
440     }
441 
442     @Override
getLockWallpaperActionIconRes()443     public int getLockWallpaperActionIconRes() {
444         return getResIdPersistedByName(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ACTION_ICON_RES,
445                 "drawable");
446     }
447 
448     @Override
setLockWallpaperActionIconRes(int resId)449     public void setLockWallpaperActionIconRes(int resId) {
450         persistResIdByName(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ACTION_ICON_RES, resId);
451     }
452 
453     @Override
454     @Nullable
getLockWallpaperCollectionId()455     public String getLockWallpaperCollectionId() {
456         return mSharedPrefs.getString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_COLLECTION_ID,
457                 null);
458     }
459 
460     @Override
setLockWallpaperCollectionId(String collectionId)461     public void setLockWallpaperCollectionId(String collectionId) {
462         mSharedPrefs.edit().putString(
463                 WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_COLLECTION_ID, collectionId).apply();
464     }
465 
466     @Override
467     @Nullable
getLockWallpaperBackingFileName()468     public String getLockWallpaperBackingFileName() {
469         return mNoBackupPrefs.getString(
470                 NoBackupKeys.KEY_LOCK_WALLPAPER_BACKING_FILE, null);
471     }
472 
473     @Override
setLockWallpaperBackingFileName(String fileName)474     public void setLockWallpaperBackingFileName(String fileName) {
475         mNoBackupPrefs.edit().putString(
476                 NoBackupKeys.KEY_LOCK_WALLPAPER_BACKING_FILE, fileName).apply();
477     }
478 
479     @Override
getLockWallpaperId()480     public int getLockWallpaperId() {
481         return mNoBackupPrefs.getInt(
482                 NoBackupKeys.KEY_LOCK_WALLPAPER_MANAGER_ID, 0);
483     }
484 
485     @Override
setLockWallpaperId(int lockWallpaperId)486     public void setLockWallpaperId(int lockWallpaperId) {
487         mNoBackupPrefs.edit().putInt(
488                 NoBackupKeys.KEY_LOCK_WALLPAPER_MANAGER_ID, lockWallpaperId)
489                 .apply();
490     }
491 
492     @Override
getLockWallpaperRemoteId()493     public String getLockWallpaperRemoteId() {
494         return mNoBackupPrefs.getString(
495                 NoBackupKeys.KEY_LOCK_WALLPAPER_REMOTE_ID, null);
496     }
497 
498     @Override
setLockWallpaperRemoteId(String wallpaperRemoteId)499     public void setLockWallpaperRemoteId(String wallpaperRemoteId) {
500         mNoBackupPrefs.edit().putString(
501                 NoBackupKeys.KEY_LOCK_WALLPAPER_REMOTE_ID, wallpaperRemoteId)
502                 .apply();
503         setFirstWallpaperApplyDateIfNeeded();
504     }
505 
506     @Override
getLockWallpaperHashCode()507     public long getLockWallpaperHashCode() {
508         return mSharedPrefs.getLong(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_HASH_CODE, 0);
509     }
510 
511     @Override
setLockWallpaperHashCode(long hashCode)512     public void setLockWallpaperHashCode(long hashCode) {
513         mSharedPrefs.edit()
514                 .putLong(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_HASH_CODE, hashCode)
515                 .apply();
516     }
517 
518     @Override
clearLockWallpaperMetadata()519     public void clearLockWallpaperMetadata() {
520         String lockWallpaperBackingFileName = getLockWallpaperBackingFileName();
521         if (!TextUtils.isEmpty(lockWallpaperBackingFileName)) {
522             new File(lockWallpaperBackingFileName).delete();
523         }
524         mSharedPrefs.edit()
525                 .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_1)
526                 .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_2)
527                 .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_3)
528                 .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ACTION_URL)
529                 .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ACTION_LABEL_RES)
530                 .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ACTION_ICON_RES)
531                 .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_COLLECTION_ID)
532                 .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_HASH_CODE)
533                 .apply();
534 
535         mNoBackupPrefs.edit()
536                 .remove(NoBackupKeys.KEY_LOCK_WALLPAPER_MANAGER_ID)
537                 .remove(NoBackupKeys.KEY_LOCK_WALLPAPER_BACKING_FILE)
538                 .remove(NoBackupKeys.KEY_LOCK_WALLPAPER_REMOTE_ID)
539                 .apply();
540     }
541 
542     @Override
addDailyRotation(long timestamp)543     public void addDailyRotation(long timestamp) {
544         String jsonString = mNoBackupPrefs.getString(
545                 NoBackupKeys.KEY_DAILY_ROTATION_TIMESTAMPS, "[]");
546         try {
547             JSONArray jsonArray = new JSONArray(jsonString);
548             jsonArray.put(timestamp);
549 
550             mNoBackupPrefs.edit()
551                     .putString(NoBackupKeys.KEY_DAILY_ROTATION_TIMESTAMPS,
552                             jsonArray.toString())
553                     .apply();
554         } catch (JSONException e) {
555             Log.e(TAG, "Failed to add a daily rotation timestamp due to a JSON parse exception");
556         }
557     }
558 
559     @Override
getLastDailyRotationTimestamp()560     public long getLastDailyRotationTimestamp() {
561         String jsonString = mNoBackupPrefs.getString(
562                 NoBackupKeys.KEY_DAILY_ROTATION_TIMESTAMPS, "[]");
563 
564         try {
565             JSONArray jsonArray = new JSONArray(jsonString);
566 
567             if (jsonArray.length() == 0) {
568                 return -1;
569             }
570 
571             return jsonArray.getLong(jsonArray.length() - 1);
572         } catch (JSONException e) {
573             Log.e(TAG, "Failed to find a daily rotation timestamp due to a JSON parse exception");
574             return -1;
575         }
576     }
577 
578     @Override
579     @Nullable
getDailyRotationsInLastWeek()580     public List<Long> getDailyRotationsInLastWeek() {
581         long enabledTimestamp = getDailyWallpaperEnabledTimestamp();
582 
583         Calendar oneWeekAgo = Calendar.getInstance();
584         oneWeekAgo.setTime(new Date());
585         oneWeekAgo.add(Calendar.WEEK_OF_YEAR, -1);
586         long oneWeekAgoTimestamp = oneWeekAgo.getTimeInMillis();
587 
588         // Return null if daily rotation wasn't enabled (timestamp value of -1) or was enabled
589         // less than one week ago.
590         if (enabledTimestamp == -1 || enabledTimestamp > oneWeekAgoTimestamp) {
591             return null;
592         }
593 
594         List<Long> timestamps = new ArrayList<>();
595         String jsonString = mNoBackupPrefs.getString(
596                 NoBackupKeys.KEY_DAILY_ROTATION_TIMESTAMPS, "[]");
597 
598         try {
599             JSONArray jsonArray = new JSONArray(jsonString);
600 
601             // Before recording the new daily rotation timestamp, filter out any that are older than
602             // 1 week old.
603             for (int i = 0; i < jsonArray.length(); i++) {
604                 long existingTimestamp = jsonArray.getLong(i);
605                 if (existingTimestamp >= oneWeekAgoTimestamp) {
606                     timestamps.add(existingTimestamp);
607                 }
608             }
609 
610             jsonArray = new JSONArray(timestamps);
611             mNoBackupPrefs.edit()
612                     .putString(NoBackupKeys.KEY_DAILY_ROTATION_TIMESTAMPS,
613                             jsonArray.toString())
614                     .apply();
615         } catch (JSONException e) {
616             Log.e(TAG, "Failed to get daily rotation timestamps due to a JSON parse exception");
617         }
618 
619         return timestamps;
620     }
621 
622     @Nullable
623     @Override
getDailyRotationsPreviousDay()624     public List<Long> getDailyRotationsPreviousDay() {
625         long enabledTimestamp = getDailyWallpaperEnabledTimestamp();
626 
627         Calendar midnightYesterday = Calendar.getInstance();
628         midnightYesterday.set(Calendar.AM_PM, Calendar.AM);
629         midnightYesterday.set(Calendar.HOUR, 0);
630         midnightYesterday.set(Calendar.MINUTE, 0);
631         midnightYesterday.add(Calendar.DATE, -1);
632         long midnightYesterdayTimestamp = midnightYesterday.getTimeInMillis();
633 
634         Calendar midnightToday = Calendar.getInstance();
635         midnightToday.set(Calendar.AM_PM, Calendar.AM);
636         midnightToday.set(Calendar.HOUR, 0);
637         midnightToday.set(Calendar.MINUTE, 0);
638         long midnightTodayTimestamp = midnightToday.getTimeInMillis();
639 
640         // Return null if daily rotation wasn't enabled (timestamp value of -1) or was enabled
641         // less than midnight yesterday.
642         if (enabledTimestamp == -1 || enabledTimestamp > midnightYesterdayTimestamp) {
643             return null;
644         }
645 
646         List<Long> timestamps = new ArrayList<>();
647         String jsonString = mNoBackupPrefs.getString(
648                 NoBackupKeys.KEY_DAILY_ROTATION_TIMESTAMPS, "[]");
649 
650         try {
651             JSONArray jsonArray = new JSONArray(jsonString);
652 
653             // Filter the timestamps (which cover up to one week of data) to only include those
654             // between midnight yesterday and midnight today.
655             for (int i = 0; i < jsonArray.length(); i++) {
656                 long timestamp = jsonArray.getLong(i);
657                 if (timestamp >= midnightYesterdayTimestamp && timestamp < midnightTodayTimestamp) {
658                     timestamps.add(timestamp);
659                 }
660             }
661 
662         } catch (JSONException e) {
663             Log.e(TAG, "Failed to get daily rotation timestamps due to a JSON parse exception");
664         }
665 
666         return timestamps;
667     }
668 
669     @Override
getDailyWallpaperEnabledTimestamp()670     public long getDailyWallpaperEnabledTimestamp() {
671         return mNoBackupPrefs.getLong(
672                 NoBackupKeys.KEY_DAILY_WALLPAPER_ENABLED_TIMESTAMP, -1);
673     }
674 
675     @Override
setDailyWallpaperEnabledTimestamp(long timestamp)676     public void setDailyWallpaperEnabledTimestamp(long timestamp) {
677         mNoBackupPrefs.edit()
678                 .putLong(NoBackupKeys.KEY_DAILY_WALLPAPER_ENABLED_TIMESTAMP,
679                         timestamp)
680                 .apply();
681     }
682 
683     @Override
clearDailyRotations()684     public void clearDailyRotations() {
685         mNoBackupPrefs.edit()
686                 .remove(NoBackupKeys.KEY_DAILY_ROTATION_TIMESTAMPS)
687                 .remove(NoBackupKeys.KEY_DAILY_WALLPAPER_ENABLED_TIMESTAMP)
688                 .apply();
689     }
690 
691     @Override
getLastDailyLogTimestamp()692     public long getLastDailyLogTimestamp() {
693         return mNoBackupPrefs.getLong(
694                 NoBackupKeys.KEY_LAST_DAILY_LOG_TIMESTAMP, 0);
695     }
696 
697     @Override
setLastDailyLogTimestamp(long timestamp)698     public void setLastDailyLogTimestamp(long timestamp) {
699         mNoBackupPrefs.edit()
700                 .putLong(NoBackupKeys.KEY_LAST_DAILY_LOG_TIMESTAMP, timestamp)
701                 .apply();
702     }
703 
704     @Override
getLastAppActiveTimestamp()705     public long getLastAppActiveTimestamp() {
706         return mNoBackupPrefs.getLong(
707                 NoBackupKeys.KEY_LAST_APP_ACTIVE_TIMESTAMP, 0);
708     }
709 
710     @Override
setLastAppActiveTimestamp(long timestamp)711     public void setLastAppActiveTimestamp(long timestamp) {
712         mNoBackupPrefs.edit()
713                 .putLong(NoBackupKeys.KEY_LAST_APP_ACTIVE_TIMESTAMP, timestamp)
714                 .apply();
715     }
716 
717     @Override
setDailyWallpaperRotationStatus(int status, long timestamp)718     public void setDailyWallpaperRotationStatus(int status, long timestamp) {
719         mNoBackupPrefs.edit()
720                 .putInt(NoBackupKeys.KEY_LAST_ROTATION_STATUS, status)
721                 .putLong(NoBackupKeys.KEY_LAST_ROTATION_STATUS_TIMESTAMP,
722                         timestamp)
723                 .apply();
724     }
725 
726     @Override
getDailyWallpaperLastRotationStatus()727     public int getDailyWallpaperLastRotationStatus() {
728         return mNoBackupPrefs.getInt(NoBackupKeys.KEY_LAST_ROTATION_STATUS, -1);
729     }
730 
731     @Override
getDailyWallpaperLastRotationStatusTimestamp()732     public long getDailyWallpaperLastRotationStatusTimestamp() {
733         return mNoBackupPrefs.getLong(
734                 NoBackupKeys.KEY_LAST_ROTATION_STATUS_TIMESTAMP, 0);
735     }
736 
737     @Override
getLastSyncTimestamp()738     public long getLastSyncTimestamp() {
739         return mNoBackupPrefs.getLong(NoBackupKeys.KEY_LAST_SYNC_TIMESTAMP, 0);
740     }
741 
742     @Override
setLastSyncTimestamp(long timestamp)743     public void setLastSyncTimestamp(long timestamp) {
744         // Write synchronously via commit() to ensure this timetsamp gets written to disk
745         // immediately.
746         mNoBackupPrefs.edit()
747                 .putLong(NoBackupKeys.KEY_LAST_SYNC_TIMESTAMP, timestamp)
748                 .commit();
749     }
750 
751     @Override
setPendingWallpaperSetStatusSync(@endingWallpaperSetStatus int setStatus)752     public void setPendingWallpaperSetStatusSync(@PendingWallpaperSetStatus int setStatus) {
753         mNoBackupPrefs.edit()
754                 .putInt(NoBackupKeys.KEY_PENDING_WALLPAPER_SET_STATUS,
755                         setStatus)
756                 .commit();
757     }
758 
759     @Override
getPendingWallpaperSetStatus()760     public int getPendingWallpaperSetStatus() {
761         //noinspection ResourceType
762         return mNoBackupPrefs.getInt(
763                 NoBackupKeys.KEY_PENDING_WALLPAPER_SET_STATUS,
764                 WALLPAPER_SET_NOT_PENDING);
765     }
766 
767     @Override
setPendingWallpaperSetStatus(@endingWallpaperSetStatus int setStatus)768     public void setPendingWallpaperSetStatus(@PendingWallpaperSetStatus int setStatus) {
769         mNoBackupPrefs.edit()
770                 .putInt(NoBackupKeys.KEY_PENDING_WALLPAPER_SET_STATUS,
771                         setStatus)
772                 .apply();
773     }
774 
775     @Override
setPendingDailyWallpaperUpdateStatusSync( @endingDailyWallpaperUpdateStatus int updateStatus)776     public void setPendingDailyWallpaperUpdateStatusSync(
777             @PendingDailyWallpaperUpdateStatus int updateStatus) {
778         mNoBackupPrefs.edit()
779                 .putInt(NoBackupKeys.KEY_PENDING_DAILY_WALLPAPER_UPDATE_STATUS,
780                         updateStatus)
781                 .commit();
782     }
783 
784     @Override
getPendingDailyWallpaperUpdateStatus()785     public int getPendingDailyWallpaperUpdateStatus() {
786         //noinspection ResourceType
787         return mNoBackupPrefs.getInt(
788                 NoBackupKeys.KEY_PENDING_DAILY_WALLPAPER_UPDATE_STATUS,
789                 DAILY_WALLPAPER_UPDATE_NOT_PENDING);
790     }
791 
792     @Override
setPendingDailyWallpaperUpdateStatus( @endingDailyWallpaperUpdateStatus int updateStatus)793     public void setPendingDailyWallpaperUpdateStatus(
794             @PendingDailyWallpaperUpdateStatus int updateStatus) {
795         mNoBackupPrefs.edit()
796                 .putInt(NoBackupKeys.KEY_PENDING_DAILY_WALLPAPER_UPDATE_STATUS,
797                         updateStatus)
798                 .apply();
799     }
800 
801     @Override
incrementNumDaysDailyRotationFailed()802     public void incrementNumDaysDailyRotationFailed() {
803         mNoBackupPrefs.edit()
804                 .putInt(NoBackupKeys.KEY_NUM_DAYS_DAILY_ROTATION_FAILED,
805                         getNumDaysDailyRotationFailed() + 1)
806                 .apply();
807     }
808 
809     @Override
getNumDaysDailyRotationFailed()810     public int getNumDaysDailyRotationFailed() {
811         return mNoBackupPrefs.getInt(
812                 NoBackupKeys.KEY_NUM_DAYS_DAILY_ROTATION_FAILED, 0);
813     }
814 
815     @Override
resetNumDaysDailyRotationFailed()816     public void resetNumDaysDailyRotationFailed() {
817         mNoBackupPrefs.edit()
818                 .putInt(NoBackupKeys.KEY_NUM_DAYS_DAILY_ROTATION_FAILED, 0)
819                 .apply();
820     }
821 
822     @Override
incrementNumDaysDailyRotationNotAttempted()823     public void incrementNumDaysDailyRotationNotAttempted() {
824         mNoBackupPrefs.edit()
825                 .putInt(NoBackupKeys.KEY_NUM_DAYS_DAILY_ROTATION_NOT_ATTEMPTED,
826                         getNumDaysDailyRotationNotAttempted() + 1)
827                 .apply();
828     }
829 
830     @Override
getNumDaysDailyRotationNotAttempted()831     public int getNumDaysDailyRotationNotAttempted() {
832         return mNoBackupPrefs.getInt(
833                 NoBackupKeys.KEY_NUM_DAYS_DAILY_ROTATION_NOT_ATTEMPTED, 0);
834     }
835 
836     @Override
resetNumDaysDailyRotationNotAttempted()837     public void resetNumDaysDailyRotationNotAttempted() {
838         mNoBackupPrefs.edit()
839                 .putInt(NoBackupKeys.KEY_NUM_DAYS_DAILY_ROTATION_NOT_ATTEMPTED, 0)
840                 .apply();
841     }
842 
843     @Override
getAppLaunchCount()844     public int getAppLaunchCount() {
845         return mNoBackupPrefs.getInt(NoBackupKeys.KEY_APP_LAUNCH_COUNT, 0);
846     }
847 
setAppLaunchCount(int count)848     private void setAppLaunchCount(int count) {
849         mNoBackupPrefs.edit().putInt(NoBackupKeys.KEY_APP_LAUNCH_COUNT, count).apply();
850     }
851 
852     @Override
getFirstLaunchDateSinceSetup()853     public int getFirstLaunchDateSinceSetup() {
854         return mNoBackupPrefs.getInt(NoBackupKeys.KEY_FIRST_LAUNCH_DATE_SINCE_SETUP, 0);
855     }
856 
setFirstLaunchDateSinceSetup(int firstLaunchDate)857     private void setFirstLaunchDateSinceSetup(int firstLaunchDate) {
858         mNoBackupPrefs.edit().putInt(NoBackupKeys.KEY_FIRST_LAUNCH_DATE_SINCE_SETUP,
859                 firstLaunchDate).apply();
860     }
861 
862     @Override
getFirstWallpaperApplyDateSinceSetup()863     public int getFirstWallpaperApplyDateSinceSetup() {
864         return mNoBackupPrefs.getInt(NoBackupKeys.KEY_FIRST_WALLPAPER_APPLY_DATE_SINCE_SETUP, 0);
865     }
866 
setFirstWallpaperApplyDateSinceSetup(int firstApplyDate)867     private void setFirstWallpaperApplyDateSinceSetup(int firstApplyDate) {
868         mNoBackupPrefs.edit().putInt(NoBackupKeys.KEY_FIRST_WALLPAPER_APPLY_DATE_SINCE_SETUP,
869                 firstApplyDate).apply();
870     }
871 
872     @Override
incrementAppLaunched()873     public void incrementAppLaunched() {
874         if (getFirstLaunchDateSinceSetup() == 0) {
875             setFirstLaunchDateSinceSetup(getCurrentDate());
876         }
877 
878         int appLaunchCount = getAppLaunchCount();
879         if (appLaunchCount < Integer.MAX_VALUE) {
880             setAppLaunchCount(appLaunchCount + 1);
881         }
882     }
883 
setFirstWallpaperApplyDateIfNeeded()884     private void setFirstWallpaperApplyDateIfNeeded() {
885         if (getFirstWallpaperApplyDateSinceSetup() == 0) {
886             setFirstWallpaperApplyDateSinceSetup(getCurrentDate());
887         }
888     }
889 
890     @Override
updateDailyWallpaperSet(@estination int destination, String collectionId, String wallpaperId)891     public void updateDailyWallpaperSet(@Destination int destination, String collectionId,
892             String wallpaperId) {
893         // Assign wallpaper info by destination.
894         if (destination == WallpaperPersister.DEST_HOME_SCREEN) {
895             setHomeWallpaperCollectionId(collectionId);
896             setHomeWallpaperRemoteId(wallpaperId);
897         } else if (destination == WallpaperPersister.DEST_LOCK_SCREEN) {
898             setLockWallpaperCollectionId(collectionId);
899             setLockWallpaperRemoteId(wallpaperId);
900         } else if (destination == WallpaperPersister.DEST_BOTH) {
901             setHomeWallpaperCollectionId(collectionId);
902             setHomeWallpaperRemoteId(wallpaperId);
903             setLockWallpaperCollectionId(collectionId);
904             setLockWallpaperRemoteId(wallpaperId);
905         }
906     }
907 
getCurrentDate()908     private int getCurrentDate() {
909         Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
910         SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd", Locale.US);
911         return Integer.parseInt(format.format(calendar.getTime()));
912     }
913 }
914