• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.devicepolicy;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.ArgumentMatchers.anyBoolean;
22 import static org.mockito.ArgumentMatchers.anyLong;
23 import static org.mockito.ArgumentMatchers.anyString;
24 import static org.mockito.Matchers.eq;
25 import static org.mockito.Mockito.doReturn;
26 import static org.mockito.Mockito.when;
27 
28 import android.annotation.RawRes;
29 import android.app.admin.DevicePolicyManager;
30 import android.content.ComponentName;
31 import android.content.Context;
32 import android.content.Intent;
33 import android.content.pm.ActivityInfo;
34 import android.content.pm.ApplicationInfo;
35 import android.content.pm.PackageInfo;
36 import android.content.pm.PackageManager;
37 import android.content.pm.ResolveInfo;
38 import android.os.UserHandle;
39 
40 import androidx.test.InstrumentationRegistry;
41 
42 import org.junit.Before;
43 
44 import java.io.InputStream;
45 import java.util.List;
46 
47 /**
48  * Temporary copy of DpmTestBase using JUnit 4 - once all tests extend it, it should be renamed
49  * back to DpmTestBase (with the temporary methods removed.
50  *
51  */
52 public abstract class DpmTestBase {
53 
54     public static final String TAG = "DpmTest";
55 
56     protected final Context mRealTestContext = InstrumentationRegistry.getTargetContext();
57     protected DpmMockContext mMockContext;
58     private MockSystemServices mServices;
59 
60     // Attributes below are public so they don't need to be prefixed with m
61     public ComponentName admin1;
62     public ComponentName admin2;
63     public ComponentName admin3;
64     public ComponentName adminAnotherPackage;
65     public ComponentName adminNoPerm;
66     public ComponentName delegateCertInstaller;
67 
68     @Before
setFixtures()69     public void setFixtures() throws Exception {
70         mServices = new MockSystemServices(mRealTestContext, "test-data");
71         mMockContext = new DpmMockContext(mServices, mRealTestContext);
72 
73         admin1 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin1.class);
74         admin2 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin2.class);
75         admin3 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin3.class);
76         adminAnotherPackage = new ComponentName(DpmMockContext.ANOTHER_PACKAGE_NAME,
77                 "whatever.random.class");
78         adminNoPerm = new ComponentName(mRealTestContext, DummyDeviceAdmins.AdminNoPerm.class);
79         delegateCertInstaller = new ComponentName(DpmMockContext.DELEGATE_PACKAGE_NAME,
80                 "some.random.class");
81         mockSystemPropertiesToReturnDefault();
82     }
83 
getContext()84     protected DpmMockContext getContext() {
85         return mMockContext;
86     }
87 
getServices()88     public MockSystemServices getServices() {
89         return mServices;
90     }
91 
sendBroadcastWithUser(DevicePolicyManagerServiceTestable dpms, String action, int userHandle)92     protected void sendBroadcastWithUser(DevicePolicyManagerServiceTestable dpms, String action,
93             int userHandle) throws Exception {
94         final Intent intent = new Intent(action);
95         intent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle);
96         getServices().injectBroadcast(getContext(), intent, userHandle);
97         flushTasks(dpms);
98     }
99 
flushTasks(DevicePolicyManagerServiceTestable dpms)100     protected void flushTasks(DevicePolicyManagerServiceTestable dpms) throws Exception {
101         dpms.mHandler.runWithScissors(() -> { }, 0 /*now*/);
102         dpms.mBackgroundHandler.runWithScissors(() -> { }, 0 /*now*/);
103 
104         // We can't let exceptions happen on the background thread. Throw them here if they happen
105         // so they still cause the test to fail despite being suppressed.
106         getServices().rethrowBackgroundBroadcastExceptions();
107     }
108 
109     protected interface DpmRunnable {
run(DevicePolicyManager dpm)110         void run(DevicePolicyManager dpm) throws Exception;
111     }
112 
113     /**
114      * Simulate an RPC from {@param caller} to the service context ({@link #mMockContext}).
115      *
116      * The caller sees its own context. The server also sees its own separate context, with the
117      * appropriate calling UID and calling permissions fields already set up.
118      */
runAsCaller(DpmMockContext caller, DevicePolicyManagerServiceTestable dpms, DpmRunnable action)119     protected void runAsCaller(DpmMockContext caller, DevicePolicyManagerServiceTestable dpms,
120             DpmRunnable action) {
121         final DpmMockContext serviceContext = mMockContext;
122 
123         // Save calling UID and PID before clearing identity so we don't run into aliasing issues.
124         final int callingUid = caller.binder.callingUid;
125         final int callingPid = caller.binder.callingPid;
126 
127         final long origId = serviceContext.binder.clearCallingIdentity();
128         try {
129             serviceContext.binder.callingUid = callingUid;
130             serviceContext.binder.callingPid = callingPid;
131             serviceContext.binder.callingPermissions.put(callingUid, caller.permissions);
132             action.run(new DevicePolicyManagerTestable(caller, dpms));
133         } catch (Exception e) {
134             throw new AssertionError(e);
135         } finally {
136             serviceContext.binder.restoreCallingIdentity(origId);
137         }
138     }
139 
markPackageAsInstalled(String packageName, ApplicationInfo ai, int userId)140     private void markPackageAsInstalled(String packageName, ApplicationInfo ai, int userId)
141             throws Exception {
142         final PackageInfo pi = DpmTestUtils.cloneParcelable(
143                 mRealTestContext.getPackageManager().getPackageInfo(
144                         mRealTestContext.getPackageName(), 0));
145         assertThat(pi.applicationInfo.flags).isNotEqualTo(0);
146 
147         if (ai != null) {
148             pi.applicationInfo = ai;
149         }
150 
151         doReturn(pi).when(mServices.ipackageManager).getPackageInfo(packageName, 0, userId);
152 
153         doReturn(ai.uid).when(mServices.packageManager).getPackageUidAsUser(packageName, userId);
154     }
155 
markDelegatedCertInstallerAsInstalled()156     protected void markDelegatedCertInstallerAsInstalled() throws Exception {
157         final ApplicationInfo ai = new ApplicationInfo();
158         ai.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
159         ai.flags = ApplicationInfo.FLAG_HAS_CODE;
160         // Mark the package as installed on the work profile.
161         ai.uid = UserHandle.getUid(DpmMockContext.CALLER_USER_HANDLE,
162                 DpmMockContext.DELEGATE_CERT_INSTALLER_UID);
163         ai.packageName = delegateCertInstaller.getPackageName();
164         ai.name = delegateCertInstaller.getClassName();
165 
166         markPackageAsInstalled(delegateCertInstaller.getPackageName(), ai,
167                 DpmMockContext.CALLER_USER_HANDLE);
168     }
169 
setUpPackageManagerForAdmin(ComponentName admin, int packageUid)170     protected void setUpPackageManagerForAdmin(ComponentName admin, int packageUid)
171             throws Exception {
172         setUpPackageManagerForAdmin(admin, packageUid,
173                 /* enabledSetting =*/ null, /* appTargetSdk = */ null);
174     }
175 
setUpPackageManagerForAdmin(ComponentName admin, int packageUid, int enabledSetting)176     protected void setUpPackageManagerForAdmin(ComponentName admin, int packageUid,
177             int enabledSetting) throws Exception {
178         setUpPackageManagerForAdmin(admin, packageUid, enabledSetting, /* appTargetSdk = */ null);
179     }
180 
setUpPackageManagerForAdmin(ComponentName admin, int packageUid, Integer enabledSetting, Integer appTargetSdk)181     protected void setUpPackageManagerForAdmin(ComponentName admin, int packageUid,
182             Integer enabledSetting, Integer appTargetSdk) throws Exception {
183         setUpPackageManagerForFakeAdmin(admin, packageUid, enabledSetting, appTargetSdk,
184                 admin);
185     }
186 
setUpPackageManagerForFakeAdmin(ComponentName admin, int packageUid, ComponentName copyFromAdmin)187     protected void setUpPackageManagerForFakeAdmin(ComponentName admin, int packageUid,
188             ComponentName copyFromAdmin)
189             throws Exception {
190         setUpPackageManagerForFakeAdmin(admin, packageUid,
191                 /* enabledSetting =*/ null, /* appTargetSdk = */ null, copyFromAdmin);
192     }
193 
194     /**
195      * Set up a component in the mock package manager to be an active admin.
196      *
197      * @param admin ComponentName that's visible to the test code, which doesn't have to exist.
198      * @param copyFromAdmin package information for {@code admin} will be built based on this
199      *    component's information.
200      */
setUpPackageManagerForFakeAdmin(ComponentName admin, int packageUid, Integer enabledSetting, Integer appTargetSdk, ComponentName copyFromAdmin)201     protected void setUpPackageManagerForFakeAdmin(ComponentName admin, int packageUid,
202             Integer enabledSetting, Integer appTargetSdk, ComponentName copyFromAdmin)
203             throws Exception {
204 
205         // Set up getApplicationInfo().
206 
207         final ApplicationInfo ai = DpmTestUtils.cloneParcelable(
208                 mRealTestContext.getPackageManager().getApplicationInfo(
209                         copyFromAdmin.getPackageName(),
210                         PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS));
211         ai.enabledSetting = enabledSetting == null
212                 ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
213                 : enabledSetting;
214         if (appTargetSdk != null) {
215             ai.targetSdkVersion = appTargetSdk;
216         }
217         ai.uid = packageUid;
218         ai.packageName = admin.getPackageName();
219         ai.name = admin.getClassName();
220 
221         doReturn(ai).when(mServices.ipackageManager).getApplicationInfo(
222                 eq(admin.getPackageName()),
223                 anyLong(),
224                 eq(UserHandle.getUserId(packageUid)));
225 
226         // Set up queryBroadcastReceivers().
227 
228         final Intent resolveIntent = new Intent();
229         resolveIntent.setComponent(copyFromAdmin);
230         final List<ResolveInfo> realResolveInfo =
231                 mRealTestContext.getPackageManager().queryBroadcastReceivers(
232                         resolveIntent,
233                         PackageManager.GET_META_DATA);
234         assertThat(realResolveInfo).isNotNull();
235         assertThat(realResolveInfo).hasSize(1);
236 
237         // We need to change AI, so set a clone.
238         realResolveInfo.set(0, DpmTestUtils.cloneParcelable(realResolveInfo.get(0)));
239 
240         // We need to rewrite the UID in the activity info.
241         final ActivityInfo aci = realResolveInfo.get(0).activityInfo;
242         aci.applicationInfo = ai;
243         aci.packageName = admin.getPackageName();
244         aci.name = admin.getClassName();
245 
246         // Note we don't set up queryBroadcastReceivers.  We don't use it in DPMS.
247 
248         doReturn(aci).when(mServices.ipackageManager).getReceiverInfo(
249                 eq(admin),
250                 anyLong(),
251                 eq(UserHandle.getUserId(packageUid)));
252 
253         doReturn(new String[] {admin.getPackageName()}).when(mServices.ipackageManager)
254             .getPackagesForUid(eq(packageUid));
255         doReturn(new String[] {admin.getPackageName()}).when(mServices.packageManager)
256                 .getPackagesForUid(eq(packageUid));
257         // Set up getPackageInfo().
258         markPackageAsInstalled(admin.getPackageName(), ai, UserHandle.getUserId(packageUid));
259     }
260 
261     /**
262      * By default, system properties are mocked to return default value. Override the mock if you
263      * want a specific value.
264      */
mockSystemPropertiesToReturnDefault()265     private void mockSystemPropertiesToReturnDefault() {
266         when(getServices().systemProperties.get(
267                 anyString(), anyString())).thenAnswer(
268                 invocation -> invocation.getArguments()[1]
269         );
270 
271         when(getServices().systemProperties.getBoolean(
272                 anyString(), anyBoolean())).thenAnswer(
273                 invocation -> invocation.getArguments()[1]
274         );
275 
276         when(getServices().systemProperties.getLong(
277                 anyString(), anyLong())).thenAnswer(
278                 invocation -> invocation.getArguments()[1]
279         );
280     }
281 
getRawStream(@awRes int id)282     protected InputStream getRawStream(@RawRes int id) {
283         return mRealTestContext.getResources().openRawResource(id);
284     }
285 }
286