1 /*
<lambda>null2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.service.settings.preferences
18 
19 import android.Manifest
20 import android.content.Context
21 import android.os.OutcomeReceiver
22 import android.platform.test.annotations.RequiresFlagsEnabled
23 import android.platform.test.flag.junit.CheckFlagsRule
24 import android.platform.test.flag.junit.DeviceFlagsValueProvider
25 import androidx.test.platform.app.InstrumentationRegistry
26 import com.android.bedstead.harrier.BedsteadJUnit4
27 import com.android.bedstead.nene.TestApis
28 import com.android.settingslib.flags.Flags.FLAG_SETTINGS_CATALYST
29 import com.android.settingslib.flags.Flags.FLAG_WRITE_SYSTEM_PREFERENCE_PERMISSION_ENABLED
30 import com.google.common.truth.Truth
31 import java.util.concurrent.CountDownLatch
32 import java.util.concurrent.TimeUnit
33 import org.junit.After
34 import org.junit.Before
35 import org.junit.Rule
36 import org.junit.Test
37 import org.junit.runner.RunWith
38 
39 @RunWith(BedsteadJUnit4::class)
40 class SettingsPreferenceServiceClientTest {
41 
42     @get:Rule
43     val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
44 
45     private lateinit var context: Context
46     private lateinit var client: SettingsPreferenceServiceClient
47 
48     @Before
49     fun setup() {
50         val connectionLatch = CountDownLatch(1)
51         context = InstrumentationRegistry.getInstrumentation().context
52         TestApis.permissions().withPermission(Manifest.permission.READ_SYSTEM_PREFERENCES).use {
53             client = SettingsPreferenceServiceClient(
54                 context,
55                 "android.service.settings.preferences.cts",
56                 false,
57                 context.mainExecutor,
58                 object : OutcomeReceiver<SettingsPreferenceServiceClient, Exception> {
59                     override fun onResult(result: SettingsPreferenceServiceClient) {
60                         connectionLatch.countDown()
61                     }
62 
63                     override fun onError(error: Exception) {
64                         throw AssertionError("Binding failed")
65                     }
66                 }
67             )
68             if (!connectionLatch.await(1, TimeUnit.SECONDS)) {
69                 throw AssertionError("Binding timeout")
70             }
71         }
72     }
73 
74     @After
75     fun teardown() {
76         client.close()
77     }
78 
79     @RequiresFlagsEnabled(FLAG_SETTINGS_CATALYST)
80     @Test
81     fun getAllPreferenceMetadata_retrievesResult() {
82         val statusLatch = CountDownLatch(1)
83         TestApis.permissions().withPermission(Manifest.permission.READ_SYSTEM_PREFERENCES).use {
84             client.getAllPreferenceMetadata(
85                 MetadataRequest.Builder().build(),
86                 context.mainExecutor
87             ) { result ->
88                 Truth.assertThat(result.resultCode).isEqualTo(MetadataResult.RESULT_OK)
89                 Truth.assertThat(result.metadataList).isNotEmpty()
90                 statusLatch.countDown()
91             }
92         }
93         Truth.assertThat(statusLatch.await(1, TimeUnit.SECONDS)).isTrue()
94     }
95 
96     @RequiresFlagsEnabled(FLAG_SETTINGS_CATALYST)
97     @Test
98     fun getPreferenceValue_retrievesResult() {
99         val statusLatch = CountDownLatch(1)
100         TestApis.permissions().withPermission(Manifest.permission.READ_SYSTEM_PREFERENCES).use {
101             client.getPreferenceValue(
102                 GetValueRequest.Builder("s", "k").build(),
103                 context.mainExecutor
104             ) { result ->
105                 Truth.assertThat(result.resultCode).isEqualTo(MetadataResult.RESULT_OK)
106                 Truth.assertThat(result.metadata).isNotNull()
107                 Truth.assertThat(result.value).isNotNull()
108                 statusLatch.countDown()
109             }
110         }
111         Truth.assertThat(statusLatch.await(1, TimeUnit.SECONDS)).isTrue()
112     }
113 
114     @RequiresFlagsEnabled(FLAG_SETTINGS_CATALYST)
115     @Test
116     fun getPreferenceValue_unsupportedKey_retrievesNoResult() {
117         val statusLatch = CountDownLatch(1)
118         TestApis.permissions().withPermission(Manifest.permission.READ_SYSTEM_PREFERENCES).use {
119             client.getPreferenceValue(
120                 GetValueRequest.Builder("invalid", "invalid").build(),
121                 context.mainExecutor
122             ) { result ->
123                 Truth.assertThat(result.resultCode).isEqualTo(MetadataResult.RESULT_UNSUPPORTED)
124                 Truth.assertThat(result.metadata).isNull()
125                 Truth.assertThat(result.value).isNull()
126                 statusLatch.countDown()
127             }
128         }
129         Truth.assertThat(statusLatch.await(1, TimeUnit.SECONDS)).isTrue()
130     }
131 
132     @RequiresFlagsEnabled(FLAG_SETTINGS_CATALYST, FLAG_WRITE_SYSTEM_PREFERENCE_PERMISSION_ENABLED)
133     @Test
134     fun setPreferenceValue_retrievesResult() {
135         val statusLatch = CountDownLatch(1)
136         TestApis.permissions().withPermission(
137             Manifest.permission.READ_SYSTEM_PREFERENCES,
138             Manifest.permission.WRITE_SYSTEM_PREFERENCES
139         ).withAppOp("android:write_system_preferences").use {
140             client.setPreferenceValue(
141                 SetValueRequest.Builder(
142                     "s",
143                     "k",
144                     SettingsPreferenceValue.Builder(SettingsPreferenceValue.TYPE_STRING)
145                         .setStringValue("value")
146                         .build()
147                 ).build(),
148                 context.mainExecutor
149             ) { result ->
150                 Truth.assertThat(result.resultCode).isEqualTo(MetadataResult.RESULT_OK)
151                 statusLatch.countDown()
152             }
153         }
154         Truth.assertThat(statusLatch.await(1, TimeUnit.SECONDS)).isTrue()
155     }
156 
157     @RequiresFlagsEnabled(FLAG_SETTINGS_CATALYST, FLAG_WRITE_SYSTEM_PREFERENCE_PERMISSION_ENABLED)
158     @Test
159     fun setPreferenceValue_withoutPermission_throwsException() {
160         val statusLatch = CountDownLatch(1)
161         client.setPreferenceValue(
162             SetValueRequest.Builder(
163                 "s",
164                 "k",
165                 SettingsPreferenceValue.Builder(SettingsPreferenceValue.TYPE_STRING)
166                     .setStringValue("value")
167                     .build()
168             ).build(),
169             context.mainExecutor,
170             object : OutcomeReceiver<SetValueResult, Exception> {
171                 override fun onResult(result: SetValueResult?) {
172                     throw AssertionError("onResult should not be invoked")
173                 }
174 
175                 override fun onError(error: Exception) {
176                     Truth.assertThat(error).isInstanceOf(SecurityException::class.java)
177                     statusLatch.countDown()
178                 }
179             }
180         )
181         Truth.assertThat(statusLatch.await(1, TimeUnit.SECONDS)).isTrue()
182     }
183 }
184