1 /* 2 * Copyright (C) 2019 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.finalization; 18 19 import static android.app.admin.DeviceAdminReceiver.ACTION_PROFILE_PROVISIONING_COMPLETE; 20 import static android.app.admin.DevicePolicyManager.ACTION_ADMIN_POLICY_COMPLIANCE; 21 import static android.app.admin.DevicePolicyManager.ACTION_PROVISIONING_SUCCESSFUL; 22 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE; 23 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE; 24 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE; 25 import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE; 26 27 import static com.android.managedprovisioning.finalization.SendDpcBroadcastService.EXTRA_PROVISIONING_PARAMS; 28 29 import static com.google.common.truth.Truth.assertThat; 30 31 import static org.robolectric.Shadows.shadowOf; 32 33 import android.app.Application; 34 import android.app.ApplicationPackageManager; 35 import android.content.ComponentName; 36 import android.content.Context; 37 import android.content.Intent; 38 import android.content.pm.ResolveInfo; 39 import android.os.PersistableBundle; 40 import android.os.UserManager; 41 42 import com.android.managedprovisioning.model.ProvisioningParams; 43 44 import org.junit.Before; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 import org.robolectric.Robolectric; 48 import org.robolectric.RobolectricTestRunner; 49 import org.robolectric.RuntimeEnvironment; 50 import org.robolectric.android.controller.ServiceController; 51 52 import java.util.List; 53 54 /** 55 * Unit tests for {@link SendDpcBroadcastService}. 56 */ 57 @RunWith(RobolectricTestRunner.class) 58 public class SendDpcBroadcastServiceTest { 59 60 private final Context mContext = RuntimeEnvironment.application; 61 private final UserManager mUserManager = mContext.getSystemService(UserManager.class); 62 private final ApplicationPackageManager mPackageManager = 63 (ApplicationPackageManager) mContext.getApplicationContext().getPackageManager(); 64 private ServiceController<SendDpcBroadcastService> mController; 65 66 private static final int USER_HANDLE = 0; 67 private static final int PROFILE_USER_HANDLE = 2; 68 69 private static final String TEST_MDM_PACKAGE_NAME = "mdm.package.name"; 70 private static final String TEST_MDM_ADMIN_RECEIVER = TEST_MDM_PACKAGE_NAME + ".AdminReceiver"; 71 private static final ComponentName TEST_MDM_ADMIN = new ComponentName(TEST_MDM_PACKAGE_NAME, 72 TEST_MDM_ADMIN_RECEIVER); 73 private static final PersistableBundle TEST_MDM_EXTRA_BUNDLE = new PersistableBundle(); 74 private static final ProvisioningParams PARAMS = 75 ProvisioningParams.Builder.builder() 76 .setProvisioningAction(ACTION_PROVISION_MANAGED_PROFILE) 77 .setDeviceAdminComponentName(TEST_MDM_ADMIN) 78 .setAdminExtrasBundle(TEST_MDM_EXTRA_BUNDLE) 79 .setFlowType(ProvisioningParams.FLOW_TYPE_UNSPECIFIED) 80 .build(); 81 private static final ProvisioningParams PARAMS_TRUSTED_SOURCE = 82 ProvisioningParams.Builder.builder() 83 .setProvisioningAction(ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE) 84 .setDeviceAdminComponentName(TEST_MDM_ADMIN) 85 .setAdminExtrasBundle(TEST_MDM_EXTRA_BUNDLE) 86 .setStartedByTrustedSource(true) 87 .setFlowType(ProvisioningParams.FLOW_TYPE_ADMIN_INTEGRATED) 88 .build(); 89 90 private static final String BOOL_KEY = "mybool"; 91 private static final boolean BOOL_VALUE = false; 92 private static final String STRING_KEY = "mystring"; 93 private static final String STRING_VALUE = "some string"; 94 private static final String INT_KEY = "myint"; 95 private static final int INT_VALUE = 1234; 96 97 static { TEST_MDM_EXTRA_BUNDLE.putBoolean(BOOL_KEY, BOOL_VALUE)98 TEST_MDM_EXTRA_BUNDLE.putBoolean(BOOL_KEY, BOOL_VALUE); TEST_MDM_EXTRA_BUNDLE.putString(STRING_KEY, STRING_VALUE)99 TEST_MDM_EXTRA_BUNDLE.putString(STRING_KEY, STRING_VALUE); TEST_MDM_EXTRA_BUNDLE.putInt(INT_KEY, INT_VALUE)100 TEST_MDM_EXTRA_BUNDLE.putInt(INT_KEY, INT_VALUE); 101 } 102 103 @Before setUp()104 public void setUp() { 105 final Intent intent = 106 new Intent(RuntimeEnvironment.application, SendDpcBroadcastService.class) 107 .putExtra(EXTRA_PROVISIONING_PARAMS, PARAMS); 108 mController = Robolectric.buildService(SendDpcBroadcastService.class, intent); 109 110 shadowOf(mUserManager).addProfile( 111 /* userHandle= */ USER_HANDLE, 112 /* profileUserHandle= */ PROFILE_USER_HANDLE, 113 /* profileName= */ "profile", 114 /* profileFlags= */ FLAG_MANAGED_PROFILE); 115 } 116 117 @Test onStartCommand_legacyFlow_launchesDpcProvisioningSuccessful()118 public void onStartCommand_legacyFlow_launchesDpcProvisioningSuccessful() { 119 shadowOf(mPackageManager) 120 .addResolveInfoForIntent(createDpcLaunchIntent(), new ResolveInfo()); 121 122 mController.startCommand(/* flags= */ 0, /* startId= */ 0); 123 124 Intent launchedActivityIntent = shadowOf((Application) mContext).getNextStartedActivity(); 125 assertThat(launchedActivityIntent.getPackage()).isEqualTo(TEST_MDM_PACKAGE_NAME); 126 assertThat(launchedActivityIntent.getAction()).isEqualTo(ACTION_PROVISIONING_SUCCESSFUL); 127 assertThat(launchedActivityIntent.getFlags()).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK); 128 assertExtras(launchedActivityIntent); 129 } 130 131 @Test onStartCommand_adminIntegratedFlow_launchesDpcPolicyCompliance()132 public void onStartCommand_adminIntegratedFlow_launchesDpcPolicyCompliance() { 133 addCreatePolicyComplianceResolveInfo(); 134 ServiceController<SendDpcBroadcastService> serviceController = 135 buildServiceControllerForPolicyCompliance(); 136 137 serviceController.startCommand(/* flags= */ 0, /* startId= */ 0); 138 139 Intent launchedActivityIntent = shadowOf((Application) mContext).getNextStartedActivity(); 140 assertThat(launchedActivityIntent.getPackage()).isEqualTo(TEST_MDM_PACKAGE_NAME); 141 assertThat(launchedActivityIntent.getAction()).isEqualTo(ACTION_ADMIN_POLICY_COMPLIANCE); 142 assertThat(launchedActivityIntent.getFlags()).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK); 143 assertExtras(launchedActivityIntent); 144 } 145 146 @Test onStartCommand_nonSpecifiedFlow_sendsOrderedBroadcast()147 public void onStartCommand_nonSpecifiedFlow_sendsOrderedBroadcast() { 148 shadowOf(mPackageManager) 149 .addResolveInfoForIntent(createDpcLaunchIntent(), new ResolveInfo()); 150 151 mController.startCommand(/* flags= */ 0, /* startId= */ 0); 152 153 Intent broadcastIntent = getBroadcastIntentForAction(ACTION_PROFILE_PROVISIONING_COMPLETE); 154 assertThat(broadcastIntent.getComponent()).isEqualTo(TEST_MDM_ADMIN); 155 assertExtras(broadcastIntent); 156 } 157 158 @Test onStartCommand_adminIntegratedFlow_doesNotSendOrderedBroadcast()159 public void onStartCommand_adminIntegratedFlow_doesNotSendOrderedBroadcast() { 160 ServiceController<SendDpcBroadcastService> controller = 161 buildServiceControllerForPolicyCompliance(); 162 addCreatePolicyComplianceResolveInfo(); 163 164 controller.startCommand(/* flags= */ 0, /* startId= */ 0); 165 166 Intent broadcastIntent = getBroadcastIntentForAction(ACTION_PROFILE_PROVISIONING_COMPLETE); 167 assertThat(broadcastIntent).isNull(); 168 } 169 buildServiceControllerForPolicyCompliance()170 private ServiceController<SendDpcBroadcastService> buildServiceControllerForPolicyCompliance() { 171 final Intent intent = 172 new Intent(RuntimeEnvironment.application, SendDpcBroadcastService.class) 173 .putExtra(EXTRA_PROVISIONING_PARAMS, PARAMS_TRUSTED_SOURCE); 174 return Robolectric.buildService(SendDpcBroadcastService.class, intent); 175 } 176 addCreatePolicyComplianceResolveInfo()177 private void addCreatePolicyComplianceResolveInfo() { 178 shadowOf(mPackageManager) 179 .addResolveInfoForIntent( 180 createPolicyComplianceIntent(TEST_MDM_PACKAGE_NAME), 181 new ResolveInfo()); 182 } 183 getBroadcastIntentForAction(String action)184 private Intent getBroadcastIntentForAction(String action) { 185 List<Intent> broadcastIntents = shadowOf((Application) mContext).getBroadcastIntents(); 186 for (Intent intent : broadcastIntents) { 187 if (intent.getAction().equals(action)) { 188 return intent; 189 } 190 } 191 return null; 192 } 193 assertExtras(Intent intent)194 private void assertExtras(Intent intent) { 195 final PersistableBundle bundle = 196 (PersistableBundle) intent.getExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE); 197 assertThat( 198 bundle.getBoolean(BOOL_KEY)).isEqualTo(TEST_MDM_EXTRA_BUNDLE.getBoolean(BOOL_KEY)); 199 assertThat( 200 bundle.getInt(INT_KEY)).isEqualTo(TEST_MDM_EXTRA_BUNDLE.getInt(INT_KEY)); 201 assertThat( 202 bundle.getInt(STRING_KEY)).isEqualTo(TEST_MDM_EXTRA_BUNDLE.getInt(STRING_KEY)); 203 } 204 createDpcLaunchIntent()205 private Intent createDpcLaunchIntent() { 206 final Intent intent = new Intent(ACTION_PROVISIONING_SUCCESSFUL); 207 final String packageName = PARAMS.inferDeviceAdminPackageName(); 208 intent.setPackage(packageName); 209 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 210 intent.putExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, PARAMS.adminExtrasBundle); 211 return intent; 212 } 213 createPolicyComplianceIntent(String packageName)214 private Intent createPolicyComplianceIntent(String packageName) { 215 final Intent intent = new Intent(ACTION_ADMIN_POLICY_COMPLIANCE); 216 intent.setPackage(packageName); 217 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 218 return intent; 219 } 220 } 221