1 /*
2  * Copyright (C) 2022 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.appenumeration.cts;
18 
19 import static android.appenumeration.cts.Constants.ACCOUNT_NAME;
20 import static android.appenumeration.cts.Constants.ACCOUNT_TYPE;
21 import static android.appenumeration.cts.Constants.ACTION_ACCOUNT_MANAGER_GET_AUTHENTICATOR_TYPES;
22 import static android.appenumeration.cts.Constants.QUERIES_NOTHING;
23 import static android.appenumeration.cts.Constants.QUERIES_PACKAGE;
24 import static android.appenumeration.cts.Constants.TARGET_STUB;
25 import static android.appenumeration.cts.Constants.TARGET_STUB_APK;
26 import static android.appenumeration.cts.Constants.TARGET_SYNCADAPTER;
27 import static android.appenumeration.cts.Constants.TARGET_WEB;
28 import static android.appenumeration.cts.Utils.ensurePackageIsInstalled;
29 import static android.content.Intent.EXTRA_RETURN_RESULT;
30 
31 import static org.hamcrest.MatcherAssert.assertThat;
32 import static org.hamcrest.collection.IsMapContaining.hasEntry;
33 import static org.hamcrest.collection.IsMapWithSize.anEmptyMap;
34 import static org.hamcrest.core.Is.is;
35 import static org.junit.Assert.assertThrows;
36 
37 import android.accounts.Account;
38 import android.accounts.AccountManager;
39 import android.accounts.AuthenticatorDescription;
40 import android.content.pm.PackageManager;
41 import android.os.Bundle;
42 
43 import androidx.test.ext.junit.runners.AndroidJUnit4;
44 
45 import org.junit.After;
46 import org.junit.Before;
47 import org.junit.BeforeClass;
48 import org.junit.Test;
49 import org.junit.runner.RunWith;
50 
51 import java.util.Arrays;
52 import java.util.HashMap;
53 import java.util.Map;
54 
55 @RunWith(AndroidJUnit4.class)
56 public class AccountManagerEnumerationTest extends AppEnumerationTestsBase {
57     private static final Account ACCOUNT = new Account(ACCOUNT_NAME, ACCOUNT_TYPE);
58 
59     private static final String TARGET_VISIBLE = TARGET_STUB;
60     private static final String TARGET_NOT_VISIBLE = TARGET_WEB;
61 
62     private AccountManager mAccountManager;
63 
64     @BeforeClass
prepareApps()65     public static void prepareApps() {
66         ensurePackageIsInstalled(TARGET_STUB, TARGET_STUB_APK);
67     }
68 
69     @Before
onBefore()70     public void onBefore() throws Exception {
71         mAccountManager = AccountManager.get(sContext);
72 
73         assertThat(sPm.canPackageQuery(sContext.getPackageName(), TARGET_VISIBLE),
74                 is(true));
75         assertThrows(PackageManager.NameNotFoundException.class,
76                 () -> sPm.canPackageQuery(sContext.getPackageName(), TARGET_NOT_VISIBLE));
77     }
78 
79     @After
onAfter()80     public void onAfter() {
81         for (Account account : mAccountManager.getAccountsByType(ACCOUNT_TYPE)) {
82             mAccountManager.removeAccountExplicitly(account);
83         }
84     }
85 
86     @Test
addAccountExplicitlyWithVisibility_targetPackageIsVisible()87     public void addAccountExplicitlyWithVisibility_targetPackageIsVisible() {
88         final Map<String, Integer> visibility = new HashMap();
89         visibility.put(TARGET_VISIBLE, AccountManager.VISIBILITY_VISIBLE);
90         assertThat(mAccountManager.addAccountExplicitly(
91                 ACCOUNT, null /* password */, null /* userdata */, visibility), is(true));
92 
93         assertThat(mAccountManager.getAccountVisibility(ACCOUNT, TARGET_VISIBLE),
94                 is(AccountManager.VISIBILITY_VISIBLE));
95         assertThat(mAccountManager.getAccountsAndVisibilityForPackage(TARGET_VISIBLE, ACCOUNT_TYPE),
96                 hasEntry(ACCOUNT, AccountManager.VISIBILITY_VISIBLE));
97     }
98 
99     @Test
addAccountExplicitlyWithVisibility_targetPackageNotVisible()100     public void addAccountExplicitlyWithVisibility_targetPackageNotVisible() {
101         final Map<String, Integer> visibility = new HashMap();
102         visibility.put(TARGET_NOT_VISIBLE, AccountManager.VISIBILITY_VISIBLE);
103         assertThat(mAccountManager.addAccountExplicitly(
104                 ACCOUNT, null /* password */, null /* userdata */, visibility), is(true));
105 
106         assertThat(mAccountManager.getAccountVisibility(ACCOUNT, TARGET_NOT_VISIBLE),
107                 is(AccountManager.VISIBILITY_NOT_VISIBLE));
108         assertThat(mAccountManager.getAccountsAndVisibilityForPackage(
109                 TARGET_NOT_VISIBLE, ACCOUNT_TYPE), anEmptyMap());
110     }
111 
112     @Test
setAccountVisibility_targetPackageIsVisible()113     public void setAccountVisibility_targetPackageIsVisible() {
114         assertThat(mAccountManager.addAccountExplicitly(
115                 ACCOUNT, null /* password */, null /* userdata */), is(true));
116         assertThat(mAccountManager.setAccountVisibility(
117                 ACCOUNT, TARGET_VISIBLE, AccountManager.VISIBILITY_VISIBLE), is(true));
118     }
119 
120     @Test
setAccountVisibility_targetPackageNotVisible()121     public void setAccountVisibility_targetPackageNotVisible() {
122         assertThat(mAccountManager.addAccountExplicitly(
123                 ACCOUNT, null /* password */, null /* userdata */), is(true));
124         assertThat(mAccountManager.setAccountVisibility(
125                 ACCOUNT, TARGET_NOT_VISIBLE, AccountManager.VISIBILITY_VISIBLE), is(false));
126     }
127 
128     @Test
queriesPackage_getAuthenticatorTypes_canSeeSyncAdapterTarget()129     public void queriesPackage_getAuthenticatorTypes_canSeeSyncAdapterTarget()
130             throws Exception {
131         assertVisible(QUERIES_PACKAGE, TARGET_SYNCADAPTER, this::getAuthenticatorTypes);
132     }
133 
134     @Test
queriesNothing_getAuthenticatorTypes_cannotSeeSyncAdapterTarget()135     public void queriesNothing_getAuthenticatorTypes_cannotSeeSyncAdapterTarget()
136             throws Exception {
137         assertNotVisible(QUERIES_NOTHING, TARGET_SYNCADAPTER, this::getAuthenticatorTypes);
138     }
139 
getAuthenticatorTypes(String sourcePackageName)140     private String[] getAuthenticatorTypes(String sourcePackageName) throws Exception {
141         final Bundle response = sendCommandBlocking(sourcePackageName, null /* targetPackageName */,
142                 /* intentExtra */ null, ACTION_ACCOUNT_MANAGER_GET_AUTHENTICATOR_TYPES);
143         final AuthenticatorDescription[] types =
144                 response.getParcelableArray(EXTRA_RETURN_RESULT, AuthenticatorDescription.class);
145         return Arrays.stream(types)
146                 .map(type -> type.packageName)
147                 .distinct()
148                 .toArray(String[]::new);
149     }
150 }
151