1 /* 2 * Copyright (C) 2012 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.cts.verifier.managedprovisioning; 18 19 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE; 20 21 import android.Manifest; 22 import android.app.Service; 23 import android.app.admin.DeviceAdminReceiver; 24 import android.app.admin.DevicePolicyManager; 25 import android.content.ComponentName; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.IntentFilter; 29 import android.content.ServiceConnection; 30 import android.content.pm.PackageManager; 31 import android.os.IBinder; 32 import android.os.PersistableBundle; 33 import android.os.Process; 34 import android.os.RemoteException; 35 import android.os.UserHandle; 36 import android.os.UserManager; 37 import android.util.Log; 38 39 import androidx.localbroadcastmanager.content.LocalBroadcastManager; 40 41 import com.android.bedstead.dpmwrapper.DeviceOwnerHelper; 42 import com.android.bedstead.dpmwrapper.TestAppSystemServiceFactory; 43 import com.android.compatibility.common.util.enterprise.DeviceAdminReceiverUtils; 44 import com.android.cts.verifier.R; 45 46 import java.util.Collections; 47 import java.util.HashSet; 48 import java.util.List; 49 import java.util.Set; 50 import java.util.function.Consumer; 51 52 /** 53 * Profile owner receiver for BYOD flow test. 54 * Setup cross-profile intent filter after successful provisioning. 55 */ 56 public class DeviceAdminTestReceiver extends DeviceAdminReceiver { 57 public static final String KEY_BUNDLE_WIPE_IMMEDIATELY = "wipe_immediately"; 58 private static final String TAG = "DeviceAdminTestReceiver"; 59 private static final String DEVICE_OWNER_PKG = 60 "com.android.cts.verifier"; 61 private static final String ADMIN_RECEIVER_TEST_CLASS = 62 DEVICE_OWNER_PKG + ".managedprovisioning.DeviceAdminTestReceiver"; 63 private static final ComponentName RECEIVER_COMPONENT_NAME = new ComponentName( 64 DEVICE_OWNER_PKG, ADMIN_RECEIVER_TEST_CLASS); 65 public static final String EXTRA_MANAGED_USER_TEST = 66 "com.android.cts.verifier.managedprovisioning.extra.MANAGED_USER_TEST"; 67 public static final String EXTRA_LOGOUT_ON_START = 68 "com.android.cts.verifier.managedprovisioning.extra.LOGOUT_ON_START"; 69 public static final String AFFILIATION_ID = "affiliationId"; 70 getReceiverComponentName()71 public static ComponentName getReceiverComponentName() { 72 return RECEIVER_COMPONENT_NAME; 73 } 74 75 @Override onReceive(Context context, Intent intent)76 public void onReceive(Context context, Intent intent) { 77 if (DeviceAdminReceiverUtils.disableSelf(context, intent)) return; 78 if (DeviceOwnerHelper.runManagerMethod(this, context, intent)) return; 79 80 DevicePolicyManager dpm = getManager(context); 81 String action = intent.getAction(); 82 Log.d(TAG, "onReceive(): user=" + UserHandle.myUserId() + ", action=" + action 83 + ", EXTRA_USER=" + intent.getExtra(Intent.EXTRA_USER) 84 + ", dpm=" + dpm); 85 86 // Must set affiliation on headless system user, otherwise some operations in the current 87 // user (which is PO) won't be allowed (like uininstalling a package) 88 if (ACTION_DEVICE_ADMIN_ENABLED.equals(action) && UserManager.isHeadlessSystemUserMode()) { 89 Set<String> ids = new HashSet<>(1); 90 ids.add(DeviceAdminTestReceiver.AFFILIATION_ID); 91 ComponentName admin = getWho(context); 92 Log.i(TAG, "Setting affiliation ids to " + ids); 93 dpm.setAffiliationIds(admin, ids); 94 if (dpm.isProfileOwnerApp(context.getPackageName()) && !dpm.isEphemeralUser(admin)) { 95 // For profile owner, also set the affiliation IDs for DO to make sure that PO is 96 // affiliated. For system user, DO affiliation ids are already set above, so no need 97 // to set them again. 98 Log.i(TAG, "Also setting the affiliation ids for device owner"); 99 DevicePolicyManager doDpm = TestAppSystemServiceFactory.getDevicePolicyManager( 100 context, getClass(), /* forDeviceOwner= */ true); 101 doDpm.setAffiliationIds(admin, ids); 102 } 103 Log.i(TAG, "Is affiliated: " + dpm.isAffiliatedUser()); 104 } 105 106 super.onReceive(context, intent); 107 } 108 109 @Override onProfileProvisioningComplete(Context context, Intent intent)110 public void onProfileProvisioningComplete(Context context, Intent intent) { 111 Log.d(TAG, "Provisioning complete intent received"); 112 setupProfile(context); 113 wipeIfNecessary(context, intent); 114 } 115 116 @Override onBugreportSharingDeclined(Context context, Intent intent)117 public void onBugreportSharingDeclined(Context context, Intent intent) { 118 Log.i(TAG, "Bugreport sharing declined"); 119 Utils.showBugreportNotification(context, context.getString( 120 R.string.bugreport_sharing_declined), Utils.BUGREPORT_NOTIFICATION_ID); 121 } 122 123 @Override onBugreportShared(Context context, Intent intent, String bugreportFileHash)124 public void onBugreportShared(Context context, Intent intent, String bugreportFileHash) { 125 Log.i(TAG, "Bugreport shared"); 126 Utils.showBugreportNotification(context, context.getString( 127 R.string.bugreport_shared_successfully), Utils.BUGREPORT_NOTIFICATION_ID); 128 } 129 130 @Override onBugreportFailed(Context context, Intent intent, int failureCode)131 public void onBugreportFailed(Context context, Intent intent, int failureCode) { 132 Log.i(TAG, "Bugreport collection operation failed, code: " + failureCode); 133 Utils.showBugreportNotification(context, context.getString( 134 R.string.bugreport_failed_completing), Utils.BUGREPORT_NOTIFICATION_ID); 135 } 136 137 @Override onLockTaskModeEntering(Context context, Intent intent, String pkg)138 public void onLockTaskModeEntering(Context context, Intent intent, String pkg) { 139 Log.i(TAG, "Entering LockTask mode: " + pkg); 140 LocalBroadcastManager.getInstance(context) 141 .sendBroadcast(new Intent(LockTaskUiTestActivity.ACTION_LOCK_TASK_STARTED)); 142 } 143 144 @Override onLockTaskModeExiting(Context context, Intent intent)145 public void onLockTaskModeExiting(Context context, Intent intent) { 146 Log.i(TAG, "Exiting LockTask mode"); 147 LocalBroadcastManager.getInstance(context) 148 .sendBroadcast(new Intent(LockTaskUiTestActivity.ACTION_LOCK_TASK_STOPPED)); 149 } 150 151 @Override onEnabled(Context context, Intent intent)152 public void onEnabled(Context context, Intent intent) { 153 int myUserId = UserHandle.myUserId(); 154 Log.i(TAG, "Device admin enabled on user " + myUserId); 155 if (intent.getBooleanExtra(EXTRA_MANAGED_USER_TEST, false)) { 156 DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 157 ComponentName admin = getReceiverComponentName(); 158 dpm.setAffiliationIds(admin, 159 Collections.singleton(DeviceAdminTestReceiver.AFFILIATION_ID)); 160 context.startActivity( 161 new Intent(context, ManagedUserPositiveTestActivity.class).setFlags( 162 Intent.FLAG_ACTIVITY_NEW_TASK)); 163 164 bindPrimaryUserService(context, iCrossUserService -> { 165 try { 166 UserHandle userHandle = Process.myUserHandle(); 167 Log.d(TAG, "calling switchUser(" + userHandle + ") from " + myUserId); 168 iCrossUserService.switchUser(userHandle); 169 } catch (RemoteException re) { 170 Log.e(TAG, "Error when calling primary user", re); 171 } 172 }); 173 } else if (intent.getBooleanExtra(EXTRA_LOGOUT_ON_START, false)) { 174 DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 175 ComponentName admin = getReceiverComponentName(); 176 dpm.setAffiliationIds(admin, 177 Collections.singleton(DeviceAdminTestReceiver.AFFILIATION_ID)); 178 dpm.logoutUser(admin); 179 } 180 } 181 setupProfile(Context context)182 private void setupProfile(Context context) { 183 DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); 184 dpm.setProfileEnabled(new ComponentName(context.getApplicationContext(), getClass())); 185 186 // Setup cross-profile intent filter to allow communications between the two versions of CtsVerifier 187 // Primary -> work direction 188 IntentFilter filter = new IntentFilter(); 189 filter.addAction(ByodHelperActivity.ACTION_QUERY_PROFILE_OWNER); 190 filter.addAction(ByodHelperActivity.ACTION_REMOVE_MANAGED_PROFILE); 191 filter.addAction(ByodHelperActivity.ACTION_CHECK_DISK_ENCRYPTION); 192 filter.addAction(ByodHelperActivity.ACTION_INSTALL_APK); 193 filter.addAction(ByodHelperActivity.ACTION_INSTALL_APK_WORK_PROFILE_GLOBAL_RESTRICTION); 194 filter.addAction(ByodHelperActivity.ACTION_INSTALL_APK_PRIMARY_PROFILE_GLOBAL_RESTRICTION); 195 filter.addAction(ByodHelperActivity.ACTION_CHECK_INTENT_FILTERS); 196 filter.addAction(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_IMAGE); 197 filter.addAction(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_VIDEO_WITH_EXTRA_OUTPUT); 198 filter.addAction(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_VIDEO_WITHOUT_EXTRA_OUTPUT); 199 filter.addAction(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_AUDIO); 200 filter.addAction(ByodHelperActivity.ACTION_KEYGUARD_DISABLED_FEATURES); 201 filter.addAction(ByodHelperActivity.ACTION_LOCKNOW); 202 filter.addAction(ByodHelperActivity.ACTION_TEST_NFC_BEAM); 203 filter.addAction(ByodHelperActivity.ACTION_TEST_CROSS_PROFILE_INTENTS_DIALOG); 204 filter.addAction(ByodHelperActivity.ACTION_TEST_APP_LINKING_DIALOG); 205 filter.addAction(ByodHelperActivity.ACTION_NOTIFICATION); 206 filter.addAction(ByodHelperActivity.ACTION_NOTIFICATION_ON_LOCKSCREEN); 207 filter.addAction(ByodHelperActivity.ACTION_CLEAR_NOTIFICATION); 208 filter.addAction(ByodHelperActivity.ACTION_SET_USER_RESTRICTION); 209 filter.addAction(ByodHelperActivity.ACTION_CLEAR_USER_RESTRICTION); 210 filter.addAction(CrossProfileTestActivity.ACTION_CROSS_PROFILE_TO_WORK); 211 filter.addAction(ScreenshotCaptureActivity.ACTION_CAPTURE_SCREENSHOT); 212 filter.addAction( 213 PermissionLockdownTestActivity.ACTION_MANAGED_PROFILE_CHECK_PERMISSION_LOCKDOWN); 214 filter.addAction(AuthenticationBoundKeyTestActivity.ACTION_AUTH_BOUND_KEY_TEST); 215 filter.addAction(VpnTestActivity.ACTION_VPN); 216 filter.addAction(AlwaysOnVpnSettingsTestActivity.ACTION_ALWAYS_ON_VPN_SETTINGS_TEST); 217 filter.addAction(RecentsRedactionActivity.ACTION_RECENTS); 218 filter.addAction(ByodHelperActivity.ACTION_TEST_SELECT_WORK_CHALLENGE); 219 filter.addAction(ByodHelperActivity.ACTION_TEST_PATTERN_WORK_CHALLENGE); 220 filter.addAction(ByodHelperActivity.ACTION_LAUNCH_CONFIRM_WORK_CREDENTIALS); 221 filter.addAction(ByodHelperActivity.ACTION_SET_ORGANIZATION_INFO); 222 filter.addAction(ByodHelperActivity.ACTION_TEST_PARENT_PROFILE_PASSWORD); 223 filter.addAction(SetSupportMessageActivity.ACTION_SET_SUPPORT_MSG); 224 filter.addAction(KeyChainTestActivity.ACTION_KEYCHAIN); 225 filter.addAction(CommandReceiverActivity.ACTION_EXECUTE_COMMAND); 226 filter.addAction(WorkProfileWidgetActivity.ACTION_TEST_WORK_PROFILE_WIDGET); 227 filter.addAction( 228 CrossProfilePermissionControlActivity.ACTION_CROSS_PROFILE_PERMISSION_CONTROL); 229 filter.addAction(LocationCheckerActivity.ACTION_CHECK_LOCATION_WORK); 230 dpm.addCrossProfileIntentFilter(getWho(context), filter, 231 DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT); 232 233 // Work -> primary direction 234 filter = new IntentFilter(); 235 filter.addAction(ByodHelperActivity.ACTION_PROFILE_OWNER_STATUS); 236 filter.addAction(ByodHelperActivity.ACTION_DISK_ENCRYPTION_STATUS); 237 filter.addAction(ByodHelperActivity.ACTION_INSTALL_APK_IN_PRIMARY); 238 filter.addAction(ByodFlowTestActivity.ACTION_TEST_RESULT); 239 filter.addAction(CrossProfileTestActivity.ACTION_CROSS_PROFILE_TO_PERSONAL); 240 filter.addAction(ScreenshotTestActivity.ACTION_SCREENSHOT_TEST); 241 filter.addAction(Intent.ACTION_SEND); 242 dpm.addCrossProfileIntentFilter(getWho(context), filter, 243 DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED); 244 245 // Disable the work profile instance of this activity, because it is a helper activity for 246 // the work -> primary direction. 247 context.getPackageManager().setComponentEnabledSetting( 248 new ComponentName(context, ByodPrimaryHelperActivity.class.getName()), 249 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); 250 251 // Disable the work profile instance of ByodFlowTestActivity 252 context.getPackageManager().setComponentEnabledSetting( 253 new ComponentName(context, ByodFlowTestActivity.class), 254 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); 255 256 dpm.setPermissionGrantState(getWho(context), context.getPackageName(), 257 Manifest.permission.POST_NOTIFICATIONS, 258 DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED); 259 } 260 wipeIfNecessary(Context context, Intent intent)261 private void wipeIfNecessary(Context context, Intent intent) { 262 PersistableBundle bundle = intent.getParcelableExtra( 263 EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE); 264 if (bundle != null && bundle.getBoolean(KEY_BUNDLE_WIPE_IMMEDIATELY, false)) { 265 getManager(context).wipeData(0); 266 } 267 } 268 bindPrimaryUserService(Context context, Consumer<ICrossUserService> consumer)269 private void bindPrimaryUserService(Context context, Consumer<ICrossUserService> consumer) { 270 DevicePolicyManager devicePolicyManager = context.getSystemService( 271 DevicePolicyManager.class); 272 List<UserHandle> adminUsers = devicePolicyManager.getBindDeviceAdminTargetUsers( 273 getReceiverComponentName()); 274 Log.d(TAG, "bindPrimaryUserService(): admins=" + adminUsers); 275 UserHandle primaryUser = adminUsers.get(0); 276 277 Log.d(TAG, "Calling primary user: " + primaryUser); 278 final ServiceConnection serviceConnection = new ServiceConnection() { 279 @Override 280 public void onServiceConnected(ComponentName name, IBinder service) { 281 Log.d(TAG, "onServiceConnected is called"); 282 consumer.accept(ICrossUserService.Stub.asInterface(service)); 283 } 284 285 @Override 286 public void onServiceDisconnected(ComponentName name) { 287 Log.d(TAG, "onServiceDisconnected is called"); 288 } 289 }; 290 final Intent serviceIntent = new Intent(context, PrimaryUserService.class); 291 devicePolicyManager.bindDeviceAdminServiceAsUser(getReceiverComponentName(), serviceIntent, 292 serviceConnection, Context.BindServiceFlags.of(Context.BIND_AUTO_CREATE), 293 primaryUser); 294 } 295 296 public static final class PrimaryUserService extends Service { 297 private final ICrossUserService.Stub mBinder = new ICrossUserService.Stub() { 298 public void switchUser(UserHandle userHandle) { 299 Log.d(TAG, "switchUser: " + userHandle); 300 getSystemService(DevicePolicyManager.class).switchUser(getReceiverComponentName(), 301 userHandle); 302 } 303 }; 304 305 @Override onBind(Intent intent)306 public IBinder onBind(Intent intent) { 307 return mBinder; 308 } 309 } 310 } 311