1 /*
<lambda>null2  * 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.WallpaperColors
19 import android.app.WallpaperManager.SetWallpaperFlags
20 import android.app.backup.BackupManager
21 import android.content.Context
22 import android.content.SharedPreferences
23 import android.content.SharedPreferences.OnSharedPreferenceChangeListener
24 import android.graphics.Bitmap
25 import android.graphics.Color
26 import android.graphics.Point
27 import android.graphics.Rect
28 import android.util.Log
29 import com.android.wallpaper.model.LiveWallpaperInfo
30 import com.android.wallpaper.model.LiveWallpaperPrefMetadata
31 import com.android.wallpaper.model.StaticWallpaperPrefMetadata
32 import com.android.wallpaper.model.WallpaperInfo
33 import com.android.wallpaper.module.WallpaperPreferenceKeys.NoBackupKeys
34 import com.android.wallpaper.module.WallpaperPreferences.Companion.generateRecentsKey
35 import com.android.wallpaper.module.WallpaperPreferences.PendingDailyWallpaperUpdateStatus
36 import com.android.wallpaper.module.WallpaperPreferences.PendingWallpaperSetStatus
37 import com.android.wallpaper.module.WallpaperPreferences.PresentationMode
38 import com.android.wallpaper.picker.customization.shared.model.WallpaperDestination
39 import com.android.wallpaper.picker.data.WallpaperModel.LiveWallpaperModel
40 import com.android.wallpaper.picker.data.WallpaperModel.StaticWallpaperModel
41 import java.text.SimpleDateFormat
42 import java.util.Calendar
43 import java.util.Locale
44 import java.util.TimeZone
45 import org.json.JSONArray
46 import org.json.JSONException
47 
48 /** Default implementation that writes to and reads from SharedPreferences. */
49 open class DefaultWallpaperPreferences(private val context: Context) : WallpaperPreferences {
50     protected val sharedPrefs: SharedPreferences =
51         context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
52     protected val noBackupPrefs: SharedPreferences =
53         context.getSharedPreferences(NO_BACKUP_PREFS_NAME, Context.MODE_PRIVATE)
54 
55     private val backupManager = BackupManager(context)
56     private val sharedPrefsChangedListener = OnSharedPreferenceChangeListener { _, _ ->
57         backupManager.dataChanged()
58     }
59 
60     init {
61         if (noBackupPrefs.all.isEmpty() && sharedPrefs.all.isNotEmpty()) {
62             upgradePrefs()
63         }
64         // Register a prefs changed listener so that all prefs changes trigger a backup event.
65         sharedPrefs.registerOnSharedPreferenceChangeListener(sharedPrefsChangedListener)
66     }
67 
68     /**
69      * Move [NoBackupKeys] preferences that might have been in mSharedPrefs from previous versions
70      * of the app into mNoBackupPrefs.
71      */
72     private fun upgradePrefs() {
73         val noBackupEditor = noBackupPrefs.edit()
74         if (sharedPrefs.contains(NoBackupKeys.KEY_HOME_WALLPAPER_BASE_IMAGE_URL)) {
75             noBackupEditor.putString(
76                 NoBackupKeys.KEY_HOME_WALLPAPER_BASE_IMAGE_URL,
77                 sharedPrefs.getString(NoBackupKeys.KEY_HOME_WALLPAPER_BASE_IMAGE_URL, null)
78             )
79         }
80         if (sharedPrefs.contains(NoBackupKeys.KEY_HOME_WALLPAPER_MANAGER_ID)) {
81             noBackupEditor.putInt(
82                 NoBackupKeys.KEY_HOME_WALLPAPER_MANAGER_ID,
83                 sharedPrefs.getInt(NoBackupKeys.KEY_HOME_WALLPAPER_MANAGER_ID, 0)
84             )
85         }
86         if (sharedPrefs.contains(NoBackupKeys.KEY_HOME_WALLPAPER_REMOTE_ID)) {
87             noBackupEditor.putString(
88                 NoBackupKeys.KEY_HOME_WALLPAPER_REMOTE_ID,
89                 sharedPrefs.getString(NoBackupKeys.KEY_HOME_WALLPAPER_REMOTE_ID, null)
90             )
91         }
92         if (sharedPrefs.contains(NoBackupKeys.KEY_HOME_WALLPAPER_BACKING_FILE)) {
93             noBackupEditor.putString(
94                 NoBackupKeys.KEY_HOME_WALLPAPER_BACKING_FILE,
95                 sharedPrefs.getString(NoBackupKeys.KEY_HOME_WALLPAPER_BACKING_FILE, null)
96             )
97         }
98         if (sharedPrefs.contains(NoBackupKeys.KEY_LOCK_WALLPAPER_MANAGER_ID)) {
99             noBackupEditor.putInt(
100                 NoBackupKeys.KEY_LOCK_WALLPAPER_MANAGER_ID,
101                 sharedPrefs.getInt(NoBackupKeys.KEY_LOCK_WALLPAPER_MANAGER_ID, 0)
102             )
103         }
104         if (sharedPrefs.contains(NoBackupKeys.KEY_LOCK_WALLPAPER_BACKING_FILE)) {
105             noBackupEditor.putString(
106                 NoBackupKeys.KEY_LOCK_WALLPAPER_BACKING_FILE,
107                 sharedPrefs.getString(NoBackupKeys.KEY_LOCK_WALLPAPER_BACKING_FILE, null)
108             )
109         }
110         if (sharedPrefs.contains(NoBackupKeys.KEY_DAILY_ROTATION_TIMESTAMPS)) {
111             noBackupEditor.putString(
112                 NoBackupKeys.KEY_DAILY_ROTATION_TIMESTAMPS,
113                 sharedPrefs.getString(NoBackupKeys.KEY_DAILY_ROTATION_TIMESTAMPS, null)
114             )
115         }
116         if (sharedPrefs.contains(NoBackupKeys.KEY_DAILY_WALLPAPER_ENABLED_TIMESTAMP)) {
117             noBackupEditor.putLong(
118                 NoBackupKeys.KEY_DAILY_WALLPAPER_ENABLED_TIMESTAMP,
119                 sharedPrefs.getLong(NoBackupKeys.KEY_DAILY_WALLPAPER_ENABLED_TIMESTAMP, -1)
120             )
121         }
122         if (sharedPrefs.contains(NoBackupKeys.KEY_LAST_DAILY_LOG_TIMESTAMP)) {
123             noBackupEditor.putLong(
124                 NoBackupKeys.KEY_LAST_DAILY_LOG_TIMESTAMP,
125                 sharedPrefs.getLong(NoBackupKeys.KEY_LAST_DAILY_LOG_TIMESTAMP, 0)
126             )
127         }
128         if (sharedPrefs.contains(NoBackupKeys.KEY_LAST_APP_ACTIVE_TIMESTAMP)) {
129             noBackupEditor.putLong(
130                 NoBackupKeys.KEY_LAST_APP_ACTIVE_TIMESTAMP,
131                 sharedPrefs.getLong(NoBackupKeys.KEY_LAST_APP_ACTIVE_TIMESTAMP, 0)
132             )
133         }
134         if (sharedPrefs.contains(NoBackupKeys.KEY_LAST_ROTATION_STATUS)) {
135             noBackupEditor.putInt(
136                 NoBackupKeys.KEY_LAST_ROTATION_STATUS,
137                 sharedPrefs.getInt(NoBackupKeys.KEY_LAST_ROTATION_STATUS, -1)
138             )
139         }
140         if (sharedPrefs.contains(NoBackupKeys.KEY_LAST_ROTATION_STATUS_TIMESTAMP)) {
141             noBackupEditor.putLong(
142                 NoBackupKeys.KEY_LAST_ROTATION_STATUS_TIMESTAMP,
143                 sharedPrefs.getLong(NoBackupKeys.KEY_LAST_ROTATION_STATUS_TIMESTAMP, 0)
144             )
145         }
146         if (sharedPrefs.contains(NoBackupKeys.KEY_LAST_SYNC_TIMESTAMP)) {
147             noBackupEditor.putLong(
148                 NoBackupKeys.KEY_LAST_SYNC_TIMESTAMP,
149                 sharedPrefs.getLong(NoBackupKeys.KEY_LAST_SYNC_TIMESTAMP, 0)
150             )
151         }
152         if (sharedPrefs.contains(NoBackupKeys.KEY_PENDING_WALLPAPER_SET_STATUS)) {
153             noBackupEditor.putInt(
154                 NoBackupKeys.KEY_PENDING_WALLPAPER_SET_STATUS,
155                 sharedPrefs.getInt(
156                     NoBackupKeys.KEY_PENDING_WALLPAPER_SET_STATUS,
157                     WallpaperPreferences.WALLPAPER_SET_NOT_PENDING
158                 )
159             )
160         }
161         if (sharedPrefs.contains(NoBackupKeys.KEY_PENDING_DAILY_WALLPAPER_UPDATE_STATUS)) {
162             noBackupEditor.putInt(
163                 NoBackupKeys.KEY_PENDING_DAILY_WALLPAPER_UPDATE_STATUS,
164                 sharedPrefs.getInt(
165                     NoBackupKeys.KEY_PENDING_DAILY_WALLPAPER_UPDATE_STATUS,
166                     WallpaperPreferences.DAILY_WALLPAPER_UPDATE_NOT_PENDING
167                 )
168             )
169         }
170         if (sharedPrefs.contains(NoBackupKeys.KEY_NUM_DAYS_DAILY_ROTATION_FAILED)) {
171             noBackupEditor.putInt(
172                 NoBackupKeys.KEY_NUM_DAYS_DAILY_ROTATION_FAILED,
173                 sharedPrefs.getInt(NoBackupKeys.KEY_NUM_DAYS_DAILY_ROTATION_FAILED, 0)
174             )
175         }
176         if (sharedPrefs.contains(NoBackupKeys.KEY_NUM_DAYS_DAILY_ROTATION_NOT_ATTEMPTED)) {
177             noBackupEditor.putInt(
178                 NoBackupKeys.KEY_NUM_DAYS_DAILY_ROTATION_NOT_ATTEMPTED,
179                 sharedPrefs.getInt(NoBackupKeys.KEY_NUM_DAYS_DAILY_ROTATION_NOT_ATTEMPTED, 0)
180             )
181         }
182         if (sharedPrefs.contains(NoBackupKeys.KEY_HOME_WALLPAPER_SERVICE_NAME)) {
183             noBackupEditor.putString(
184                 NoBackupKeys.KEY_HOME_WALLPAPER_SERVICE_NAME,
185                 sharedPrefs.getString(NoBackupKeys.KEY_HOME_WALLPAPER_SERVICE_NAME, null)
186             )
187         }
188         noBackupEditor.apply()
189     }
190 
191     private fun getResIdPersistedByName(key: String, type: String): Int {
192         val resName = sharedPrefs.getString(key, null) ?: return 0
193         return context.resources.getIdentifier(resName, type, context.packageName)
194     }
195 
196     private fun persistResIdByName(key: String, resId: Int) {
197         sharedPrefs.edit().putString(key, getResName(resId)).apply()
198     }
199 
200     private fun getResName(resId: Int): String {
201         return context.resources.getResourceName(resId)
202     }
203 
204     override fun getWallpaperPresentationMode(): Int {
205         @PresentationMode
206         val homeWallpaperPresentationMode =
207             sharedPrefs.getInt(
208                 WallpaperPreferenceKeys.KEY_WALLPAPER_PRESENTATION_MODE,
209                 WallpaperPreferences.PRESENTATION_MODE_STATIC
210             )
211         return homeWallpaperPresentationMode
212     }
213 
214     override fun setWallpaperPresentationMode(@PresentationMode presentationMode: Int) {
215         sharedPrefs
216             .edit()
217             .putInt(WallpaperPreferenceKeys.KEY_WALLPAPER_PRESENTATION_MODE, presentationMode)
218             .apply()
219     }
220 
221     override fun getHomeWallpaperAttributions(): List<String?>? {
222         return listOf(
223             sharedPrefs.getString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_1, null),
224             sharedPrefs.getString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_2, null),
225             sharedPrefs.getString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_3, null)
226         )
227     }
228 
229     override fun setHomeWallpaperAttributions(attributions: List<String?>?) {
230         if (attributions.isNullOrEmpty()) {
231             return
232         }
233         val editor = sharedPrefs.edit()
234         attributions.take(3).forEachIndexed { index, attr ->
235             when (index) {
236                 0 -> editor.putString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_1, attr)
237                 1 -> editor.putString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_2, attr)
238                 2 -> editor.putString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_3, attr)
239             }
240         }
241         editor.apply()
242     }
243 
244     override fun getHomeWallpaperActionUrl(): String? {
245         return sharedPrefs.getString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ACTION_URL, null)
246     }
247 
248     override fun setHomeWallpaperActionUrl(actionUrl: String?) {
249         sharedPrefs
250             .edit()
251             .putString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ACTION_URL, actionUrl)
252             .apply()
253     }
254 
255     override fun getHomeWallpaperCollectionId(): String? {
256         return sharedPrefs.getString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_COLLECTION_ID, null)
257     }
258 
259     override fun setHomeWallpaperCollectionId(collectionId: String?) {
260         sharedPrefs
261             .edit()
262             .putString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_COLLECTION_ID, collectionId)
263             .apply()
264     }
265 
266     override fun clearHomeWallpaperMetadata() {
267         sharedPrefs
268             .edit()
269             .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_1)
270             .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_2)
271             .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_3)
272             .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ACTION_URL)
273             .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_COLLECTION_ID)
274             .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_HASH_CODE)
275             .apply()
276         noBackupPrefs
277             .edit()
278             .remove(NoBackupKeys.KEY_HOME_WALLPAPER_SERVICE_NAME)
279             .remove(NoBackupKeys.KEY_HOME_WALLPAPER_EFFECTS)
280             .remove(NoBackupKeys.KEY_HOME_WALLPAPER_MANAGER_ID)
281             .remove(NoBackupKeys.KEY_HOME_WALLPAPER_REMOTE_ID)
282             .remove(NoBackupKeys.KEY_HOME_WALLPAPER_BASE_IMAGE_URL)
283             .remove(NoBackupKeys.KEY_HOME_WALLPAPER_BACKING_FILE)
284             .apply()
285     }
286 
287     override fun setHomeStaticImageWallpaperMetadata(metadata: StaticWallpaperPrefMetadata) {
288         val sharedEditor = sharedPrefs.edit()
289         val attributions = metadata.attributions
290         if (!attributions.isNullOrEmpty()) {
291             attributions.take(3).forEachIndexed { index, attr ->
292                 when (index) {
293                     0 ->
294                         sharedEditor.putString(
295                             WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_1,
296                             attr
297                         )
298                     1 ->
299                         sharedEditor.putString(
300                             WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_2,
301                             attr
302                         )
303                     2 ->
304                         sharedEditor.putString(
305                             WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_3,
306                             attr
307                         )
308                 }
309             }
310         }
311         sharedEditor.putString(
312             WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ACTION_URL,
313             metadata.actionUrl
314         )
315         sharedEditor.putString(
316             WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_COLLECTION_ID,
317             metadata.collectionId
318         )
319         val hashCode = metadata.hashCode
320         if (hashCode != null) {
321             sharedEditor.putLong(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_HASH_CODE, hashCode)
322         }
323         sharedEditor.apply()
324 
325         val noBackupEditor = noBackupPrefs.edit()
326         noBackupEditor.putInt(NoBackupKeys.KEY_HOME_WALLPAPER_MANAGER_ID, metadata.managerId)
327         noBackupEditor.putString(NoBackupKeys.KEY_HOME_WALLPAPER_REMOTE_ID, metadata.remoteId)
328         noBackupEditor.apply()
329     }
330 
331     override fun setHomeLiveWallpaperMetadata(metadata: LiveWallpaperPrefMetadata) {
332         val sharedEditor = sharedPrefs.edit()
333         val attributions = metadata.attributions
334         if (!attributions.isNullOrEmpty()) {
335             attributions.take(3).forEachIndexed { index, attr ->
336                 when (index) {
337                     0 ->
338                         sharedEditor.putString(
339                             WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_1,
340                             attr
341                         )
342                     1 ->
343                         sharedEditor.putString(
344                             WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_2,
345                             attr
346                         )
347                     2 ->
348                         sharedEditor.putString(
349                             WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_3,
350                             attr
351                         )
352                 }
353             }
354         }
355         sharedEditor.putString(
356             WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_COLLECTION_ID,
357             metadata.collectionId
358         )
359         sharedEditor.apply()
360 
361         val noBackupEditor = noBackupPrefs.edit()
362         noBackupEditor.putString(NoBackupKeys.KEY_HOME_WALLPAPER_SERVICE_NAME, metadata.serviceName)
363         noBackupEditor.putString(NoBackupKeys.KEY_HOME_WALLPAPER_EFFECTS, metadata.effectName)
364         noBackupEditor.putInt(NoBackupKeys.KEY_HOME_WALLPAPER_MANAGER_ID, metadata.managerId)
365         noBackupEditor.apply()
366     }
367 
368     override fun getHomeWallpaperHashCode(): Long {
369         return sharedPrefs.getLong(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_HASH_CODE, 0)
370     }
371 
372     override fun setHomeWallpaperHashCode(hashCode: Long) {
373         sharedPrefs
374             .edit()
375             .putLong(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_HASH_CODE, hashCode)
376             .apply()
377     }
378 
379     override fun getHomeWallpaperServiceName(): String? {
380         return noBackupPrefs.getString(NoBackupKeys.KEY_HOME_WALLPAPER_SERVICE_NAME, null)
381     }
382 
383     override fun setHomeWallpaperServiceName(serviceName: String?) {
384         noBackupPrefs
385             .edit()
386             .putString(NoBackupKeys.KEY_HOME_WALLPAPER_SERVICE_NAME, serviceName)
387             .apply()
388         setFirstWallpaperApplyDateIfNeeded()
389     }
390 
391     override fun getHomeWallpaperManagerId(): Int {
392         return noBackupPrefs.getInt(NoBackupKeys.KEY_HOME_WALLPAPER_MANAGER_ID, 0)
393     }
394 
395     override fun setHomeWallpaperManagerId(homeWallpaperId: Int) {
396         noBackupPrefs
397             .edit()
398             .putInt(NoBackupKeys.KEY_HOME_WALLPAPER_MANAGER_ID, homeWallpaperId)
399             .apply()
400     }
401 
402     override fun getHomeWallpaperRemoteId(): String? {
403         return noBackupPrefs.getString(NoBackupKeys.KEY_HOME_WALLPAPER_REMOTE_ID, null)
404     }
405 
406     override fun setHomeWallpaperRemoteId(wallpaperRemoteId: String?) {
407         noBackupPrefs
408             .edit()
409             .putString(NoBackupKeys.KEY_HOME_WALLPAPER_REMOTE_ID, wallpaperRemoteId)
410             .apply()
411         setFirstWallpaperApplyDateIfNeeded()
412     }
413 
414     override fun getHomeWallpaperRecentsKey(): String? {
415         return noBackupPrefs.getString(
416             NoBackupKeys.KEY_HOME_WALLPAPER_RECENTS_KEY,
417             generateRecentsKey(getHomeWallpaperRemoteId(), getHomeWallpaperHashCode())
418         )
419     }
420 
421     override fun setHomeWallpaperRecentsKey(recentsKey: String?) {
422         noBackupPrefs
423             .edit()
424             .putString(NoBackupKeys.KEY_HOME_WALLPAPER_RECENTS_KEY, recentsKey)
425             .apply()
426     }
427 
428     override fun getHomeWallpaperEffects(): String? {
429         return noBackupPrefs.getString(NoBackupKeys.KEY_HOME_WALLPAPER_EFFECTS, null)
430     }
431 
432     override fun setHomeWallpaperEffects(wallpaperEffects: String?) {
433         noBackupPrefs
434             .edit()
435             .putString(NoBackupKeys.KEY_HOME_WALLPAPER_EFFECTS, wallpaperEffects)
436             .apply()
437     }
438 
439     override fun getLockWallpaperAttributions(): List<String?>? {
440         return listOf(
441             sharedPrefs.getString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_1, null),
442             sharedPrefs.getString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_2, null),
443             sharedPrefs.getString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_3, null)
444         )
445     }
446 
447     override fun setLockWallpaperAttributions(attributions: List<String?>?) {
448         if (attributions.isNullOrEmpty()) {
449             return
450         }
451         val editor = sharedPrefs.edit()
452         attributions.take(3).forEachIndexed { index, attr ->
453             when (index) {
454                 0 -> editor.putString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_1, attr)
455                 1 -> editor.putString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_2, attr)
456                 2 -> editor.putString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_3, attr)
457             }
458         }
459         editor.apply()
460     }
461 
462     override fun getLockWallpaperActionUrl(): String? {
463         return sharedPrefs.getString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ACTION_URL, null)
464     }
465 
466     override fun setLockWallpaperActionUrl(actionUrl: String?) {
467         sharedPrefs
468             .edit()
469             .putString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ACTION_URL, actionUrl)
470             .apply()
471     }
472 
473     override fun getLockWallpaperCollectionId(): String? {
474         return sharedPrefs.getString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_COLLECTION_ID, null)
475     }
476 
477     override fun setLockWallpaperCollectionId(collectionId: String?) {
478         sharedPrefs
479             .edit()
480             .putString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_COLLECTION_ID, collectionId)
481             .apply()
482     }
483 
484     override fun clearLockWallpaperMetadata() {
485         sharedPrefs
486             .edit()
487             .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_1)
488             .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_2)
489             .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_3)
490             .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ACTION_URL)
491             .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_COLLECTION_ID)
492             .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_HASH_CODE)
493             .apply()
494         noBackupPrefs
495             .edit()
496             .remove(NoBackupKeys.KEY_LOCK_WALLPAPER_SERVICE_NAME)
497             .remove(NoBackupKeys.KEY_LOCK_WALLPAPER_EFFECTS)
498             .remove(NoBackupKeys.KEY_LOCK_WALLPAPER_MANAGER_ID)
499             .remove(NoBackupKeys.KEY_LOCK_WALLPAPER_REMOTE_ID)
500             .remove(NoBackupKeys.KEY_LOCK_WALLPAPER_BACKING_FILE)
501             .apply()
502     }
503 
504     override fun setLockStaticImageWallpaperMetadata(metadata: StaticWallpaperPrefMetadata) {
505         val sharedEditor = sharedPrefs.edit()
506         val attributions = metadata.attributions
507         if (!attributions.isNullOrEmpty()) {
508             attributions.take(3).forEachIndexed { index, attr ->
509                 when (index) {
510                     0 ->
511                         sharedEditor.putString(
512                             WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_1,
513                             attr
514                         )
515                     1 ->
516                         sharedEditor.putString(
517                             WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_2,
518                             attr
519                         )
520                     2 ->
521                         sharedEditor.putString(
522                             WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_3,
523                             attr
524                         )
525                 }
526             }
527         }
528         sharedEditor.putString(
529             WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ACTION_URL,
530             metadata.actionUrl
531         )
532         sharedEditor.putString(
533             WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_COLLECTION_ID,
534             metadata.collectionId
535         )
536         val hashCode = metadata.hashCode
537         if (hashCode != null) {
538             sharedEditor.putLong(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_HASH_CODE, hashCode)
539         }
540         sharedEditor.apply()
541 
542         val noBackupEditor = noBackupPrefs.edit()
543         noBackupEditor.putInt(NoBackupKeys.KEY_LOCK_WALLPAPER_MANAGER_ID, metadata.managerId)
544         noBackupEditor.putString(NoBackupKeys.KEY_LOCK_WALLPAPER_REMOTE_ID, metadata.remoteId)
545         noBackupEditor.apply()
546     }
547 
548     override fun setLockLiveWallpaperMetadata(metadata: LiveWallpaperPrefMetadata) {
549         val sharedEditor = sharedPrefs.edit()
550         val attributions = metadata.attributions
551         if (!attributions.isNullOrEmpty()) {
552             attributions.take(3).forEachIndexed { index, attr ->
553                 when (index) {
554                     0 ->
555                         sharedEditor.putString(
556                             WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_1,
557                             attr
558                         )
559                     1 ->
560                         sharedEditor.putString(
561                             WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_2,
562                             attr
563                         )
564                     2 ->
565                         sharedEditor.putString(
566                             WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_3,
567                             attr
568                         )
569                 }
570             }
571         }
572         sharedEditor.putString(
573             WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_COLLECTION_ID,
574             metadata.collectionId
575         )
576         sharedEditor.apply()
577 
578         val noBackupEditor = noBackupPrefs.edit()
579         noBackupEditor.putString(NoBackupKeys.KEY_LOCK_WALLPAPER_SERVICE_NAME, metadata.serviceName)
580         noBackupEditor.putString(NoBackupKeys.KEY_LOCK_WALLPAPER_EFFECTS, metadata.effectName)
581         noBackupEditor.putInt(NoBackupKeys.KEY_LOCK_WALLPAPER_MANAGER_ID, metadata.managerId)
582         noBackupEditor.apply()
583     }
584 
585     override fun getLockWallpaperHashCode(): Long {
586         return sharedPrefs.getLong(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_HASH_CODE, 0)
587     }
588 
589     override fun setLockWallpaperHashCode(hashCode: Long) {
590         sharedPrefs
591             .edit()
592             .putLong(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_HASH_CODE, hashCode)
593             .apply()
594     }
595 
596     override fun getLockWallpaperServiceName(): String? {
597         return noBackupPrefs.getString(NoBackupKeys.KEY_LOCK_WALLPAPER_SERVICE_NAME, null)
598     }
599 
600     override fun setLockWallpaperServiceName(serviceName: String?) {
601         noBackupPrefs
602             .edit()
603             .putString(NoBackupKeys.KEY_LOCK_WALLPAPER_SERVICE_NAME, serviceName)
604             .apply()
605     }
606 
607     override fun getLockWallpaperManagerId(): Int {
608         return noBackupPrefs.getInt(NoBackupKeys.KEY_LOCK_WALLPAPER_MANAGER_ID, 0)
609     }
610 
611     override fun setLockWallpaperManagerId(lockWallpaperId: Int) {
612         noBackupPrefs
613             .edit()
614             .putInt(NoBackupKeys.KEY_LOCK_WALLPAPER_MANAGER_ID, lockWallpaperId)
615             .apply()
616     }
617 
618     override fun getLockWallpaperRemoteId(): String? {
619         return noBackupPrefs.getString(NoBackupKeys.KEY_LOCK_WALLPAPER_REMOTE_ID, null)
620     }
621 
622     override fun setLockWallpaperRemoteId(wallpaperRemoteId: String?) {
623         noBackupPrefs
624             .edit()
625             .putString(NoBackupKeys.KEY_LOCK_WALLPAPER_REMOTE_ID, wallpaperRemoteId)
626             .apply()
627         setFirstWallpaperApplyDateIfNeeded()
628     }
629 
630     override fun getLockWallpaperRecentsKey(): String? {
631         return noBackupPrefs.getString(
632             NoBackupKeys.KEY_LOCK_WALLPAPER_RECENTS_KEY,
633             generateRecentsKey(getLockWallpaperRemoteId(), getLockWallpaperHashCode())
634         )
635     }
636 
637     override fun setLockWallpaperRecentsKey(recentsKey: String?) {
638         noBackupPrefs
639             .edit()
640             .putString(NoBackupKeys.KEY_LOCK_WALLPAPER_RECENTS_KEY, recentsKey)
641             .apply()
642     }
643 
644     override fun getLockWallpaperEffects(): String? {
645         return noBackupPrefs.getString(NoBackupKeys.KEY_LOCK_WALLPAPER_EFFECTS, null)
646     }
647 
648     override fun setLockWallpaperEffects(wallpaperEffects: String?) {
649         noBackupPrefs
650             .edit()
651             .putString(NoBackupKeys.KEY_LOCK_WALLPAPER_EFFECTS, wallpaperEffects)
652             .apply()
653     }
654 
655     override fun addDailyRotation(timestamp: Long) {
656         val jsonString = noBackupPrefs.getString(NoBackupKeys.KEY_DAILY_ROTATION_TIMESTAMPS, "[]")
657         try {
658             val jsonArray = JSONArray(jsonString)
659             jsonArray.put(timestamp)
660             noBackupPrefs
661                 .edit()
662                 .putString(NoBackupKeys.KEY_DAILY_ROTATION_TIMESTAMPS, jsonArray.toString())
663                 .apply()
664         } catch (e: JSONException) {
665             Log.e(TAG, "Failed to add a daily rotation timestamp due to a JSON parse exception")
666         }
667     }
668 
669     override fun getLastDailyRotationTimestamp(): Long {
670         val jsonString = noBackupPrefs.getString(NoBackupKeys.KEY_DAILY_ROTATION_TIMESTAMPS, "[]")
671         return try {
672             val jsonArray = JSONArray(jsonString)
673             if (jsonArray.length() == 0) {
674                 -1
675             } else jsonArray.getLong(jsonArray.length() - 1)
676         } catch (e: JSONException) {
677             Log.e(TAG, "Failed to find a daily rotation timestamp due to a JSON parse exception")
678             -1
679         }
680     }
681 
682     override fun getDailyWallpaperEnabledTimestamp(): Long {
683         return noBackupPrefs.getLong(NoBackupKeys.KEY_DAILY_WALLPAPER_ENABLED_TIMESTAMP, -1)
684     }
685 
686     override fun setDailyWallpaperEnabledTimestamp(timestamp: Long) {
687         noBackupPrefs
688             .edit()
689             .putLong(NoBackupKeys.KEY_DAILY_WALLPAPER_ENABLED_TIMESTAMP, timestamp)
690             .apply()
691     }
692 
693     override fun clearDailyRotations() {
694         noBackupPrefs
695             .edit()
696             .remove(NoBackupKeys.KEY_DAILY_ROTATION_TIMESTAMPS)
697             .remove(NoBackupKeys.KEY_DAILY_WALLPAPER_ENABLED_TIMESTAMP)
698             .apply()
699     }
700 
701     override fun getLastDailyLogTimestamp(): Long {
702         return noBackupPrefs.getLong(NoBackupKeys.KEY_LAST_DAILY_LOG_TIMESTAMP, 0)
703     }
704 
705     override fun setLastDailyLogTimestamp(timestamp: Long) {
706         noBackupPrefs.edit().putLong(NoBackupKeys.KEY_LAST_DAILY_LOG_TIMESTAMP, timestamp).apply()
707     }
708 
709     override fun getLastAppActiveTimestamp(): Long {
710         return noBackupPrefs.getLong(NoBackupKeys.KEY_LAST_APP_ACTIVE_TIMESTAMP, 0)
711     }
712 
713     override fun setLastAppActiveTimestamp(timestamp: Long) {
714         noBackupPrefs.edit().putLong(NoBackupKeys.KEY_LAST_APP_ACTIVE_TIMESTAMP, timestamp).apply()
715     }
716 
717     override fun setDailyWallpaperRotationStatus(status: Int, timestamp: Long) {
718         noBackupPrefs
719             .edit()
720             .putInt(NoBackupKeys.KEY_LAST_ROTATION_STATUS, status)
721             .putLong(NoBackupKeys.KEY_LAST_ROTATION_STATUS_TIMESTAMP, timestamp)
722             .apply()
723     }
724 
725     override fun setPendingWallpaperSetStatusSync(@PendingWallpaperSetStatus setStatus: Int) {
726         noBackupPrefs
727             .edit()
728             .putInt(NoBackupKeys.KEY_PENDING_WALLPAPER_SET_STATUS, setStatus)
729             .commit()
730     }
731 
732     @PendingWallpaperSetStatus
733     override fun getPendingWallpaperSetStatus(): Int {
734         return noBackupPrefs.getInt(
735             NoBackupKeys.KEY_PENDING_WALLPAPER_SET_STATUS,
736             WallpaperPreferences.WALLPAPER_SET_NOT_PENDING
737         )
738     }
739 
740     override fun setPendingWallpaperSetStatus(@PendingWallpaperSetStatus setStatus: Int) {
741         noBackupPrefs
742             .edit()
743             .putInt(NoBackupKeys.KEY_PENDING_WALLPAPER_SET_STATUS, setStatus)
744             .apply()
745     }
746 
747     override fun setPendingDailyWallpaperUpdateStatusSync(
748         @PendingDailyWallpaperUpdateStatus updateStatus: Int
749     ) {
750         noBackupPrefs
751             .edit()
752             .putInt(NoBackupKeys.KEY_PENDING_DAILY_WALLPAPER_UPDATE_STATUS, updateStatus)
753             .commit()
754     }
755 
756     @PendingDailyWallpaperUpdateStatus
757     override fun getPendingDailyWallpaperUpdateStatus(): Int {
758         return noBackupPrefs.getInt(
759             NoBackupKeys.KEY_PENDING_DAILY_WALLPAPER_UPDATE_STATUS,
760             WallpaperPreferences.DAILY_WALLPAPER_UPDATE_NOT_PENDING
761         )
762     }
763 
764     override fun setPendingDailyWallpaperUpdateStatus(
765         @PendingDailyWallpaperUpdateStatus updateStatus: Int
766     ) {
767         noBackupPrefs
768             .edit()
769             .putInt(NoBackupKeys.KEY_PENDING_DAILY_WALLPAPER_UPDATE_STATUS, updateStatus)
770             .apply()
771     }
772 
773     override fun getAppLaunchCount(): Int {
774         return noBackupPrefs.getInt(NoBackupKeys.KEY_APP_LAUNCH_COUNT, 0)
775     }
776 
777     override fun getFirstLaunchDateSinceSetup(): Int {
778         return noBackupPrefs.getInt(NoBackupKeys.KEY_FIRST_LAUNCH_DATE_SINCE_SETUP, 0)
779     }
780 
781     override fun incrementAppLaunched() {
782         if (getFirstLaunchDateSinceSetup() == 0) {
783             setFirstLaunchDateSinceSetup(getCurrentDate())
784         }
785 
786         val appLaunchCount = getAppLaunchCount()
787         if (appLaunchCount < Int.MAX_VALUE) {
788             setAppLaunchCount(appLaunchCount + 1)
789         }
790     }
791 
792     override fun getFirstWallpaperApplyDateSinceSetup(): Int {
793         return noBackupPrefs.getInt(NoBackupKeys.KEY_FIRST_WALLPAPER_APPLY_DATE_SINCE_SETUP, 0)
794     }
795 
796     override fun storeWallpaperColors(
797         storedWallpaperId: String?,
798         wallpaperColors: WallpaperColors?
799     ) {
800         if (storedWallpaperId == null || wallpaperColors == null) {
801             return
802         }
803         val primaryColor = wallpaperColors.primaryColor
804         var value = java.lang.String(primaryColor.toArgb().toString()) as String
805         val secondaryColor = wallpaperColors.secondaryColor
806         if (secondaryColor != null) {
807             value += "," + secondaryColor.toArgb()
808         }
809         val tertiaryColor = wallpaperColors.tertiaryColor
810         if (tertiaryColor != null) {
811             value += "," + tertiaryColor.toArgb()
812         }
813         noBackupPrefs
814             .edit()
815             .putString(NoBackupKeys.KEY_PREVIEW_WALLPAPER_COLOR_ID + storedWallpaperId, value)
816             .apply()
817     }
818 
819     override fun getWallpaperColors(storedWallpaperId: String): WallpaperColors? {
820         val value =
821             noBackupPrefs.getString(
822                 NoBackupKeys.KEY_PREVIEW_WALLPAPER_COLOR_ID + storedWallpaperId,
823                 null
824             )
825         if (value == null || value.isEmpty()) {
826             return null
827         }
828         val colorStrings = value.split(",")
829         val colorPrimary = Color.valueOf(colorStrings[0].toInt())
830         var colorSecondary: Color? = null
831         if (colorStrings.size >= 2) {
832             colorSecondary = Color.valueOf(colorStrings[1].toInt())
833         }
834         var colorTerTiary: Color? = null
835         if (colorStrings.size >= 3) {
836             colorTerTiary = Color.valueOf(colorStrings[2].toInt())
837         }
838         return WallpaperColors(
839             colorPrimary,
840             colorSecondary,
841             colorTerTiary,
842             WallpaperColors.HINT_FROM_BITMAP
843         )
844     }
845 
846     override fun updateDailyWallpaperSet(
847         @WallpaperPersister.Destination destination: Int,
848         collectionId: String?,
849         wallpaperId: String?,
850     ) {
851         // Assign wallpaper info by destination.
852         when (destination) {
853             WallpaperPersister.DEST_HOME_SCREEN -> {
854                 setHomeWallpaperCollectionId(collectionId!!)
855                 setHomeWallpaperRemoteId(wallpaperId)
856             }
857             WallpaperPersister.DEST_LOCK_SCREEN -> {
858                 setLockWallpaperCollectionId(collectionId!!)
859                 setLockWallpaperRemoteId(wallpaperId!!)
860             }
861             WallpaperPersister.DEST_BOTH -> {
862                 setHomeWallpaperCollectionId(collectionId!!)
863                 setHomeWallpaperRemoteId(wallpaperId)
864                 setLockWallpaperCollectionId(collectionId)
865                 setLockWallpaperRemoteId(wallpaperId!!)
866             }
867         }
868         setHomeWallpaperEffects(null)
869     }
870 
871     override fun storeLatestWallpaper(
872         @SetWallpaperFlags which: Int,
873         wallpaperId: String,
874         wallpaper: LiveWallpaperInfo,
875         colors: WallpaperColors,
876     ) {}
877 
878     override fun storeLatestWallpaper(
879         @SetWallpaperFlags which: Int,
880         wallpaperId: String,
881         wallpaper: WallpaperInfo,
882         croppedWallpaperBitmap: Bitmap,
883         colors: WallpaperColors,
884     ) {}
885 
886     override fun storeLatestWallpaper(
887         @SetWallpaperFlags which: Int,
888         wallpaperId: String,
889         attributions: List<String>?,
890         actionUrl: String?,
891         collectionId: String?,
892         croppedWallpaperBitmap: Bitmap,
893         colors: WallpaperColors,
894     ) {}
895 
896     override suspend fun addStaticWallpaperToRecentWallpapers(
897         destination: WallpaperDestination,
898         wallpaperModel: StaticWallpaperModel,
899         bitmap: Bitmap,
900         cropHints: Map<Point, Rect>?,
901     ) {}
902 
903     override suspend fun addLiveWallpaperToRecentWallpapers(
904         destination: WallpaperDestination,
905         wallpaperModel: LiveWallpaperModel
906     ) {}
907 
908     override fun setHasSmallPreviewTooltipBeenShown(hasTooltipBeenShown: Boolean) {
909         sharedPrefs
910             .edit()
911             .putBoolean(
912                 WallpaperPreferenceKeys.KEY_HAS_SMALL_PREVIEW_TOOLTIP_BEEN_SHOWN,
913                 hasTooltipBeenShown
914             )
915             .apply()
916     }
917 
918     override fun getHasSmallPreviewTooltipBeenShown(): Boolean {
919         return sharedPrefs.getBoolean(
920             WallpaperPreferenceKeys.KEY_HAS_SMALL_PREVIEW_TOOLTIP_BEEN_SHOWN,
921             false
922         )
923     }
924 
925     override fun setHasFullPreviewTooltipBeenShown(hasTooltipBeenShown: Boolean) {
926         sharedPrefs
927             .edit()
928             .putBoolean(
929                 WallpaperPreferenceKeys.KEY_HAS_FULL_PREVIEW_TOOLTIP_BEEN_SHOWN,
930                 hasTooltipBeenShown
931             )
932             .apply()
933     }
934 
935     override fun getHasFullPreviewTooltipBeenShown(): Boolean {
936         return sharedPrefs.getBoolean(
937             WallpaperPreferenceKeys.KEY_HAS_FULL_PREVIEW_TOOLTIP_BEEN_SHOWN,
938             false
939         )
940     }
941 
942     private fun setFirstLaunchDateSinceSetup(firstLaunchDate: Int) {
943         noBackupPrefs
944             .edit()
945             .putInt(NoBackupKeys.KEY_FIRST_LAUNCH_DATE_SINCE_SETUP, firstLaunchDate)
946             .apply()
947     }
948 
949     private fun setAppLaunchCount(count: Int) {
950         noBackupPrefs.edit().putInt(NoBackupKeys.KEY_APP_LAUNCH_COUNT, count).apply()
951     }
952 
953     private fun setFirstWallpaperApplyDateSinceSetup(firstApplyDate: Int) {
954         noBackupPrefs
955             .edit()
956             .putInt(NoBackupKeys.KEY_FIRST_WALLPAPER_APPLY_DATE_SINCE_SETUP, firstApplyDate)
957             .apply()
958     }
959 
960     private fun setFirstWallpaperApplyDateIfNeeded() {
961         if (getFirstWallpaperApplyDateSinceSetup() == 0) {
962             setFirstWallpaperApplyDateSinceSetup(getCurrentDate())
963         }
964     }
965 
966     private fun getCurrentDate(): Int {
967         val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
968         val format = SimpleDateFormat("yyyyMMdd", Locale.US)
969         return format.format(calendar.time).toInt()
970     }
971 
972     companion object {
973         const val PREFS_NAME = "wallpaper"
974         const val NO_BACKUP_PREFS_NAME = "wallpaper-nobackup"
975         const val KEY_VALUE_DIVIDER = "="
976         private const val TAG = "DefaultWallpaperPreferences"
977     }
978 }
979