Home | History | Annotate | Download | only in devicepolicy
      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