• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2023 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.launcher3
17 
18 import android.content.Context
19 import android.content.SharedPreferences
20 import android.content.SharedPreferences.OnSharedPreferenceChangeListener
21 import androidx.test.ext.junit.runners.AndroidJUnit4
22 import androidx.test.filters.SmallTest
23 import androidx.test.platform.app.InstrumentationRegistry
24 import com.android.launcher3.LauncherPrefs.Companion.BOOT_AWARE_PREFS_KEY
25 import com.google.common.truth.Truth.assertThat
26 import java.util.concurrent.CountDownLatch
27 import java.util.concurrent.TimeUnit
28 import org.junit.AfterClass
29 import org.junit.BeforeClass
30 import org.junit.Test
31 import org.junit.runner.RunWith
32 
33 private val TEST_BOOLEAN_ITEM = LauncherPrefs.nonRestorableItem("1", false)
34 private val TEST_STRING_ITEM = LauncherPrefs.nonRestorableItem("2", "( ͡❛ ͜ʖ ͡❛)")
35 private val TEST_INT_ITEM = LauncherPrefs.nonRestorableItem("3", -1)
36 private val TEST_CONTEXTUAL_ITEM = ContextualItem("4", true, { true }, false, Boolean::class.java)
37 
38 private const val TEST_DEFAULT_VALUE = "default"
39 private const val TEST_PREF_KEY = "test_pref_key"
40 
41 private const val WAIT_TIME_IN_SECONDS = 3L
42 
43 @SmallTest
44 @RunWith(AndroidJUnit4::class)
45 class LauncherPrefsTest {
46 
<lambda>null47     private val context by lazy { InstrumentationRegistry.getInstrumentation().targetContext }
<lambda>null48     private val launcherPrefs by lazy { LauncherPrefs.get(context) }
49 
50     companion object {
51         @BeforeClass
52         @JvmStatic
setupnull53         fun setup() {
54             isBootAwareStartupDataEnabled = true
55         }
56 
57         @AfterClass
58         @JvmStatic
teardownnull59         fun teardown() {
60             isBootAwareStartupDataEnabled = false
61         }
62     }
63 
64     @Test
has_keyMissingFromLauncherPrefs_returnsFalsenull65     fun has_keyMissingFromLauncherPrefs_returnsFalse() {
66         assertThat(launcherPrefs.has(TEST_BOOLEAN_ITEM)).isFalse()
67     }
68 
69     @Test
has_keyPresentInLauncherPrefs_returnsTruenull70     fun has_keyPresentInLauncherPrefs_returnsTrue() {
71         with(launcherPrefs) {
72             putSync(TEST_BOOLEAN_ITEM.to(TEST_BOOLEAN_ITEM.defaultValue))
73             assertThat(has(TEST_BOOLEAN_ITEM)).isTrue()
74             remove(TEST_BOOLEAN_ITEM)
75         }
76     }
77 
78     @Test
addListener_listeningForStringItemUpdates_isCorrectlyNotifiedOfUpdatesnull79     fun addListener_listeningForStringItemUpdates_isCorrectlyNotifiedOfUpdates() {
80         val latch = CountDownLatch(1)
81         val listener = OnSharedPreferenceChangeListener { _, _ -> latch.countDown() }
82 
83         with(launcherPrefs) {
84             putSync(TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue))
85             addListener(listener, TEST_STRING_ITEM)
86             putSync(TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue + "abc"))
87 
88             assertThat(latch.await(WAIT_TIME_IN_SECONDS, TimeUnit.SECONDS)).isTrue()
89             remove(TEST_STRING_ITEM)
90         }
91     }
92 
93     @Test
removeListener_previouslyListeningForStringItemUpdates_isNoLongerNotifiedOfUpdatesnull94     fun removeListener_previouslyListeningForStringItemUpdates_isNoLongerNotifiedOfUpdates() {
95         val latch = CountDownLatch(1)
96         val listener = OnSharedPreferenceChangeListener { _, _ -> latch.countDown() }
97 
98         with(launcherPrefs) {
99             addListener(listener, TEST_STRING_ITEM)
100             removeListener(listener, TEST_STRING_ITEM)
101             putSync(TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue + "hello."))
102 
103             // latch will be still be 1 (and await will return false) if the listener was not called
104             assertThat(latch.await(WAIT_TIME_IN_SECONDS, TimeUnit.SECONDS)).isFalse()
105             remove(TEST_STRING_ITEM)
106         }
107     }
108 
109     @Test
addListenerAndRemoveListener_forMultipleItems_bothWorkProperlynull110     fun addListenerAndRemoveListener_forMultipleItems_bothWorkProperly() {
111         var latch = CountDownLatch(3)
112         val listener = OnSharedPreferenceChangeListener { _, _ -> latch.countDown() }
113 
114         with(launcherPrefs) {
115             addListener(listener, TEST_INT_ITEM, TEST_STRING_ITEM, TEST_BOOLEAN_ITEM)
116             putSync(
117                 TEST_INT_ITEM.to(TEST_INT_ITEM.defaultValue + 123),
118                 TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue + "abc"),
119                 TEST_BOOLEAN_ITEM.to(!TEST_BOOLEAN_ITEM.defaultValue)
120             )
121             assertThat(latch.await(WAIT_TIME_IN_SECONDS, TimeUnit.SECONDS)).isTrue()
122 
123             removeListener(listener, TEST_INT_ITEM, TEST_STRING_ITEM, TEST_BOOLEAN_ITEM)
124             latch = CountDownLatch(1)
125             putSync(
126                 TEST_INT_ITEM.to(TEST_INT_ITEM.defaultValue),
127                 TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue),
128                 TEST_BOOLEAN_ITEM.to(TEST_BOOLEAN_ITEM.defaultValue)
129             )
130             remove(TEST_INT_ITEM, TEST_STRING_ITEM, TEST_BOOLEAN_ITEM)
131 
132             assertThat(latch.await(WAIT_TIME_IN_SECONDS, TimeUnit.SECONDS)).isFalse()
133         }
134     }
135 
136     @Test
get_booleanItemNotInLauncherprefs_returnsDefaultValuenull137     fun get_booleanItemNotInLauncherprefs_returnsDefaultValue() {
138         assertThat(launcherPrefs.get(TEST_BOOLEAN_ITEM)).isEqualTo(TEST_BOOLEAN_ITEM.defaultValue)
139     }
140 
141     @Test
get_stringItemNotInLauncherPrefs_returnsDefaultValuenull142     fun get_stringItemNotInLauncherPrefs_returnsDefaultValue() {
143         assertThat(launcherPrefs.get(TEST_STRING_ITEM)).isEqualTo(TEST_STRING_ITEM.defaultValue)
144     }
145 
146     @Test
get_intItemNotInLauncherprefs_returnsDefaultValuenull147     fun get_intItemNotInLauncherprefs_returnsDefaultValue() {
148         assertThat(launcherPrefs.get(TEST_INT_ITEM)).isEqualTo(TEST_INT_ITEM.defaultValue)
149     }
150 
151     @Test
put_storesItemInLauncherPrefs_successfullynull152     fun put_storesItemInLauncherPrefs_successfully() {
153         val notDefaultValue = !TEST_BOOLEAN_ITEM.defaultValue
154 
155         with(launcherPrefs) {
156             putSync(TEST_BOOLEAN_ITEM.to(notDefaultValue))
157             assertThat(get(TEST_BOOLEAN_ITEM)).isEqualTo(notDefaultValue)
158             remove(TEST_BOOLEAN_ITEM)
159         }
160     }
161 
162     @Test
put_storesListOfItemsInLauncherPrefs_successfullynull163     fun put_storesListOfItemsInLauncherPrefs_successfully() {
164         with(launcherPrefs) {
165             putSync(
166                 TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue),
167                 TEST_INT_ITEM.to(TEST_INT_ITEM.defaultValue),
168                 TEST_BOOLEAN_ITEM.to(TEST_BOOLEAN_ITEM.defaultValue)
169             )
170             assertThat(has(TEST_BOOLEAN_ITEM, TEST_INT_ITEM, TEST_STRING_ITEM)).isTrue()
171             remove(TEST_STRING_ITEM, TEST_INT_ITEM, TEST_BOOLEAN_ITEM)
172         }
173     }
174 
175     @Test
remove_deletesItemFromLauncherPrefs_successfullynull176     fun remove_deletesItemFromLauncherPrefs_successfully() {
177         val notDefaultValue = !TEST_BOOLEAN_ITEM.defaultValue
178 
179         with(launcherPrefs) {
180             putSync(TEST_BOOLEAN_ITEM.to(notDefaultValue))
181             remove(TEST_BOOLEAN_ITEM)
182             assertThat(get(TEST_BOOLEAN_ITEM)).isEqualTo(TEST_BOOLEAN_ITEM.defaultValue)
183         }
184     }
185 
186     @Test
get_contextualItem_returnsCorrectDefaultnull187     fun get_contextualItem_returnsCorrectDefault() {
188         assertThat(launcherPrefs.get(TEST_CONTEXTUAL_ITEM)).isTrue()
189     }
190 
191     @Test
getItemSharedPrefFile_forNonRestorableItem_isCorrectnull192     fun getItemSharedPrefFile_forNonRestorableItem_isCorrect() {
193         val nonRestorableItem = LauncherPrefs.nonRestorableItem(TEST_PREF_KEY, TEST_DEFAULT_VALUE)
194         assertThat(nonRestorableItem.sharedPrefFile).isEqualTo(LauncherFiles.DEVICE_PREFERENCES_KEY)
195     }
196 
197     @Test
getItemSharedPrefFile_forBackedUpItem_isCorrectnull198     fun getItemSharedPrefFile_forBackedUpItem_isCorrect() {
199         val backedUpItem = LauncherPrefs.backedUpItem(TEST_PREF_KEY, TEST_DEFAULT_VALUE)
200         assertThat(backedUpItem.sharedPrefFile).isEqualTo(LauncherFiles.SHARED_PREFERENCES_KEY)
201     }
202 
203     @Test
put_bootAwareItem_updatesDeviceProtectedStoragenull204     fun put_bootAwareItem_updatesDeviceProtectedStorage() {
205         val bootAwareItem =
206             LauncherPrefs.backedUpItem(TEST_PREF_KEY, TEST_DEFAULT_VALUE, isBootAware = true)
207 
208         val bootAwarePrefs: SharedPreferences =
209             context
210                 .createDeviceProtectedStorageContext()
211                 .getSharedPreferences(BOOT_AWARE_PREFS_KEY, Context.MODE_PRIVATE)
212         bootAwarePrefs.edit().remove(bootAwareItem.sharedPrefKey).commit()
213 
214         launcherPrefs.putSync(bootAwareItem.to(bootAwareItem.defaultValue))
215         assertThat(bootAwarePrefs.contains(bootAwareItem.sharedPrefKey)).isTrue()
216 
217         launcherPrefs.removeSync(bootAwareItem)
218     }
219 
220     @Test
put_bootAwareItem_updatesEncryptedStoragenull221     fun put_bootAwareItem_updatesEncryptedStorage() {
222         val bootAwareItem =
223             LauncherPrefs.backedUpItem(TEST_PREF_KEY, TEST_DEFAULT_VALUE, isBootAware = true)
224 
225         val encryptedPrefs: SharedPreferences =
226             context.getSharedPreferences(bootAwareItem.sharedPrefFile, Context.MODE_PRIVATE)
227         encryptedPrefs.edit().remove(bootAwareItem.sharedPrefKey).commit()
228 
229         launcherPrefs.putSync(bootAwareItem.to(TEST_STRING_ITEM.defaultValue))
230         assertThat(encryptedPrefs.contains(bootAwareItem.sharedPrefKey)).isTrue()
231 
232         launcherPrefs.removeSync(bootAwareItem)
233     }
234 
235     @Test
remove_bootAwareItem_removesFromDeviceProtectedStoragenull236     fun remove_bootAwareItem_removesFromDeviceProtectedStorage() {
237         val bootAwareItem =
238             LauncherPrefs.backedUpItem(TEST_PREF_KEY, TEST_DEFAULT_VALUE, isBootAware = true)
239 
240         val bootAwarePrefs: SharedPreferences =
241             context
242                 .createDeviceProtectedStorageContext()
243                 .getSharedPreferences(BOOT_AWARE_PREFS_KEY, Context.MODE_PRIVATE)
244 
245         bootAwarePrefs
246             .edit()
247             .putString(bootAwareItem.sharedPrefKey, bootAwareItem.defaultValue)
248             .commit()
249 
250         launcherPrefs.removeSync(bootAwareItem)
251         assertThat(bootAwarePrefs.contains(bootAwareItem.sharedPrefKey)).isFalse()
252     }
253 
254     @Test
remove_bootAwareItem_removesFromEncryptedStoragenull255     fun remove_bootAwareItem_removesFromEncryptedStorage() {
256         val bootAwareItem =
257             LauncherPrefs.backedUpItem(TEST_PREF_KEY, TEST_DEFAULT_VALUE, isBootAware = true)
258 
259         val encryptedPrefs: SharedPreferences =
260             context.getSharedPreferences(bootAwareItem.sharedPrefFile, Context.MODE_PRIVATE)
261 
262         encryptedPrefs
263             .edit()
264             .putString(bootAwareItem.sharedPrefKey, bootAwareItem.defaultValue)
265             .commit()
266 
267         launcherPrefs.removeSync(bootAwareItem)
268         assertThat(encryptedPrefs.contains(bootAwareItem.sharedPrefKey)).isFalse()
269     }
270 
271     @Test
migrate_bootAwareItemsToDeviceProtectedStorage_worksAsIntendednull272     fun migrate_bootAwareItemsToDeviceProtectedStorage_worksAsIntended() {
273         val bootAwareItem =
274             LauncherPrefs.backedUpItem(TEST_PREF_KEY, TEST_DEFAULT_VALUE, isBootAware = true)
275         launcherPrefs.removeSync(bootAwareItem)
276 
277         val bootAwarePrefs: SharedPreferences =
278             context
279                 .createDeviceProtectedStorageContext()
280                 .getSharedPreferences(BOOT_AWARE_PREFS_KEY, Context.MODE_PRIVATE)
281 
282         if (bootAwarePrefs.contains(bootAwareItem.sharedPrefKey)) {
283             bootAwarePrefs.edit().remove(bootAwareItem.sharedPrefKey).commit()
284         }
285 
286         val encryptedPrefs: SharedPreferences =
287             context.getSharedPreferences(bootAwareItem.sharedPrefFile, Context.MODE_PRIVATE)
288 
289         encryptedPrefs
290             .edit()
291             .putString(bootAwareItem.sharedPrefKey, bootAwareItem.defaultValue)
292             .commit()
293 
294         launcherPrefs.migrateStartupDataToDeviceProtectedStorage()
295         assertThat(bootAwarePrefs.contains(bootAwareItem.sharedPrefKey)).isTrue()
296 
297         launcherPrefs.removeSync(bootAwareItem)
298     }
299 
300     @Test
migrate_onlyEncryptedItemsToDeviceProtectedStorage_doesNotHappennull301     fun migrate_onlyEncryptedItemsToDeviceProtectedStorage_doesNotHappen() {
302         val onlyEncryptedItem =
303             LauncherPrefs.backedUpItem(
304                 TEST_PREF_KEY + "_",
305                 TEST_DEFAULT_VALUE + "_",
306                 isBootAware = false
307             )
308 
309         val bootAwarePrefs: SharedPreferences =
310             context
311                 .createDeviceProtectedStorageContext()
312                 .getSharedPreferences(BOOT_AWARE_PREFS_KEY, Context.MODE_PRIVATE)
313 
314         if (bootAwarePrefs.contains(onlyEncryptedItem.sharedPrefKey)) {
315             bootAwarePrefs.edit().remove(onlyEncryptedItem.sharedPrefKey).commit()
316         }
317 
318         val encryptedPrefs: SharedPreferences =
319             context.getSharedPreferences(onlyEncryptedItem.sharedPrefFile, Context.MODE_PRIVATE)
320 
321         encryptedPrefs
322             .edit()
323             .putString(onlyEncryptedItem.sharedPrefKey, onlyEncryptedItem.defaultValue)
324             .commit()
325 
326         launcherPrefs.migrateStartupDataToDeviceProtectedStorage()
327         assertThat(bootAwarePrefs.contains(onlyEncryptedItem.sharedPrefKey)).isFalse()
328 
329         encryptedPrefs.edit().remove(onlyEncryptedItem.sharedPrefKey).commit()
330     }
331 }
332