• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.cts.applicationvisibility;
17 
18 import static android.content.pm.PackageManager.MATCH_KNOWN_PACKAGES;
19 
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertTrue;
22 import static org.junit.Assert.fail;
23 
24 import android.app.UiAutomation;
25 import android.content.Context;
26 import android.content.pm.ApplicationInfo;
27 import android.content.pm.PackageInfo;
28 import android.content.pm.PackageManager;
29 import android.os.Bundle;
30 import android.os.Process;
31 import android.os.UserHandle;
32 
33 import androidx.test.InstrumentationRegistry;
34 
35 import org.junit.Before;
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 import org.junit.runners.JUnit4;
39 
40 import java.util.List;
41 import java.util.stream.Stream;
42 
43 @RunWith(JUnit4.class)
44 public class ApplicationVisibilityCrossUserTest {
45     private String TINY_PKG = "android.appsecurity.cts.tinyapp";
46     private Context mContext;
47 
48     @Before
setUp()49     public void setUp() throws Exception {
50         mContext = InstrumentationRegistry.getContext();
51     }
52 
53     /** Tests getting installed packages for the current user */
54     @Test
testPackageVisibility_currentUser()55     public void testPackageVisibility_currentUser() throws Exception {
56         final PackageManager pm = mContext.getPackageManager();
57         final List<PackageInfo> packageList =
58                 pm.getInstalledPackagesAsUser(0, mContext.getUserId());
59         assertFalse(isAppInPackageList(TINY_PKG, packageList));
60     }
61 
62     /** Tests getting installed packages for all users, with cross user permission granted */
63     @Test
testPackageVisibility_anyUserCrossUserGrant()64     public void testPackageVisibility_anyUserCrossUserGrant() throws Exception {
65         final PackageManager pm = mContext.getPackageManager();
66         final List<PackageInfo> packageList =
67                 pm.getInstalledPackagesAsUser(MATCH_KNOWN_PACKAGES, mContext.getUserId());
68         assertTrue(isAppInPackageList(TINY_PKG, packageList));
69     }
70 
71     /** Tests getting installed packages for all users, with cross user permission revoked */
72     @Test
testPackageVisibility_anyUserCrossUserNoGrant()73     public void testPackageVisibility_anyUserCrossUserNoGrant() throws Exception {
74         final PackageManager pm = mContext.getPackageManager();
75         try {
76             ungrantAcrossUsersPermission();
77             final List<PackageInfo> packageList =
78                     pm.getInstalledPackagesAsUser(MATCH_KNOWN_PACKAGES, mContext.getUserId());
79             fail("Should have received a security exception");
80         } catch (SecurityException ignore) {}
81     }
82 
83     /** Tests getting installed packages for another user, with cross user permission granted */
84     @Test
testPackageVisibility_otherUserGrant()85     public void testPackageVisibility_otherUserGrant() throws Exception {
86         final PackageManager pm = mContext.getPackageManager();
87         final List<PackageInfo> packageList =
88                 pm.getInstalledPackagesAsUser(0, getTestUser());
89         assertTrue(isAppInPackageList(TINY_PKG, packageList));
90     }
91 
92     /** Tests getting installed packages for another user, with cross user permission revoked */
93     @Test
testPackageVisibility_otherUserNoGrant()94     public void testPackageVisibility_otherUserNoGrant() throws Exception {
95         final PackageManager pm = mContext.getPackageManager();
96         try {
97             ungrantAcrossUsersPermission();
98             final List<PackageInfo> packageList =
99                     pm.getInstalledPackagesAsUser(0, getTestUser());
100             fail("Should have received a security exception");
101         } catch (SecurityException ignore) {}
102     }
103 
104     /** Tests getting installed applications for the current user */
105     @Test
testApplicationVisibility_currentUser()106     public void testApplicationVisibility_currentUser() throws Exception {
107         final PackageManager pm = mContext.getPackageManager();
108         final List<ApplicationInfo> applicationList =
109                 pm.getInstalledApplicationsAsUser(0, mContext.getUserId());
110         assertFalse(isAppInApplicationList(TINY_PKG, applicationList));
111     }
112 
113     /** Tests getting installed applications for all users, with cross user permission granted */
114     @Test
testApplicationVisibility_anyUserCrossUserGrant()115     public void testApplicationVisibility_anyUserCrossUserGrant() throws Exception {
116         final PackageManager pm = mContext.getPackageManager();
117         final List<ApplicationInfo> applicationList =
118                 pm.getInstalledApplicationsAsUser(MATCH_KNOWN_PACKAGES, mContext.getUserId());
119         assertTrue(isAppInApplicationList(TINY_PKG, applicationList));
120     }
121 
122     /** Tests getting installed applications for all users, with cross user permission revoked */
123     @Test
testApplicationVisibility_anyUserCrossUserNoGrant()124     public void testApplicationVisibility_anyUserCrossUserNoGrant() throws Exception {
125         final PackageManager pm = mContext.getPackageManager();
126         try {
127             ungrantAcrossUsersPermission();
128             final List<ApplicationInfo> applicationList =
129                     pm.getInstalledApplicationsAsUser(MATCH_KNOWN_PACKAGES, mContext.getUserId());
130             fail("Should have received a security exception");
131         } catch (SecurityException ignore) {}
132     }
133 
134     /** Tests getting installed applications for another user, with cross user permission granted */
135     @Test
testApplicationVisibility_otherUserGrant()136     public void testApplicationVisibility_otherUserGrant() throws Exception {
137         final PackageManager pm = mContext.getPackageManager();
138         final List<ApplicationInfo> applicationList =
139                 pm.getInstalledApplicationsAsUser(0, getTestUser());
140         assertTrue(isAppInApplicationList(TINY_PKG, applicationList));
141     }
142 
143     /** Tests getting installed applications for another user, with cross user permission revoked */
144     @Test
testApplicationVisibility_otherUserNoGrant()145     public void testApplicationVisibility_otherUserNoGrant() throws Exception {
146         final PackageManager pm = mContext.getPackageManager();
147         try {
148             ungrantAcrossUsersPermission();
149             final List<ApplicationInfo> applicationList =
150                     pm.getInstalledApplicationsAsUser(0, getTestUser());
151             fail("Should have received a security exception");
152         } catch (SecurityException ignore) {}
153     }
154 
155     /** Tests getting installed packages for the current user */
156     @Test
testGetPackagesForUidVisibility_currentUser()157     public void testGetPackagesForUidVisibility_currentUser() throws Exception {
158         final PackageManager pm = mContext.getPackageManager();
159         final int userId = mContext.getUserId();
160         final int firstAppUid = UserHandle.getUid(userId, Process.FIRST_APPLICATION_UID);
161         final int lastAppUid = UserHandle.getUid(userId, Process.LAST_APPLICATION_UID);
162         boolean found = false;
163         for (int appUid = firstAppUid; appUid < lastAppUid; appUid++) {
164             found = isAppInPackageNamesArray(TINY_PKG, pm.getPackagesForUid(appUid));
165             if (found) break;
166         }
167         assertFalse(found);
168     }
169 
170     /** Tests getting installed packages for primary user, with cross user permission granted */
171     @Test
testGetPackagesForUidVisibility_anotherUserCrossUserGrant()172     public void testGetPackagesForUidVisibility_anotherUserCrossUserGrant() throws Exception {
173         final PackageManager pm = mContext.getPackageManager();
174         boolean found = false;
175         for (int appUid = Process.FIRST_APPLICATION_UID; appUid < Process.LAST_APPLICATION_UID;
176                 appUid++) {
177             found = isAppInPackageNamesArray(TINY_PKG, pm.getPackagesForUid(appUid));
178             if (found) break;
179         }
180         assertTrue(found);
181     }
182 
183     /** Tests getting installed packages for primary user, with cross user permission revoked */
184     @Test
testGetPackagesForUidVisibility_anotherUserCrossUserNoGrant()185     public void testGetPackagesForUidVisibility_anotherUserCrossUserNoGrant() throws Exception {
186         final PackageManager pm = mContext.getPackageManager();
187         ungrantAcrossUsersPermission();
188         try {
189             for (int appUid = Process.FIRST_APPLICATION_UID; appUid < Process.LAST_APPLICATION_UID;
190                     appUid++) {
191                 isAppInPackageNamesArray(TINY_PKG, pm.getPackagesForUid(appUid));
192             }
193             fail("Should have received a security exception");
194         } catch (SecurityException e) {}
195     }
196 
197     /**
198      * Tests getting the uid of the installed packages for the current user.
199      **/
200     @Test
testGetPackageUidVisibility_currentUser()201     public void testGetPackageUidVisibility_currentUser() {
202         final PackageManager pm = mContext.getPackageManager();
203         try {
204             pm.getPackageUid(TINY_PKG, 0 /*flags*/);
205             fail("Should have received a NameNotFoundException");
206         } catch (PackageManager.NameNotFoundException e) {
207             // Expected
208         }
209     }
210 
211     /**
212      * Tests getting the uid of the installed packages for primary user,
213      * with cross user permission granted.
214      **/
215     @Test
testGetPackageUidVisibility_anotherUserCrossUserGrant()216     public void testGetPackageUidVisibility_anotherUserCrossUserGrant() {
217         final PackageManager pm = mContext.createContextAsUser(UserHandle.of(getTestUser()),
218                 0 /*flags*/).getPackageManager();
219         try {
220             pm.getPackageUid(TINY_PKG, MATCH_KNOWN_PACKAGES);
221         } catch (PackageManager.NameNotFoundException e) {
222             fail("Should not receive a NameNotFoundException");
223         }
224     }
225 
226     /**
227      * Tests getting the uid of the installed packages for primary user,
228      * with cross user permission revoked.
229      **/
230     @Test
testGetPackageUidVisibility_anotherUserCrossUserNoGrant()231     public void testGetPackageUidVisibility_anotherUserCrossUserNoGrant()
232             throws PackageManager.NameNotFoundException {
233         final PackageManager pm = mContext.createContextAsUser(UserHandle.of(getTestUser()),
234                 0 /*flags*/).getPackageManager();
235         ungrantAcrossUsersPermission();
236         try {
237             pm.getPackageUid(TINY_PKG, MATCH_KNOWN_PACKAGES);
238             fail("Should have received a SecurityException");
239         } catch (SecurityException e) {
240             // Expected
241         }
242     }
243 
244     /**
245      * Tests getting the gids of the installed packages for the current user.
246      **/
247     @Test
testGetPackageGidsVisibility_currentUser()248     public void testGetPackageGidsVisibility_currentUser() {
249         final PackageManager pm = mContext.getPackageManager();
250         try {
251             pm.getPackageGids(TINY_PKG, 0 /*flags*/);
252             fail("Should have received a NameNotFoundException");
253         } catch (PackageManager.NameNotFoundException e) {
254             // Expected
255         }
256     }
257 
258     /**
259      * Tests getting the gids of the installed packages for primary user,
260      * with cross user permission granted.
261      **/
262     @Test
testGetPackageGidsVisibility_anotherUserCrossUserGrant()263     public void testGetPackageGidsVisibility_anotherUserCrossUserGrant() {
264         final PackageManager pm = mContext.createContextAsUser(UserHandle.of(getTestUser()),
265                 0 /*flags*/).getPackageManager();
266         try {
267             pm.getPackageUid(TINY_PKG, MATCH_KNOWN_PACKAGES);
268         } catch (PackageManager.NameNotFoundException e) {
269             fail("Should not receive a NameNotFoundException");
270         }
271     }
272 
273     /**
274      * Tests getting the gids of the installed packages for primary user,
275      * with cross user permission revoked.
276      **/
277     @Test
testGetPackageGidsVisibility_anotherUserCrossUserNoGrant()278     public void testGetPackageGidsVisibility_anotherUserCrossUserNoGrant()
279             throws PackageManager.NameNotFoundException {
280         final PackageManager pm = mContext.createContextAsUser(UserHandle.of(getTestUser()),
281                 0 /*flags*/).getPackageManager();
282         ungrantAcrossUsersPermission();
283         try {
284             pm.getPackageUid(TINY_PKG, MATCH_KNOWN_PACKAGES);
285             fail("Should have received a SecurityException");
286         } catch (SecurityException e) {
287             // Expected
288         }
289     }
290 
isAppInPackageList(String packageName, List<PackageInfo> packageList)291     private boolean isAppInPackageList(String packageName,
292             List<PackageInfo> packageList) {
293         for (PackageInfo pkgInfo : packageList) {
294             if (pkgInfo.packageName.equals(packageName)) {
295                 return true;
296             }
297         }
298         return false;
299     }
300 
isAppInApplicationList( String packageName, List<ApplicationInfo> applicationList)301     private boolean isAppInApplicationList(
302             String packageName, List<ApplicationInfo> applicationList) {
303         for (ApplicationInfo appInfo : applicationList) {
304             if (appInfo.packageName.equals(packageName)) {
305                 return true;
306             }
307         }
308         return false;
309     }
310 
isAppInPackageNamesArray(String packageName, String[] packageNames)311     private boolean isAppInPackageNamesArray(String packageName, String[] packageNames) {
312         return packageNames != null && Stream.of(packageNames).anyMatch(
313                 name -> name.equals(packageName));
314     }
315 
getTestUser()316     private int getTestUser() {
317         final Bundle testArguments = InstrumentationRegistry.getArguments();
318         if (testArguments.containsKey("testUser")) {
319             try {
320                 return Integer.parseInt(testArguments.getString("testUser"));
321             } catch (NumberFormatException ignore) {}
322         }
323         return mContext.getUserId();
324     }
325 
ungrantAcrossUsersPermission()326     private static void ungrantAcrossUsersPermission() {
327         final Context context = InstrumentationRegistry.getContext();
328         final PackageManager pm = context.getPackageManager();
329         final UiAutomation uiAutomation =
330                 InstrumentationRegistry.getInstrumentation().getUiAutomation();
331         try {
332             uiAutomation.adoptShellPermissionIdentity();
333             pm.revokeRuntimePermission(context.getPackageName(),
334                     "android.permission.INTERACT_ACROSS_USERS", Process.myUserHandle());
335         } finally {
336             uiAutomation.dropShellPermissionIdentity();
337         }
338     }
339 }
340