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 org.mockito.ArgumentMatchers.anyBoolean; 20 import static org.mockito.ArgumentMatchers.anyLong; 21 import static org.mockito.ArgumentMatchers.anyString; 22 import static org.mockito.Matchers.anyInt; 23 import static org.mockito.Matchers.eq; 24 import static org.mockito.Mockito.doReturn; 25 import static org.mockito.Mockito.when; 26 27 import android.app.admin.DevicePolicyManager; 28 import android.content.ComponentName; 29 import android.content.Context; 30 import android.content.Intent; 31 import android.content.pm.ActivityInfo; 32 import android.content.pm.ApplicationInfo; 33 import android.content.pm.PackageInfo; 34 import android.content.pm.PackageManager; 35 import android.content.pm.ResolveInfo; 36 import android.os.UserHandle; 37 import android.test.AndroidTestCase; 38 39 import java.util.List; 40 41 public abstract class DpmTestBase extends AndroidTestCase { 42 public static final String TAG = "DpmTest"; 43 44 protected Context mRealTestContext; 45 protected DpmMockContext mMockContext; 46 private MockSystemServices mServices; 47 48 public ComponentName admin1; 49 public ComponentName admin2; 50 public ComponentName admin3; 51 public ComponentName adminAnotherPackage; 52 public ComponentName adminNoPerm; 53 54 @Override 55 protected void setUp() throws Exception { 56 super.setUp(); 57 58 mRealTestContext = super.getContext(); 59 60 mServices = new MockSystemServices(mRealTestContext, "test-data"); 61 mMockContext = new DpmMockContext(mServices, mRealTestContext); 62 63 admin1 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin1.class); 64 admin2 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin2.class); 65 admin3 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin3.class); 66 adminAnotherPackage = new ComponentName(DpmMockContext.ANOTHER_PACKAGE_NAME, 67 "whatever.random.class"); 68 adminNoPerm = new ComponentName(mRealTestContext, DummyDeviceAdmins.AdminNoPerm.class); 69 mockSystemPropertiesToReturnDefault(); 70 } 71 72 @Override 73 public DpmMockContext getContext() { 74 return mMockContext; 75 } 76 77 public MockSystemServices getServices() { 78 return mServices; 79 } 80 81 protected interface DpmRunnable { 82 void run(DevicePolicyManager dpm) throws Exception; 83 } 84 85 /** 86 * Simulate an RPC from {@param caller} to the service context ({@link #mMockContext}). 87 * 88 * The caller sees its own context. The server also sees its own separate context, with the 89 * appropriate calling UID and calling permissions fields already set up. 90 */ 91 protected void runAsCaller(DpmMockContext caller, DevicePolicyManagerServiceTestable dpms, 92 DpmRunnable action) { 93 final DpmMockContext serviceContext = mMockContext; 94 95 // Save calling UID and PID before clearing identity so we don't run into aliasing issues. 96 final int callingUid = caller.binder.callingUid; 97 final int callingPid = caller.binder.callingPid; 98 99 final long origId = serviceContext.binder.clearCallingIdentity(); 100 try { 101 serviceContext.binder.callingUid = callingUid; 102 serviceContext.binder.callingPid = callingPid; 103 serviceContext.binder.callingPermissions.put(callingUid, caller.permissions); 104 action.run(new DevicePolicyManagerTestable(caller, dpms)); 105 } catch (Exception e) { 106 throw new AssertionError(e); 107 } finally { 108 serviceContext.binder.restoreCallingIdentity(origId); 109 } 110 } 111 112 private void markPackageAsInstalled(String packageName, ApplicationInfo ai, int userId) 113 throws Exception { 114 final PackageInfo pi = DpmTestUtils.cloneParcelable( 115 mRealTestContext.getPackageManager().getPackageInfo( 116 mRealTestContext.getPackageName(), 0)); 117 assertTrue(pi.applicationInfo.flags != 0); 118 119 if (ai != null) { 120 pi.applicationInfo = ai; 121 } 122 123 doReturn(pi).when(mServices.ipackageManager).getPackageInfo( 124 eq(packageName), 125 eq(0), 126 eq(userId)); 127 128 doReturn(ai.uid).when(mServices.packageManager).getPackageUidAsUser( 129 eq(packageName), 130 eq(userId)); 131 } 132 133 protected void setUpPackageManagerForAdmin(ComponentName admin, int packageUid) 134 throws Exception { 135 setUpPackageManagerForAdmin(admin, packageUid, 136 /* enabledSetting =*/ null, /* appTargetSdk = */ null); 137 } 138 139 protected void setUpPackageManagerForAdmin(ComponentName admin, int packageUid, 140 int enabledSetting) throws Exception { 141 setUpPackageManagerForAdmin(admin, packageUid, enabledSetting, /* appTargetSdk = */ null); 142 } 143 144 protected void setUpPackageManagerForAdmin(ComponentName admin, int packageUid, 145 Integer enabledSetting, Integer appTargetSdk) throws Exception { 146 setUpPackageManagerForFakeAdmin(admin, packageUid, enabledSetting, appTargetSdk, 147 admin); 148 } 149 150 protected void setUpPackageManagerForFakeAdmin(ComponentName admin, int packageUid, 151 ComponentName copyFromAdmin) 152 throws Exception { 153 setUpPackageManagerForFakeAdmin(admin, packageUid, 154 /* enabledSetting =*/ null, /* appTargetSdk = */ null, copyFromAdmin); 155 } 156 157 /** 158 * Set up a component in the mock package manager to be an active admin. 159 * 160 * @param admin ComponentName that's visible to the test code, which doesn't have to exist. 161 * @param copyFromAdmin package information for {@code admin} will be built based on this 162 * component's information. 163 */ 164 private void setUpPackageManagerForFakeAdmin(ComponentName admin, int packageUid, 165 Integer enabledSetting, Integer appTargetSdk, ComponentName copyFromAdmin) 166 throws Exception { 167 168 // Set up getApplicationInfo(). 169 170 final ApplicationInfo ai = DpmTestUtils.cloneParcelable( 171 mRealTestContext.getPackageManager().getApplicationInfo( 172 copyFromAdmin.getPackageName(), 173 PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS)); 174 ai.enabledSetting = enabledSetting == null 175 ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED 176 : enabledSetting; 177 if (appTargetSdk != null) { 178 ai.targetSdkVersion = appTargetSdk; 179 } 180 ai.uid = packageUid; 181 ai.packageName = admin.getPackageName(); 182 ai.name = admin.getClassName(); 183 184 doReturn(ai).when(mServices.ipackageManager).getApplicationInfo( 185 eq(admin.getPackageName()), 186 anyInt(), 187 eq(UserHandle.getUserId(packageUid))); 188 189 // Set up queryBroadcastReceivers(). 190 191 final Intent resolveIntent = new Intent(); 192 resolveIntent.setComponent(copyFromAdmin); 193 final List<ResolveInfo> realResolveInfo = 194 mRealTestContext.getPackageManager().queryBroadcastReceivers( 195 resolveIntent, 196 PackageManager.GET_META_DATA); 197 assertNotNull(realResolveInfo); 198 assertEquals(1, realResolveInfo.size()); 199 200 // We need to change AI, so set a clone. 201 realResolveInfo.set(0, DpmTestUtils.cloneParcelable(realResolveInfo.get(0))); 202 203 // We need to rewrite the UID in the activity info. 204 final ActivityInfo aci = realResolveInfo.get(0).activityInfo; 205 aci.applicationInfo = ai; 206 aci.packageName = admin.getPackageName(); 207 aci.name = admin.getClassName(); 208 209 // Note we don't set up queryBroadcastReceivers. We don't use it in DPMS. 210 211 doReturn(aci).when(mServices.ipackageManager).getReceiverInfo( 212 eq(admin), 213 anyInt(), 214 eq(UserHandle.getUserId(packageUid))); 215 216 doReturn(new String[] {admin.getPackageName()}).when(mServices.ipackageManager) 217 .getPackagesForUid(eq(packageUid)); 218 // Set up getPackageInfo(). 219 markPackageAsInstalled(admin.getPackageName(), ai, UserHandle.getUserId(packageUid)); 220 } 221 222 /** 223 * By default, system properties are mocked to return default value. Override the mock if you 224 * want a specific value. 225 */ 226 private void mockSystemPropertiesToReturnDefault() { 227 when(getServices().systemProperties.get( 228 anyString(), anyString())).thenAnswer( 229 invocation -> invocation.getArguments()[1] 230 ); 231 232 when(getServices().systemProperties.getBoolean( 233 anyString(), anyBoolean())).thenAnswer( 234 invocation -> invocation.getArguments()[1] 235 ); 236 237 when(getServices().systemProperties.getLong( 238 anyString(), anyLong())).thenAnswer( 239 invocation -> invocation.getArguments()[1] 240 ); 241 } 242 } 243