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