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.managedprovisioning.ota; 18 19 import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE; 20 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.ArgumentMatchers.anyInt; 23 import static org.mockito.ArgumentMatchers.anyString; 24 import static org.mockito.ArgumentMatchers.eq; 25 import static org.mockito.Mockito.mock; 26 import static org.mockito.Mockito.when; 27 import static org.robolectric.Shadows.shadowOf; 28 29 import static com.google.common.truth.Truth.assertThat; 30 import android.app.AppOpsManager; 31 import android.app.admin.DevicePolicyManager; 32 import android.content.Context; 33 import android.content.pm.CrossProfileApps; 34 import android.content.pm.PackageManager; 35 import android.os.UserHandle; 36 import android.os.UserManager; 37 38 import androidx.test.core.app.ApplicationProvider; 39 40 import com.android.managedprovisioning.task.interactacrossprofiles.CrossProfileAppsSnapshot; 41 42 import org.junit.Before; 43 import org.junit.Test; 44 import org.junit.runner.RunWith; 45 import org.robolectric.RobolectricTestRunner; 46 import org.robolectric.shadows.ShadowProcess; 47 48 import java.util.Collections; 49 import java.util.Set; 50 51 @RunWith(RobolectricTestRunner.class) 52 public class CrossProfileAppsPregrantControllerTest { 53 54 private static final int MY_USER_ID = 0; 55 private static final int OTHER_USER_ID = 5; 56 private static final int OTHER_USER_UID = UserHandle.PER_USER_RANGE * OTHER_USER_ID; 57 58 private final Context mContext = ApplicationProvider.getApplicationContext(); 59 private final UserManager mUserManager = mContext.getSystemService(UserManager.class); 60 private final CrossProfileApps mCrossProfileApps = 61 mContext.getSystemService(CrossProfileApps.class); 62 private final DevicePolicyManager mDevicePolicyManager = 63 mContext.getSystemService(DevicePolicyManager.class); 64 private final CrossProfileAppsSnapshot mCrossProfileAppsSnapshot = 65 new CrossProfileAppsSnapshot(mContext); 66 67 // TODO(158280372): Remove mocks once suitable shadows are added 68 private final PackageManager mPackageManager = mock(PackageManager.class); 69 private final AppOpsManager mAppOpsManager = mock(AppOpsManager.class); 70 71 private final CrossProfileAppsPregrantController mPregrantController = 72 new CrossProfileAppsPregrantController( 73 mContext, 74 mUserManager, 75 mPackageManager, 76 mDevicePolicyManager, 77 mCrossProfileApps, 78 mAppOpsManager); 79 80 private static final String TEST_PACKAGE = "test.package"; 81 82 @Before setup()83 public void setup() { 84 // This is needed because the cross profile apps shadow doesn't actually set the appop 85 // so we copy the value of the app op into the mock AppOpsManager 86 when(mAppOpsManager.unsafeCheckOpNoThrow(anyString(), anyInt(), anyString())) 87 .thenAnswer( 88 invocation -> 89 shadowOf(mCrossProfileApps).getInteractAcrossProfilesAppOp( 90 invocation.getArgument(2))); 91 } 92 93 @Test onPrimaryProfile_noManagedProfile_doesNotPregrant()94 public void onPrimaryProfile_noManagedProfile_doesNotPregrant() { 95 // We default to no managed profile 96 setWhitelistedPackages(Collections.singleton(TEST_PACKAGE)); 97 setConfigurablePackages(Collections.singleton(TEST_PACKAGE)); 98 mCrossProfileAppsSnapshot.takeNewSnapshot(mContext.getUserId()); 99 mCrossProfileApps.setInteractAcrossProfilesAppOp(TEST_PACKAGE, AppOpsManager.MODE_DEFAULT); 100 101 mPregrantController.checkCrossProfileAppsPermissions(); 102 103 assertThat(shadowOf(mCrossProfileApps) 104 .getInteractAcrossProfilesAppOp(TEST_PACKAGE)) 105 .isEqualTo(AppOpsManager.MODE_DEFAULT); 106 } 107 108 @Test onManagedProfile_doesNotPregrant()109 public void onManagedProfile_doesNotPregrant() { 110 setRunningOnManagedProfile(); 111 setWhitelistedPackages(Collections.singleton(TEST_PACKAGE)); 112 setConfigurablePackages(Collections.singleton(TEST_PACKAGE)); 113 mCrossProfileAppsSnapshot.takeNewSnapshot(mContext.getUserId()); 114 mCrossProfileApps.setInteractAcrossProfilesAppOp(TEST_PACKAGE, AppOpsManager.MODE_DEFAULT); 115 116 mPregrantController.checkCrossProfileAppsPermissions(); 117 118 assertThat(shadowOf(mCrossProfileApps) 119 .getInteractAcrossProfilesAppOp(TEST_PACKAGE)) 120 .isEqualTo(AppOpsManager.MODE_DEFAULT); 121 } 122 123 @Test defaultConfigurablePackage_doesPregrant()124 public void defaultConfigurablePackage_doesPregrant() { 125 setRunningOnParentProfile(); 126 setWhitelistedPackages(Collections.singleton(TEST_PACKAGE)); 127 setConfigurablePackages(Collections.singleton(TEST_PACKAGE)); 128 mCrossProfileAppsSnapshot.takeNewSnapshot(mContext.getUserId()); 129 mCrossProfileApps.setInteractAcrossProfilesAppOp(TEST_PACKAGE, AppOpsManager.MODE_DEFAULT); 130 131 mPregrantController.checkCrossProfileAppsPermissions(); 132 133 assertThat(shadowOf(mCrossProfileApps) 134 .getInteractAcrossProfilesAppOp(TEST_PACKAGE)) 135 .isEqualTo(AppOpsManager.MODE_ALLOWED); 136 } 137 138 @Test nonDefaultConfigurablePackage_doesNotPregrant()139 public void nonDefaultConfigurablePackage_doesNotPregrant() { 140 setRunningOnParentProfile(); 141 setWhitelistedPackages(Collections.singleton(TEST_PACKAGE)); 142 setConfigurablePackages(Collections.singleton(TEST_PACKAGE)); 143 mCrossProfileAppsSnapshot.takeNewSnapshot(mContext.getUserId()); 144 mCrossProfileApps.setInteractAcrossProfilesAppOp(TEST_PACKAGE, AppOpsManager.MODE_IGNORED); 145 146 mPregrantController.checkCrossProfileAppsPermissions(); 147 148 assertThat(shadowOf(mCrossProfileApps) 149 .getInteractAcrossProfilesAppOp(TEST_PACKAGE)) 150 .isEqualTo(AppOpsManager.MODE_IGNORED); 151 } 152 setRunningOnParentProfile()153 private void setRunningOnParentProfile() { 154 shadowOf(mUserManager).addProfile( 155 MY_USER_ID, OTHER_USER_ID, /* profileName= */"otherUser", FLAG_MANAGED_PROFILE); 156 } 157 setRunningOnManagedProfile()158 private void setRunningOnManagedProfile() { 159 shadowOf(mUserManager).addProfile( 160 MY_USER_ID, OTHER_USER_ID, /* profileName= */"otherUser", FLAG_MANAGED_PROFILE); 161 ShadowProcess.setUid(OTHER_USER_UID); 162 } 163 setWhitelistedPackages(Set<String> packages)164 private void setWhitelistedPackages(Set<String> packages) { 165 shadowOf(mDevicePolicyManager).setDefaultCrossProfilePackages(packages); 166 } 167 setConfigurablePackages(Set<String> packages)168 private void setConfigurablePackages(Set<String> packages) { 169 packages.forEach(p -> shadowOf(mCrossProfileApps).addCrossProfilePackage(p)); 170 } 171 } 172