1 /*
2  * 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.server.credentials;
17 
18 import static com.google.common.truth.Truth.assertThat;
19 
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.os.UserHandle;
23 import android.provider.Settings;
24 
25 import androidx.annotation.NonNull;
26 import androidx.test.core.app.ApplicationProvider;
27 import androidx.test.filters.SmallTest;
28 import androidx.test.runner.AndroidJUnit4;
29 
30 import org.junit.Before;
31 import org.junit.Test;
32 import org.junit.runner.RunWith;
33 
34 import java.security.cert.CertificateException;
35 import java.util.HashSet;
36 import java.util.Set;
37 
38 /** atest FrameworksServicesTests:com.android.server.credentials.CredentialManagerServiceTest */
39 @RunWith(AndroidJUnit4.class)
40 @SmallTest
41 public final class CredentialManagerServiceTest {
42 
43     Context mContext = null;
44     MockSettingsWrapper mSettingsWrapper = null;
45 
46     @Before
setUp()47     public void setUp() throws CertificateException {
48         mContext = ApplicationProvider.getApplicationContext();
49         mSettingsWrapper = new MockSettingsWrapper(mContext);
50     }
51 
52     @Test
getStoredProviders_emptyValue_success()53     public void getStoredProviders_emptyValue_success() {
54         Set<String> providers = CredentialManagerService.getStoredProviders("", "");
55         assertThat(providers.size()).isEqualTo(0);
56     }
57 
58     @Test
getStoredProviders_nullValue_success()59     public void getStoredProviders_nullValue_success() {
60         Set<String> providers = CredentialManagerService.getStoredProviders(null, null);
61         assertThat(providers.size()).isEqualTo(0);
62     }
63 
64     @Test
getStoredProviders_success()65     public void getStoredProviders_success() {
66         Set<String> providers =
67                 CredentialManagerService.getStoredProviders(
68                         "com.example.test/.TestActivity:com.example.test/.TestActivity2:"
69                                 + "com.example.test2/.TestActivity:blank",
70                         "com.example.test");
71         assertThat(providers.size()).isEqualTo(1);
72         assertThat(providers.contains("com.example.test2/com.example.test2.TestActivity")).isTrue();
73     }
74 
75     @Test
onProviderRemoved_success()76     public void onProviderRemoved_success() {
77         setSettingsKey(
78                 Settings.Secure.AUTOFILL_SERVICE,
79                 CredentialManagerService.AUTOFILL_PLACEHOLDER_VALUE);
80         setSettingsKey(
81                 Settings.Secure.CREDENTIAL_SERVICE,
82                 "com.example.test/com.example.test.TestActivity:com.example.test2/com.example.test2.TestActivity");
83         setSettingsKey(
84                 Settings.Secure.CREDENTIAL_SERVICE_PRIMARY,
85                 "com.example.test/com.example.test.TestActivity");
86 
87         CredentialManagerService.updateProvidersWhenPackageRemoved(
88                 mSettingsWrapper, "com.example.test");
89 
90         assertThat(getSettingsKey(Settings.Secure.AUTOFILL_SERVICE)).isEqualTo("");
91         assertThat(getSettingsKey(Settings.Secure.CREDENTIAL_SERVICE))
92                 .isEqualTo("com.example.test2/com.example.test2.TestActivity");
93         assertThat(getSettingsKey(Settings.Secure.CREDENTIAL_SERVICE_PRIMARY)).isEqualTo("");
94     }
95 
96     @Test
onProviderRemoved_notPrimaryRemoved_success()97     public void onProviderRemoved_notPrimaryRemoved_success() {
98         final String testCredentialPrimaryValue = "com.example.test/com.example.test.TestActivity";
99         final String testCredentialValue =
100                 "com.example.test/com.example.test.TestActivity:com.example.test2/com.example.test2.TestActivity";
101 
102         setSettingsKey(
103                 Settings.Secure.AUTOFILL_SERVICE,
104                 CredentialManagerService.AUTOFILL_PLACEHOLDER_VALUE);
105         setSettingsKey(Settings.Secure.CREDENTIAL_SERVICE, testCredentialValue);
106         setSettingsKey(Settings.Secure.CREDENTIAL_SERVICE_PRIMARY, testCredentialPrimaryValue);
107 
108         CredentialManagerService.updateProvidersWhenPackageRemoved(
109                 mSettingsWrapper, "com.example.test3");
110 
111         // Since the provider removed was not a primary provider then we should do nothing.
112         assertThat(getSettingsKey(Settings.Secure.AUTOFILL_SERVICE))
113                 .isEqualTo(CredentialManagerService.AUTOFILL_PLACEHOLDER_VALUE);
114         assertCredentialPropertyEquals(
115                 getSettingsKey(Settings.Secure.CREDENTIAL_SERVICE), testCredentialValue);
116         assertCredentialPropertyEquals(
117                 getSettingsKey(Settings.Secure.CREDENTIAL_SERVICE_PRIMARY),
118                 testCredentialPrimaryValue);
119     }
120 
121     @Test
onProviderRemoved_isAlsoAutofillProvider_success()122     public void onProviderRemoved_isAlsoAutofillProvider_success() {
123         setSettingsKey(
124                 Settings.Secure.AUTOFILL_SERVICE,
125                 "com.example.test/com.example.test.AutofillProvider");
126         setSettingsKey(
127                 Settings.Secure.CREDENTIAL_SERVICE,
128                 "com.example.test/com.example.test.TestActivity:com.example.test2/com.example.test2.TestActivity");
129         setSettingsKey(
130                 Settings.Secure.CREDENTIAL_SERVICE_PRIMARY,
131                 "com.example.test/com.example.test.TestActivity");
132 
133         CredentialManagerService.updateProvidersWhenPackageRemoved(
134                 mSettingsWrapper, "com.example.test");
135 
136         assertThat(getSettingsKey(Settings.Secure.AUTOFILL_SERVICE)).isEqualTo("");
137         assertThat(getSettingsKey(Settings.Secure.CREDENTIAL_SERVICE))
138                 .isEqualTo("com.example.test2/com.example.test2.TestActivity");
139         assertThat(getSettingsKey(Settings.Secure.CREDENTIAL_SERVICE_PRIMARY)).isEqualTo("");
140     }
141 
142     @Test
onProviderRemoved_notPrimaryRemoved_isAlsoAutofillProvider_success()143     public void onProviderRemoved_notPrimaryRemoved_isAlsoAutofillProvider_success() {
144         final String testCredentialPrimaryValue = "com.example.test/com.example.test.TestActivity";
145         final String testCredentialValue =
146                 "com.example.test/com.example.test.TestActivity:com.example.test2/com.example.test2.TestActivity";
147         final String testAutofillValue = "com.example.test/com.example.test.TestAutofillActivity";
148 
149         setSettingsKey(Settings.Secure.AUTOFILL_SERVICE, testAutofillValue);
150         setSettingsKey(Settings.Secure.CREDENTIAL_SERVICE, testCredentialValue);
151         setSettingsKey(Settings.Secure.CREDENTIAL_SERVICE_PRIMARY, testCredentialPrimaryValue);
152 
153         CredentialManagerService.updateProvidersWhenPackageRemoved(
154                 mSettingsWrapper, "com.example.test3");
155 
156         // Since the provider removed was not a primary provider then we should do nothing.
157         assertCredentialPropertyEquals(
158                 getSettingsKey(Settings.Secure.AUTOFILL_SERVICE), testAutofillValue);
159         assertCredentialPropertyEquals(
160                 getSettingsKey(Settings.Secure.CREDENTIAL_SERVICE), testCredentialValue);
161         assertCredentialPropertyEquals(
162                 getSettingsKey(Settings.Secure.CREDENTIAL_SERVICE_PRIMARY),
163                 testCredentialPrimaryValue);
164     }
165 
assertCredentialPropertyEquals(String actualValue, String newValue)166     private void assertCredentialPropertyEquals(String actualValue, String newValue) {
167         Set<ComponentName> actualValueSet = new HashSet<>();
168         for (String rawComponentName : actualValue.split(":")) {
169             ComponentName cn = ComponentName.unflattenFromString(rawComponentName);
170             if (cn != null) {
171                 actualValueSet.add(cn);
172             }
173         }
174 
175         Set<ComponentName> newValueSet = new HashSet<>();
176         for (String rawComponentName : newValue.split(":")) {
177             ComponentName cn = ComponentName.unflattenFromString(rawComponentName);
178             if (cn != null) {
179                 newValueSet.add(cn);
180             }
181         }
182 
183         assertThat(actualValueSet).isEqualTo(newValueSet);
184     }
185 
setSettingsKey(String name, String value)186     private void setSettingsKey(String name, String value) {
187         assertThat(
188                         mSettingsWrapper.putStringForUser(
189                                 name, value, UserHandle.myUserId(), true))
190                 .isTrue();
191     }
192 
getSettingsKey(String name)193     private String getSettingsKey(String name) {
194         return mSettingsWrapper.getStringForUser(name, UserHandle.myUserId());
195     }
196 
197     private static final class MockSettingsWrapper
198             extends CredentialManagerService.SettingsWrapper {
199 
MockSettingsWrapper(@onNull Context context)200         MockSettingsWrapper(@NonNull Context context) {
201             super(context);
202         }
203 
204         /** Updates the string value of a system setting */
205         @Override
putStringForUser( String name, String value, int userHandle, boolean overrideableByRestore)206         public boolean putStringForUser(
207                 String name,
208                 String value,
209                 int userHandle,
210                 boolean overrideableByRestore) {
211             // This will ensure that when the settings putStringForUser method is called by
212             // CredentialManagerService that the overrideableByRestore bit is true.
213             assertThat(overrideableByRestore).isTrue();
214 
215             return Settings.Secure.putStringForUser(getContentResolver(), name, value, userHandle);
216         }
217     }
218 }
219