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