1 /*
2  * Copyright (C) 2020 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 com.android.server.uri;
18 
19 import static org.mockito.ArgumentMatchers.anyLong;
20 import static org.mockito.ArgumentMatchers.eq;
21 import static org.mockito.Mockito.mock;
22 import static org.mockito.Mockito.when;
23 
24 import android.annotation.NonNull;
25 import android.app.ActivityManagerInternal;
26 import android.content.ContentResolver;
27 import android.content.Context;
28 import android.content.ContextWrapper;
29 import android.content.Intent;
30 import android.content.pm.ApplicationInfo;
31 import android.content.pm.PackageManager;
32 import android.content.pm.PackageManagerInternal;
33 import android.content.pm.PathPermission;
34 import android.content.pm.ProviderInfo;
35 import android.net.Uri;
36 import android.os.FileUtils;
37 import android.os.PatternMatcher;
38 import android.os.Process;
39 import android.os.UserHandle;
40 import android.test.mock.MockContentResolver;
41 import android.test.mock.MockPackageManager;
42 
43 import com.android.server.LocalServices;
44 
45 import java.io.File;
46 
47 public class UriGrantsMockContext extends ContextWrapper {
48     static final String TAG = "UriGrants";
49 
50     static final int FLAG_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
51     static final int FLAG_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
52     static final int FLAG_PERSISTABLE = Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
53     static final int FLAG_PREFIX = Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
54 
55     static final int USER_PRIMARY = 10;
56     static final int USER_SECONDARY = 11;
57 
58     /** Typical social network app */
59     static final String PKG_SOCIAL = "com.example.social";
60     /** Typical camera app that allows grants */
61     static final String PKG_CAMERA = "com.example.camera";
62     /** Completely private app/provider that offers no grants */
63     static final String PKG_PRIVATE = "com.example.private";
64     /** Completely public app/provider that needs no grants */
65     static final String PKG_PUBLIC = "com.example.public";
66     /** Completely public app/provider that forces grants */
67     static final String PKG_FORCE = "com.example.force";
68     /** Complex provider that offers nested grants */
69     static final String PKG_COMPLEX = "com.example.complex";
70 
71     private static final int UID_SOCIAL = android.os.Process.LAST_APPLICATION_UID - 1;
72     private static final int UID_CAMERA = android.os.Process.LAST_APPLICATION_UID - 2;
73     private static final int UID_PRIVATE = android.os.Process.LAST_APPLICATION_UID - 3;
74     private static final int UID_PUBLIC = android.os.Process.LAST_APPLICATION_UID - 4;
75     private static final int UID_FORCE = android.os.Process.LAST_APPLICATION_UID - 5;
76     private static final int UID_COMPLEX = android.os.Process.LAST_APPLICATION_UID - 6;
77 
78     static final int UID_PRIMARY_SOCIAL = UserHandle.getUid(USER_PRIMARY, UID_SOCIAL);
79     static final int UID_PRIMARY_CAMERA = UserHandle.getUid(USER_PRIMARY, UID_CAMERA);
80     static final int UID_PRIMARY_PRIVATE = UserHandle.getUid(USER_PRIMARY, UID_PRIVATE);
81     static final int UID_PRIMARY_PUBLIC = UserHandle.getUid(USER_PRIMARY, UID_PUBLIC);
82     static final int UID_PRIMARY_FORCE = UserHandle.getUid(USER_PRIMARY, UID_FORCE);
83     static final int UID_PRIMARY_COMPLEX = UserHandle.getUid(USER_PRIMARY, UID_COMPLEX);
84 
85     static final int UID_SECONDARY_SOCIAL = UserHandle.getUid(USER_SECONDARY, UID_SOCIAL);
86     static final int UID_SECONDARY_CAMERA = UserHandle.getUid(USER_SECONDARY, UID_CAMERA);
87     static final int UID_SECONDARY_PRIVATE = UserHandle.getUid(USER_SECONDARY, UID_PRIVATE);
88     static final int UID_SECONDARY_PUBLIC = UserHandle.getUid(USER_SECONDARY, UID_PUBLIC);
89     static final int UID_SECONDARY_FORCE = UserHandle.getUid(USER_SECONDARY, UID_FORCE);
90     static final int UID_SECONDARY_COMPLEX = UserHandle.getUid(USER_SECONDARY, UID_COMPLEX);
91 
92     static final Uri URI_PHOTO_1 = Uri.parse("content://" + PKG_CAMERA + "/1");
93     static final Uri URI_PHOTO_2 = Uri.parse("content://" + PKG_CAMERA + "/2");
94     static final Uri URI_PRIVATE = Uri.parse("content://" + PKG_PRIVATE + "/42");
95     static final Uri URI_PUBLIC = Uri.parse("content://" + PKG_PUBLIC + "/42");
96     static final Uri URI_FORCE = Uri.parse("content://" + PKG_FORCE + "/42");
97 
98     private final File mDir;
99 
100     private final MockPackageManager mPackage;
101     private final MockContentResolver mResolver;
102 
103     final ActivityManagerInternal mAmInternal;
104     final PackageManagerInternal mPmInternal;
105 
UriGrantsMockContext(@onNull Context base)106     public UriGrantsMockContext(@NonNull Context base) {
107         super(base);
108         mDir = new File(base.getFilesDir(), TAG);
109         mDir.mkdirs();
110         FileUtils.deleteContents(mDir);
111 
112         mPackage = new MockPackageManager();
113         mResolver = new MockContentResolver(this);
114 
115         mAmInternal = mock(ActivityManagerInternal.class);
116         LocalServices.removeServiceForTest(ActivityManagerInternal.class);
117         LocalServices.addService(ActivityManagerInternal.class, mAmInternal);
118 
119         mPmInternal = mock(PackageManagerInternal.class);
120         LocalServices.removeServiceForTest(PackageManagerInternal.class);
121         LocalServices.addService(PackageManagerInternal.class, mPmInternal);
122 
123         for (int userId : new int[] { USER_PRIMARY, USER_SECONDARY }) {
124             when(mPmInternal.getPackageUid(eq(PKG_SOCIAL), anyLong(), eq(userId)))
125                     .thenReturn(UserHandle.getUid(userId, UID_SOCIAL));
126             when(mPmInternal.getPackageUid(eq(PKG_CAMERA), anyLong(), eq(userId)))
127                     .thenReturn(UserHandle.getUid(userId, UID_CAMERA));
128             when(mPmInternal.getPackageUid(eq(PKG_PRIVATE), anyLong(), eq(userId)))
129                     .thenReturn(UserHandle.getUid(userId, UID_PRIVATE));
130             when(mPmInternal.getPackageUid(eq(PKG_PUBLIC), anyLong(), eq(userId)))
131                     .thenReturn(UserHandle.getUid(userId, UID_PUBLIC));
132             when(mPmInternal.getPackageUid(eq(PKG_FORCE), anyLong(), eq(userId)))
133                     .thenReturn(UserHandle.getUid(userId, UID_FORCE));
134             when(mPmInternal.getPackageUid(eq(PKG_COMPLEX), anyLong(), eq(userId)))
135                     .thenReturn(UserHandle.getUid(userId, UID_COMPLEX));
136 
137             when(mPmInternal.resolveContentProvider(eq(PKG_CAMERA), anyLong(), eq(userId),
138                     eq(Process.SYSTEM_UID)))
139                     .thenReturn(buildCameraProvider(userId));
140             when(mPmInternal.resolveContentProvider(eq(PKG_CAMERA), anyLong(), eq(userId),
141                     eq(UserHandle.getUid(userId, UID_CAMERA))))
142                     .thenReturn(buildCameraProvider(userId));
143             when(mPmInternal.resolveContentProvider(eq(PKG_PRIVATE), anyLong(), eq(userId),
144                     eq(Process.SYSTEM_UID)))
145                     .thenReturn(buildPrivateProvider(userId));
146             when(mPmInternal.resolveContentProvider(eq(PKG_PRIVATE), anyLong(), eq(userId),
147                     eq(UserHandle.getUid(userId, UID_PRIVATE))))
148                     .thenReturn(buildPrivateProvider(userId));
149             when(mPmInternal.resolveContentProvider(eq(PKG_PUBLIC), anyLong(), eq(userId),
150                     eq(Process.SYSTEM_UID)))
151                     .thenReturn(buildPublicProvider(userId));
152             when(mPmInternal.resolveContentProvider(eq(PKG_PUBLIC), anyLong(), eq(userId),
153                     eq(UserHandle.getUid(userId, UID_PUBLIC))))
154                     .thenReturn(buildPublicProvider(userId));
155             when(mPmInternal.resolveContentProvider(eq(PKG_FORCE), anyLong(), eq(userId),
156                     eq(Process.SYSTEM_UID)))
157                     .thenReturn(buildForceProvider(userId));
158             when(mPmInternal.resolveContentProvider(eq(PKG_FORCE), anyLong(), eq(userId),
159                     eq(UserHandle.getUid(userId, UID_FORCE))))
160                     .thenReturn(buildForceProvider(userId));
161             when(mPmInternal.resolveContentProvider(eq(PKG_COMPLEX), anyLong(), eq(userId),
162                     eq(Process.SYSTEM_UID)))
163                     .thenReturn(buildComplexProvider(userId));
164             when(mPmInternal.resolveContentProvider(eq(PKG_COMPLEX), anyLong(), eq(userId),
165                     eq(UserHandle.getUid(userId, UID_COMPLEX))))
166                     .thenReturn(buildComplexProvider(userId));
167         }
168     }
169 
buildCameraProvider(int userId)170     private static ProviderInfo buildCameraProvider(int userId) {
171         final ProviderInfo pi = new ProviderInfo();
172         pi.packageName = PKG_CAMERA;
173         pi.authority = PKG_CAMERA;
174         pi.readPermission = android.Manifest.permission.READ_EXTERNAL_STORAGE;
175         pi.writePermission = android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
176         pi.grantUriPermissions = true;
177         pi.applicationInfo = new ApplicationInfo();
178         pi.applicationInfo.uid = UserHandle.getUid(userId, UID_CAMERA);
179         return pi;
180     }
181 
buildPrivateProvider(int userId)182     private static ProviderInfo buildPrivateProvider(int userId) {
183         final ProviderInfo pi = new ProviderInfo();
184         pi.packageName = PKG_PRIVATE;
185         pi.authority = PKG_PRIVATE;
186         pi.exported = false;
187         pi.grantUriPermissions = false;
188         pi.applicationInfo = new ApplicationInfo();
189         pi.applicationInfo.uid = UserHandle.getUid(userId, UID_PRIVATE);
190         return pi;
191     }
192 
buildPublicProvider(int userId)193     private static ProviderInfo buildPublicProvider(int userId) {
194         final ProviderInfo pi = new ProviderInfo();
195         pi.packageName = PKG_PUBLIC;
196         pi.authority = PKG_PUBLIC;
197         pi.exported = true;
198         pi.grantUriPermissions = false;
199         pi.applicationInfo = new ApplicationInfo();
200         pi.applicationInfo.uid = UserHandle.getUid(userId, UID_PUBLIC);
201         return pi;
202     }
203 
buildForceProvider(int userId)204     private static ProviderInfo buildForceProvider(int userId) {
205         final ProviderInfo pi = new ProviderInfo();
206         pi.packageName = PKG_FORCE;
207         pi.authority = PKG_FORCE;
208         pi.exported = true;
209         pi.grantUriPermissions = true;
210         pi.forceUriPermissions = true;
211         pi.applicationInfo = new ApplicationInfo();
212         pi.applicationInfo.uid = UserHandle.getUid(userId, UID_FORCE);
213         return pi;
214     }
215 
buildComplexProvider(int userId)216     private static ProviderInfo buildComplexProvider(int userId) {
217         final ProviderInfo pi = new ProviderInfo();
218         pi.packageName = PKG_COMPLEX;
219         pi.authority = PKG_COMPLEX;
220         pi.exported = true;
221         pi.grantUriPermissions = true;
222         pi.applicationInfo = new ApplicationInfo();
223         pi.applicationInfo.uid = UserHandle.getUid(userId, UID_COMPLEX);
224         pi.pathPermissions = new PathPermission[] {
225                 new PathPermission("/secure", PathPermission.PATTERN_PREFIX,
226                         android.Manifest.permission.READ_EXTERNAL_STORAGE,
227                         android.Manifest.permission.WRITE_EXTERNAL_STORAGE),
228         };
229         pi.uriPermissionPatterns = new PatternMatcher[] {
230                 new PatternMatcher("/secure", PathPermission.PATTERN_PREFIX),
231                 new PatternMatcher("/insecure", PathPermission.PATTERN_PREFIX),
232         };
233         return pi;
234     }
235 
236     @Override
getPackageManager()237     public PackageManager getPackageManager() {
238         return mPackage;
239     }
240 
241     @Override
getContentResolver()242     public ContentResolver getContentResolver() {
243         return mResolver;
244     }
245 
246     @Override
getFilesDir()247     public File getFilesDir() {
248         return mDir;
249     }
250 }
251