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                         /* isSingleUser = */ false);
102                 doDpm.setAffiliationIds(admin, ids);
103             }
104             Log.i(TAG, "Is affiliated: " + dpm.isAffiliatedUser());
105         }
106 
107         super.onReceive(context, intent);
108     }
109 
110     @Override
onProfileProvisioningComplete(Context context, Intent intent)111     public void onProfileProvisioningComplete(Context context, Intent intent) {
112         Log.d(TAG, "Provisioning complete intent received");
113         setupProfile(context);
114         wipeIfNecessary(context, intent);
115     }
116 
117     @Override
onBugreportSharingDeclined(Context context, Intent intent)118     public void onBugreportSharingDeclined(Context context, Intent intent) {
119         Log.i(TAG, "Bugreport sharing declined");
120         Utils.showBugreportNotification(context, context.getString(
121                 R.string.bugreport_sharing_declined), Utils.BUGREPORT_NOTIFICATION_ID);
122     }
123 
124     @Override
onBugreportShared(Context context, Intent intent, String bugreportFileHash)125     public void onBugreportShared(Context context, Intent intent, String bugreportFileHash) {
126         Log.i(TAG, "Bugreport shared");
127         Utils.showBugreportNotification(context, context.getString(
128                 R.string.bugreport_shared_successfully), Utils.BUGREPORT_NOTIFICATION_ID);
129     }
130 
131     @Override
onBugreportFailed(Context context, Intent intent, int failureCode)132     public void onBugreportFailed(Context context, Intent intent, int failureCode) {
133         Log.i(TAG, "Bugreport collection operation failed, code: " + failureCode);
134         Utils.showBugreportNotification(context, context.getString(
135                 R.string.bugreport_failed_completing), Utils.BUGREPORT_NOTIFICATION_ID);
136     }
137 
138     @Override
onLockTaskModeEntering(Context context, Intent intent, String pkg)139     public void onLockTaskModeEntering(Context context, Intent intent, String pkg) {
140         Log.i(TAG, "Entering LockTask mode: " + pkg);
141         LocalBroadcastManager.getInstance(context)
142                 .sendBroadcast(new Intent(LockTaskUiTestActivity.ACTION_LOCK_TASK_STARTED));
143     }
144 
145     @Override
onLockTaskModeExiting(Context context, Intent intent)146     public void onLockTaskModeExiting(Context context, Intent intent) {
147         Log.i(TAG, "Exiting LockTask mode");
148         LocalBroadcastManager.getInstance(context)
149                 .sendBroadcast(new Intent(LockTaskUiTestActivity.ACTION_LOCK_TASK_STOPPED));
150     }
151 
152     @Override
onEnabled(Context context, Intent intent)153     public void onEnabled(Context context, Intent intent) {
154         int myUserId = UserHandle.myUserId();
155         Log.i(TAG, "Device admin enabled on user " + myUserId);
156         if (intent.getBooleanExtra(EXTRA_MANAGED_USER_TEST, false)) {
157             DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
158             ComponentName admin = getReceiverComponentName();
159             dpm.setAffiliationIds(admin,
160                     Collections.singleton(DeviceAdminTestReceiver.AFFILIATION_ID));
161             context.startActivity(
162                     new Intent(context, ManagedUserPositiveTestActivity.class).setFlags(
163                             Intent.FLAG_ACTIVITY_NEW_TASK));
164 
165             bindPrimaryUserService(context, iCrossUserService -> {
166                 try {
167                     UserHandle userHandle = Process.myUserHandle();
168                     Log.d(TAG, "calling switchUser(" + userHandle + ") from " + myUserId);
169                     iCrossUserService.switchUser(userHandle);
170                 } catch (RemoteException re) {
171                     Log.e(TAG, "Error when calling primary user", re);
172                 }
173             });
174         } else if (intent.getBooleanExtra(EXTRA_LOGOUT_ON_START, false)) {
175             DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
176             ComponentName admin = getReceiverComponentName();
177             dpm.setAffiliationIds(admin,
178                     Collections.singleton(DeviceAdminTestReceiver.AFFILIATION_ID));
179             dpm.logoutUser(admin);
180         }
181     }
182 
setupProfile(Context context)183     private void setupProfile(Context context) {
184         DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
185         dpm.setProfileEnabled(new ComponentName(context.getApplicationContext(), getClass()));
186 
187         // Setup cross-profile intent filter to allow communications between the two versions of CtsVerifier
188         // Primary -> work direction
189         IntentFilter filter = new IntentFilter();
190         filter.addAction(ByodHelperActivity.ACTION_QUERY_PROFILE_OWNER);
191         filter.addAction(ByodHelperActivity.ACTION_REMOVE_MANAGED_PROFILE);
192         filter.addAction(ByodHelperActivity.ACTION_CHECK_DISK_ENCRYPTION);
193         filter.addAction(ByodHelperActivity.ACTION_INSTALL_APK);
194         filter.addAction(ByodHelperActivity.ACTION_INSTALL_APK_WORK_PROFILE_GLOBAL_RESTRICTION);
195         filter.addAction(ByodHelperActivity.ACTION_INSTALL_APK_PRIMARY_PROFILE_GLOBAL_RESTRICTION);
196         filter.addAction(ByodHelperActivity.ACTION_CHECK_INTENT_FILTERS);
197         filter.addAction(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_IMAGE);
198         filter.addAction(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_VIDEO_WITH_EXTRA_OUTPUT);
199         filter.addAction(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_VIDEO_WITHOUT_EXTRA_OUTPUT);
200         filter.addAction(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_AUDIO);
201         filter.addAction(ByodHelperActivity.ACTION_KEYGUARD_DISABLED_FEATURES);
202         filter.addAction(ByodHelperActivity.ACTION_LOCKNOW);
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