• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016, 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.preprovisioning;
18 
19 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE;
20 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE;
21 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
22 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE;
23 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
24 import static android.app.admin.DevicePolicyManager.CODE_ADD_MANAGED_PROFILE_DISALLOWED;
25 import static android.app.admin.DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE;
26 import static android.app.admin.DevicePolicyManager.CODE_HAS_DEVICE_OWNER;
27 import static android.app.admin.DevicePolicyManager.CODE_MANAGED_USERS_NOT_SUPPORTED;
28 import static android.app.admin.DevicePolicyManager.CODE_NOT_SYSTEM_USER;
29 import static android.app.admin.DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT;
30 import static android.app.admin.DevicePolicyManager.CODE_OK;
31 import static android.app.admin.DevicePolicyManager.CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER;
32 import static android.app.admin.DevicePolicyManager.CODE_USER_SETUP_COMPLETED;
33 import static android.nfc.NfcAdapter.ACTION_NDEF_DISCOVERED;
34 
35 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_PREPROVISIONING_ACTIVITY_TIME_MS;
36 import static com.android.internal.util.Preconditions.checkNotNull;
37 import static com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker.CANCELLED_BEFORE_PROVISIONING;
38 import static com.android.managedprovisioning.common.Globals.ACTION_RESUME_PROVISIONING;
39 
40 import android.annotation.NonNull;
41 import android.annotation.Nullable;
42 import android.app.ActivityManager;
43 import android.app.KeyguardManager;
44 import android.app.admin.DevicePolicyManager;
45 import android.content.ComponentName;
46 import android.content.Context;
47 import android.content.Intent;
48 import android.content.pm.PackageInfo;
49 import android.content.pm.PackageManager;
50 import android.content.pm.UserInfo;
51 import android.graphics.Bitmap;
52 import android.graphics.BitmapFactory;
53 import android.graphics.drawable.BitmapDrawable;
54 import android.graphics.drawable.Drawable;
55 import android.os.AsyncTask;
56 import android.os.UserManager;
57 import android.service.persistentdata.PersistentDataBlockManager;
58 import android.text.TextUtils;
59 
60 import com.android.internal.annotations.VisibleForTesting;
61 import com.android.managedprovisioning.R;
62 import com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker;
63 import com.android.managedprovisioning.analytics.TimeLogger;
64 import com.android.managedprovisioning.common.IllegalProvisioningArgumentException;
65 import com.android.managedprovisioning.common.MdmPackageInfo;
66 import com.android.managedprovisioning.common.ProvisionLogger;
67 import com.android.managedprovisioning.common.SettingsFacade;
68 import com.android.managedprovisioning.common.StoreUtils;
69 import com.android.managedprovisioning.common.Utils;
70 import com.android.managedprovisioning.model.CustomizationParams;
71 import com.android.managedprovisioning.model.ProvisioningParams;
72 import com.android.managedprovisioning.parser.MessageParser;
73 import com.android.managedprovisioning.preprovisioning.terms.TermsDocument;
74 import com.android.managedprovisioning.preprovisioning.terms.TermsProvider;
75 
76 import java.util.List;
77 import java.util.stream.Collectors;
78 
79 public class PreProvisioningController {
80     private final Context mContext;
81     private final Ui mUi;
82     private final MessageParser mMessageParser;
83     private final Utils mUtils;
84     private final SettingsFacade mSettingsFacade;
85     private final EncryptionController mEncryptionController;
86 
87     // used system services
88     private final DevicePolicyManager mDevicePolicyManager;
89     private final UserManager mUserManager;
90     private final PackageManager mPackageManager;
91     private final ActivityManager mActivityManager;
92     private final KeyguardManager mKeyguardManager;
93     private final PersistentDataBlockManager mPdbManager;
94     private final TimeLogger mTimeLogger;
95     private final ProvisioningAnalyticsTracker mProvisioningAnalyticsTracker;
96 
97     private ProvisioningParams mParams;
98 
PreProvisioningController( @onNull Context context, @NonNull Ui ui)99     public PreProvisioningController(
100             @NonNull Context context,
101             @NonNull Ui ui) {
102         this(context, ui,
103                 new TimeLogger(context, PROVISIONING_PREPROVISIONING_ACTIVITY_TIME_MS),
104                 new MessageParser(context), new Utils(), new SettingsFacade(),
105                 EncryptionController.getInstance(context));
106     }
107     @VisibleForTesting
PreProvisioningController( @onNull Context context, @NonNull Ui ui, @NonNull TimeLogger timeLogger, @NonNull MessageParser parser, @NonNull Utils utils, @NonNull SettingsFacade settingsFacade, @NonNull EncryptionController encryptionController)108     PreProvisioningController(
109             @NonNull Context context,
110             @NonNull Ui ui,
111             @NonNull TimeLogger timeLogger,
112             @NonNull MessageParser parser,
113             @NonNull Utils utils,
114             @NonNull SettingsFacade settingsFacade,
115             @NonNull EncryptionController encryptionController) {
116         mContext = checkNotNull(context, "Context must not be null");
117         mUi = checkNotNull(ui, "Ui must not be null");
118         mTimeLogger = checkNotNull(timeLogger, "Time logger must not be null");
119         mMessageParser = checkNotNull(parser, "MessageParser must not be null");
120         mSettingsFacade = checkNotNull(settingsFacade);
121         mUtils = checkNotNull(utils, "Utils must not be null");
122         mEncryptionController = checkNotNull(encryptionController,
123                 "EncryptionController must not be null");
124 
125         mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
126                 Context.DEVICE_POLICY_SERVICE);
127         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
128         mPackageManager = mContext.getPackageManager();
129         mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
130         mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
131         mPdbManager = (PersistentDataBlockManager) mContext.getSystemService(
132                 Context.PERSISTENT_DATA_BLOCK_SERVICE);
133         mProvisioningAnalyticsTracker = ProvisioningAnalyticsTracker.getInstance();
134     }
135 
136     interface Ui {
137         /**
138          * Show an error message and cancel provisioning.
139          * @param titleId resource id used to form the user facing error title
140          * @param messageId resource id used to form the user facing error message
141          * @param errorMessage an error message that gets logged for debugging
142          */
showErrorAndClose(Integer titleId, int messageId, String errorMessage)143         void showErrorAndClose(Integer titleId, int messageId, String errorMessage);
144 
145         /**
146          * Request the user to encrypt the device.
147          * @param params the {@link ProvisioningParams} object related to the ongoing provisioning
148          */
requestEncryption(ProvisioningParams params)149         void requestEncryption(ProvisioningParams params);
150 
151         /**
152          * Request the user to choose a wifi network.
153          */
requestWifiPick()154         void requestWifiPick();
155 
156         /**
157          * Initialize the pre provisioning UI
158          * @param layoutRes resource id for the layout
159          * @param titleRes resource id for the title text
160          * @param packageLabel package label
161          * @param packageIcon package icon
162          * @param isProfileOwnerProvisioning false for Device Owner provisioning
163          * @param isComp true if in COMP provisioning mode
164          * @param termsHeaders list of terms headers
165          * @param customization customization parameters
166          */
initiateUi(int layoutRes, int titleRes, @Nullable String packageLabel, @Nullable Drawable packageIcon, boolean isProfileOwnerProvisioning, boolean isComp, @NonNull List<String> termsHeaders, @NonNull CustomizationParams customization)167         void initiateUi(int layoutRes, int titleRes, @Nullable String packageLabel,
168                 @Nullable Drawable packageIcon, boolean isProfileOwnerProvisioning, boolean isComp,
169                 @NonNull List<String> termsHeaders, @NonNull CustomizationParams customization);
170 
171         /**
172          * Start provisioning.
173          * @param userId the id of the user we want to start provisioning on
174          * @param params the {@link ProvisioningParams} object related to the ongoing provisioning
175          */
startProvisioning(int userId, ProvisioningParams params)176         void startProvisioning(int userId, ProvisioningParams params);
177 
178         /**
179          * Show a dialog to delete an existing managed profile.
180          * @param mdmPackageName the {@link ComponentName} of the existing profile's profile owner
181          * @param domainName domain name of the organization which owns the managed profile
182          * @param userId the user id of the existing profile
183          */
showDeleteManagedProfileDialog(ComponentName mdmPackageName, String domainName, int userId)184         void showDeleteManagedProfileDialog(ComponentName mdmPackageName, String domainName,
185                 int userId);
186 
187         /**
188          * Show an error dialog indicating that the current launcher does not support managed
189          * profiles and ask the user to choose a different one.
190          */
showCurrentLauncherInvalid()191         void showCurrentLauncherInvalid();
192     }
193 
194     /**
195      * Initiates Profile owner and device owner provisioning.
196      * @param intent Intent that started provisioning.
197      * @param params cached ProvisioningParams if it has been parsed from Intent
198      * @param callingPackage Package that started provisioning.
199      */
initiateProvisioning(Intent intent, ProvisioningParams params, String callingPackage)200     public void initiateProvisioning(Intent intent, ProvisioningParams params,
201             String callingPackage) {
202         mProvisioningAnalyticsTracker.logProvisioningSessionStarted(mContext);
203 
204         if (!tryParseParameters(intent, params)) {
205             return;
206         }
207 
208         if (!checkFactoryResetProtection(mParams, callingPackage)) {
209             return;
210         }
211 
212         if (!verifyActionAndCaller(intent, callingPackage)) {
213             return;
214         }
215 
216         // Check whether provisioning is allowed for the current action
217         if (!checkDevicePolicyPreconditions()) {
218             return;
219         }
220 
221         // PO preconditions
222         boolean waitForUserDelete = false;
223         if (isProfileOwnerProvisioning()) {
224             // If there is already a managed profile, setup the profile deletion dialog.
225             int existingManagedProfileUserId = mUtils.alreadyHasManagedProfile(mContext);
226             if (existingManagedProfileUserId != -1) {
227                 ComponentName mdmPackageName = mDevicePolicyManager
228                         .getProfileOwnerAsUser(existingManagedProfileUserId);
229                 String domainName = mDevicePolicyManager
230                         .getProfileOwnerNameAsUser(existingManagedProfileUserId);
231                 mUi.showDeleteManagedProfileDialog(mdmPackageName, domainName,
232                         existingManagedProfileUserId);
233                 waitForUserDelete = true;
234             }
235         }
236 
237         // DO preconditions
238         if (!isProfileOwnerProvisioning()) {
239             // TODO: make a general test based on deviceAdminDownloadInfo field
240             // PO doesn't ever initialize that field, so OK as a general case
241             if (!mUtils.isConnectedToNetwork(mContext) && mParams.wifiInfo == null
242                     && mParams.deviceAdminDownloadInfo != null
243                     && !mParams.useMobileData) {
244                 // Have the user pick a wifi network if necessary.
245                 // It is not possible to ask the user to pick a wifi network if
246                 // the screen is locked.
247                 // TODO: remove this check once we know the screen will not be locked.
248                 if (mKeyguardManager.inKeyguardRestrictedInputMode()) {
249                     // TODO: decide on what to do in that case; fail? retry on screen unlock?
250                     ProvisionLogger.logi("Cannot pick wifi because the screen is locked.");
251                 } else if (canRequestWifiPick()) {
252                     // we resume this method after a successful WiFi pick
253                     // TODO: refactor as evil - logic should be less spread out
254                     mUi.requestWifiPick();
255                     return;
256                 } else {
257                     mUi.showErrorAndClose(R.string.cant_set_up_device,
258                             R.string.contact_your_admin_for_help,
259                             "Cannot pick WiFi because there is no handler to the intent");
260                 }
261             }
262         }
263 
264         mTimeLogger.start();
265         mProvisioningAnalyticsTracker.logPreProvisioningStarted(mContext, intent);
266 
267         // as of now this is only true for COMP provisioning, where we already have a user consent
268         // since the DPC is DO already
269         if (mParams.skipUserConsent || isSilentProvisioningForTestingDeviceOwner()
270                 || isSilentProvisioningForTestingManagedProfile()) {
271             if (!waitForUserDelete) {
272                 continueProvisioningAfterUserConsent();
273             }
274             return;
275         }
276 
277         CustomizationParams customization =
278                 CustomizationParams.createInstance(mParams, mContext, mUtils);
279 
280         // show UI so we can get user's consent to continue
281         if (isProfileOwnerProvisioning()) {
282             boolean isComp = mDevicePolicyManager.isDeviceManaged();
283             mUi.initiateUi(R.layout.intro_profile_owner, R.string.setup_profile, null, null, true,
284                     isComp, getDisclaimerHeadings(), customization);
285         } else {
286             String packageName = mParams.inferDeviceAdminPackageName();
287             MdmPackageInfo packageInfo = MdmPackageInfo.createFromPackageName(mContext,
288                     packageName);
289             // Always take packageInfo first for installed app since PackageManager is more reliable
290             String packageLabel = packageInfo != null ? packageInfo.appLabel
291                     : mParams.deviceAdminLabel != null ? mParams.deviceAdminLabel : packageName;
292             Drawable packageIcon = packageInfo != null ? packageInfo.packageIcon
293                     : getDeviceAdminIconDrawable(mParams.deviceAdminIconFilePath);
294             mUi.initiateUi(R.layout.intro_device_owner,
295                     R.string.setup_device,
296                     packageLabel,
297                     packageIcon,
298                     false  /* isProfileOwnerProvisioning */,
299                     false, /* isComp */
300                     getDisclaimerHeadings(),
301                     customization);
302         }
303     }
304 
getDisclaimerHeadings()305     private @NonNull List<String> getDisclaimerHeadings() {
306         // TODO: only fetch headings, no need to fetch content; now not fast, but at least correct
307         return new TermsProvider(mContext, StoreUtils::readString, mUtils)
308                 .getTerms(mParams, TermsProvider.Flags.SKIP_GENERAL_DISCLAIMER)
309                 .stream()
310                 .map(TermsDocument::getHeading)
311                 .collect(Collectors.toList());
312     }
313 
getDeviceAdminIconDrawable(String deviceAdminIconFilePath)314     private Drawable getDeviceAdminIconDrawable(String deviceAdminIconFilePath) {
315         if (deviceAdminIconFilePath == null) {
316             return null;
317         }
318 
319         Bitmap bitmap = BitmapFactory.decodeFile(mParams.deviceAdminIconFilePath);
320         if (bitmap == null) {
321             return null;
322         }
323         return new BitmapDrawable(mContext.getResources(), bitmap);
324     }
325 
326     /**
327      * Start provisioning for real. In profile owner case, double check that the launcher
328      * supports managed profiles if necessary. In device owner case, possibly create a new user
329      * before starting provisioning.
330      */
continueProvisioningAfterUserConsent()331     public void continueProvisioningAfterUserConsent() {
332         // check if encryption is required
333         if (isEncryptionRequired()) {
334             if (mDevicePolicyManager.getStorageEncryptionStatus()
335                     == DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED) {
336                 mUi.showErrorAndClose(R.string.cant_set_up_device,
337                         R.string.device_doesnt_allow_encryption_contact_admin,
338                         "This device does not support encryption, and "
339                                 + DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION
340                                 + " was not passed.");
341             } else {
342                 mUi.requestEncryption(mParams);
343                 // we come back to this method after returning from encryption dialog
344                 // TODO: refactor as evil - logic should be less spread out
345             }
346             return;
347         }
348 
349         if (isProfileOwnerProvisioning()) { // PO case
350             // Check whether the current launcher supports managed profiles.
351             if (!mUtils.currentLauncherSupportsManagedProfiles(mContext)) {
352                 mUi.showCurrentLauncherInvalid();
353                 // we come back to this method after returning from launcher dialog
354                 // TODO: refactor as evil - logic should be less spread out
355                 return;
356             } else {
357                 // Cancel the boot reminder as provisioning has now started.
358                 mEncryptionController.cancelEncryptionReminder();
359                 stopTimeLogger();
360                 mUi.startProvisioning(mUserManager.getUserHandle(), mParams);
361             }
362         } else { // DO case
363             // Cancel the boot reminder as provisioning has now started.
364             mEncryptionController.cancelEncryptionReminder();
365             if (isMeatUserCreationRequired(mParams.provisioningAction)) {
366                 // Create the primary user, and continue the provisioning in this user.
367                 // successful end of this task triggers provisioning
368                 // TODO: refactor as evil - logic should be less spread out
369                 new CreatePrimaryUserTask().execute();
370             } else {
371                 stopTimeLogger();
372                 mUi.startProvisioning(mUserManager.getUserHandle(), mParams);
373             }
374         }
375     }
376 
377     /** @return False if condition preventing further provisioning */
378     @VisibleForTesting
checkFactoryResetProtection(ProvisioningParams params, String callingPackage)379     boolean checkFactoryResetProtection(ProvisioningParams params, String callingPackage) {
380         if (skipFactoryResetProtectionCheck(params, callingPackage)) {
381             return true;
382         }
383         if (factoryResetProtected()) {
384             mUi.showErrorAndClose(R.string.cant_set_up_device,
385                     R.string.device_has_reset_protection_contact_admin,
386                     "Factory reset protection blocks provisioning.");
387             return false;
388         }
389         return true;
390     }
391 
skipFactoryResetProtectionCheck( ProvisioningParams params, String callingPackage)392     private boolean skipFactoryResetProtectionCheck(
393             ProvisioningParams params, String callingPackage) {
394         if (TextUtils.isEmpty(callingPackage)) {
395             return false;
396         }
397         String persistentDataPackageName = mContext.getResources()
398                 .getString(com.android.internal.R.string.config_persistentDataPackageName);
399         try {
400             // Only skip the FRP check if the caller is the package responsible for maintaining FRP
401             // - i.e. if this is a flow for restoring device owner after factory reset.
402             PackageInfo callingPackageInfo = mPackageManager.getPackageInfo(callingPackage, 0);
403             return callingPackageInfo != null
404                     && callingPackageInfo.applicationInfo != null
405                     && callingPackageInfo.applicationInfo.isSystemApp()
406                     && !TextUtils.isEmpty(persistentDataPackageName)
407                     && callingPackage.equals(persistentDataPackageName)
408                     && params != null
409                     && params.startedByTrustedSource;
410         } catch (PackageManager.NameNotFoundException e) {
411             ProvisionLogger.loge("Calling package not found.", e);
412             return false;
413         }
414     }
415 
416     /** @return False if condition preventing further provisioning */
checkDevicePolicyPreconditions()417     @VisibleForTesting protected boolean checkDevicePolicyPreconditions() {
418         // If isSilentProvisioningForTestingDeviceOwner returns true, the component must be
419         // current device owner, and we can safely ignore isProvisioningAllowed as we don't call
420         // setDeviceOwner.
421         if (isSilentProvisioningForTestingDeviceOwner()) {
422             return true;
423         }
424 
425         int provisioningPreCondition = mDevicePolicyManager.checkProvisioningPreCondition(
426                 mParams.provisioningAction, mParams.inferDeviceAdminPackageName());
427         // Check whether provisioning is allowed for the current action.
428         if (provisioningPreCondition != CODE_OK) {
429             mProvisioningAnalyticsTracker.logProvisioningNotAllowed(mContext,
430                     provisioningPreCondition);
431             showProvisioningErrorAndClose(mParams.provisioningAction, provisioningPreCondition);
432             return false;
433         }
434         return true;
435     }
436 
437     /** @return False if condition preventing further provisioning */
tryParseParameters(Intent intent, ProvisioningParams params)438     private boolean tryParseParameters(Intent intent, ProvisioningParams params) {
439         try {
440             // Read the provisioning params from the provisioning intent
441             mParams = params == null ? mMessageParser.parse(intent) : params;
442         } catch (IllegalProvisioningArgumentException e) {
443             mUi.showErrorAndClose(R.string.cant_set_up_device, R.string.contact_your_admin_for_help,
444                     e.getMessage());
445             return false;
446         }
447         return true;
448     }
449 
450     /** @return False if condition preventing further provisioning */
verifyActionAndCaller(Intent intent, String callingPackage)451     @VisibleForTesting protected boolean verifyActionAndCaller(Intent intent,
452             String callingPackage) {
453         if (verifyActionAndCallerInner(intent, callingPackage)) {
454             return true;
455         } else {
456             mUi.showErrorAndClose(R.string.cant_set_up_device, R.string.contact_your_admin_for_help,
457                     "invalid intent or calling package");
458             return false;
459         }
460     }
461 
verifyActionAndCallerInner(Intent intent, String callingPackage)462     private boolean verifyActionAndCallerInner(Intent intent, String callingPackage) {
463         // If this is a resume after encryption or trusted intent, we verify the activity alias.
464         // Otherwise, verify that the calling app is trying to set itself as Device/ProfileOwner
465         if (ACTION_RESUME_PROVISIONING.equals(intent.getAction())) {
466             return verifyActivityAlias(intent, "PreProvisioningActivityAfterEncryption");
467         } else if (ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
468             return verifyActivityAlias(intent, "PreProvisioningActivityViaNfc");
469         } else if (ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE.equals(intent.getAction())) {
470             return verifyActivityAlias(intent, "PreProvisioningActivityViaTrustedApp");
471         } else {
472             return verifyCaller(callingPackage);
473         }
474     }
475 
verifyActivityAlias(Intent intent, String activityAlias)476     private boolean verifyActivityAlias(Intent intent, String activityAlias) {
477         ComponentName componentName = intent.getComponent();
478         if (componentName == null || componentName.getClassName() == null) {
479             ProvisionLogger.loge("null class in component when verifying activity alias "
480                     + activityAlias);
481             return false;
482         }
483 
484         if (!componentName.getClassName().endsWith(activityAlias)) {
485             ProvisionLogger.loge("Looking for activity alias " + activityAlias + ", but got "
486                     + componentName.getClassName());
487             return false;
488         }
489 
490         return true;
491     }
492 
493     /**
494      * Verify that the caller is trying to set itself as owner.
495      * @return false if the caller is trying to set a different package as owner.
496      */
verifyCaller(@onNull String callingPackage)497     private boolean verifyCaller(@NonNull String callingPackage) {
498         if (callingPackage == null) {
499             ProvisionLogger.loge("Calling package is null. Was startActivityForResult used to "
500                     + "start this activity?");
501             return false;
502         }
503 
504         if (!callingPackage.equals(mParams.inferDeviceAdminPackageName())) {
505             ProvisionLogger.loge("Permission denied, "
506                     + "calling package tried to set a different package as owner. ");
507             return false;
508         }
509 
510         return true;
511     }
512 
513     /**
514      * Returns whether the device needs encryption.
515      */
isEncryptionRequired()516     private boolean isEncryptionRequired() {
517         return !mParams.skipEncryption && mUtils.isEncryptionRequired();
518     }
519 
isSilentProvisioningForTestingDeviceOwner()520     private boolean isSilentProvisioningForTestingDeviceOwner() {
521         final ComponentName currentDeviceOwner =
522                 mDevicePolicyManager.getDeviceOwnerComponentOnCallingUser();
523         final ComponentName targetDeviceAdmin = mParams.deviceAdminComponentName;
524 
525         switch (mParams.provisioningAction) {
526             case DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE:
527                 return isPackageTestOnly()
528                         && currentDeviceOwner != null
529                         && targetDeviceAdmin != null
530                         && currentDeviceOwner.equals(targetDeviceAdmin);
531             default:
532                 return false;
533         }
534     }
535 
isSilentProvisioningForTestingManagedProfile()536     private boolean isSilentProvisioningForTestingManagedProfile() {
537         return DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE.equals(
538                 mParams.provisioningAction) && isPackageTestOnly();
539     }
540 
isPackageTestOnly()541     private boolean isPackageTestOnly() {
542         return mUtils.isPackageTestOnly(mContext.getPackageManager(),
543                 mParams.inferDeviceAdminPackageName(), mUserManager.getUserHandle());
544     }
545 
546     /**
547      * Returns whether the device is frp protected during setup wizard.
548      */
factoryResetProtected()549     private boolean factoryResetProtected() {
550         // If we are started during setup wizard, check for factory reset protection.
551         // If the device is already setup successfully, do not check factory reset protection.
552         if (mSettingsFacade.isDeviceProvisioned(mContext)) {
553             ProvisionLogger.logd("Device is provisioned, FRP not required.");
554             return false;
555         }
556 
557         if (mPdbManager == null) {
558             ProvisionLogger.logd("Reset protection not supported.");
559             return false;
560         }
561         int size = mPdbManager.getDataBlockSize();
562         ProvisionLogger.logd("Data block size: " + size);
563         return size > 0;
564     }
565 
566     /**
567      * Returns whether meat user creation is required or not.
568      * @param action Intent action that started provisioning
569      */
isMeatUserCreationRequired(String action)570     public boolean isMeatUserCreationRequired(String action) {
571         if (mUtils.isSplitSystemUser()
572                 && ACTION_PROVISION_MANAGED_DEVICE.equals(action)) {
573             List<UserInfo> users = mUserManager.getUsers();
574             if (users.size() > 1) {
575                 mUi.showErrorAndClose(R.string.cant_set_up_device,
576                         R.string.contact_your_admin_for_help,
577                         "Cannot start Device Owner Provisioning because there are already "
578                                 + users.size() + " users");
579                 return false;
580             }
581             return true;
582         } else {
583             return false;
584         }
585     }
586 
587     /**
588      * Returns whether activity to pick wifi can be requested or not.
589      */
canRequestWifiPick()590     private boolean canRequestWifiPick() {
591         return mPackageManager.resolveActivity(mUtils.getWifiPickIntent(), 0) != null;
592     }
593 
594     /**
595      * Returns whether the provisioning process is a profile owner provisioning process.
596      */
isProfileOwnerProvisioning()597     public boolean isProfileOwnerProvisioning() {
598         return mUtils.isProfileOwnerAction(mParams.provisioningAction);
599     }
600 
601     @Nullable
getParams()602     public ProvisioningParams getParams() {
603         return mParams;
604     }
605 
606     /**
607      * Notifies the time logger to stop.
608      */
stopTimeLogger()609     public void stopTimeLogger() {
610         mTimeLogger.stop();
611     }
612 
613     /**
614      * Log if PreProvisioning was cancelled.
615      */
logPreProvisioningCancelled()616     public void logPreProvisioningCancelled() {
617         mProvisioningAnalyticsTracker.logProvisioningCancelled(mContext,
618                 CANCELLED_BEFORE_PROVISIONING);
619     }
620 
621     /**
622      * Removes a user profile. If we are in COMP case, and were blocked by having to delete a user,
623      * resumes COMP provisioning.
624      */
removeUser(int userProfileId)625     public void removeUser(int userProfileId) {
626         // There is a possibility that the DO has set the disallow remove managed profile user
627         // restriction, but is initiating the provisioning. In this case, we still want to remove
628         // the managed profile.
629         // We know that we can remove the managed profile because we checked
630         // DevicePolicyManager.checkProvisioningPreCondition
631         mUserManager.removeUserEvenWhenDisallowed(userProfileId);
632     }
633 
634     /**
635      * See comment in place of usage. Check if we were in silent provisioning, got blocked, and now
636      * can resume.
637      */
checkResumeSilentProvisioning()638     public void checkResumeSilentProvisioning() {
639         if (mParams.skipUserConsent || isSilentProvisioningForTestingDeviceOwner()
640                 || isSilentProvisioningForTestingManagedProfile()) {
641             continueProvisioningAfterUserConsent();
642         }
643     }
644 
645     // TODO: review the use of async task for the case where the activity might have got killed
646     private class CreatePrimaryUserTask extends AsyncTask<Void, Void, UserInfo> {
647         @Override
doInBackground(Void... args)648         protected UserInfo doInBackground(Void... args) {
649             // Create the user where we're going to install the device owner.
650             UserInfo userInfo = mUserManager.createUser(
651                     mContext.getString(R.string.default_first_meat_user_name),
652                     UserInfo.FLAG_PRIMARY | UserInfo.FLAG_ADMIN);
653 
654             if (userInfo != null) {
655                 ProvisionLogger.logi("Created user " + userInfo.id + " to hold the device owner");
656             }
657             return userInfo;
658         }
659 
660         @Override
onPostExecute(UserInfo userInfo)661         protected void onPostExecute(UserInfo userInfo) {
662             if (userInfo == null) {
663                 mUi.showErrorAndClose(R.string.cant_set_up_device,
664                         R.string.contact_your_admin_for_help,
665                         "Could not create user to hold the device owner");
666             } else {
667                 mActivityManager.switchUser(userInfo.id);
668                 stopTimeLogger();
669                 // TODO: refactor as evil - logic should be less spread out
670                 mUi.startProvisioning(userInfo.id, mParams);
671             }
672         }
673     }
674 
showProvisioningErrorAndClose(String action, int provisioningPreCondition)675     private void showProvisioningErrorAndClose(String action, int provisioningPreCondition) {
676         // Try to show an error message explaining why provisioning is not allowed.
677         switch (action) {
678             case ACTION_PROVISION_MANAGED_USER:
679                 mUi.showErrorAndClose(R.string.cant_set_up_device,
680                         R.string.contact_your_admin_for_help,
681                         "Exiting managed user provisioning, setup incomplete");
682                 return;
683             case ACTION_PROVISION_MANAGED_PROFILE:
684                 showManagedProfileErrorAndClose(provisioningPreCondition);
685                 return;
686             case ACTION_PROVISION_MANAGED_DEVICE:
687             case ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE:
688                 showDeviceOwnerErrorAndClose(provisioningPreCondition);
689                 return;
690         }
691         // This should never be the case, as showProvisioningError is always called after
692         // verifying the supported provisioning actions.
693     }
694 
showManagedProfileErrorAndClose(int provisioningPreCondition)695     private void showManagedProfileErrorAndClose(int provisioningPreCondition) {
696         UserInfo userInfo = mUserManager.getUserInfo(mUserManager.getUserHandle());
697         ProvisionLogger.logw("DevicePolicyManager.checkProvisioningPreCondition returns code: "
698                 + provisioningPreCondition);
699         switch (provisioningPreCondition) {
700             case CODE_ADD_MANAGED_PROFILE_DISALLOWED:
701             case CODE_MANAGED_USERS_NOT_SUPPORTED:
702                 mUi.showErrorAndClose(R.string.cant_add_work_profile,
703                         R.string.work_profile_cant_be_added_contact_admin,
704                         "Exiting managed profile provisioning, managed profiles feature is not available");
705                 break;
706             case CODE_CANNOT_ADD_MANAGED_PROFILE:
707                 if (!userInfo.canHaveProfile()) {
708                     mUi.showErrorAndClose(R.string.cant_add_work_profile,
709                             R.string.work_profile_cant_be_added_contact_admin,
710                             "Exiting managed profile provisioning, calling user cannot have managed profiles");
711                 } else if (isRemovingManagedProfileDisallowed()){
712                     mUi.showErrorAndClose(R.string.cant_replace_or_remove_work_profile,
713                             R.string.for_help_contact_admin,
714                             "Exiting managed profile provisioning, removing managed profile is disallowed");
715                 } else {
716                     mUi.showErrorAndClose(R.string.cant_add_work_profile,
717                             R.string.work_profile_cant_be_added_contact_admin,
718                             "Exiting managed profile provisioning, cannot add more managed profiles");
719                 }
720                 break;
721             case CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER:
722                 mUi.showErrorAndClose(R.string.cant_add_work_profile,
723                         R.string.contact_your_admin_for_help,
724                         "Exiting managed profile provisioning, a device owner exists");
725                 break;
726             default:
727                 mUi.showErrorAndClose(R.string.cant_add_work_profile,
728                         R.string.contact_your_admin_for_help,
729                         "Managed profile provisioning not allowed for an unknown " +
730                         "reason, code: " + provisioningPreCondition);
731         }
732     }
733 
isRemovingManagedProfileDisallowed()734     private boolean isRemovingManagedProfileDisallowed() {
735         return mUtils.alreadyHasManagedProfile(mContext) != -1
736                 && mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE);
737     }
738 
showDeviceOwnerErrorAndClose(int provisioningPreCondition)739     private void showDeviceOwnerErrorAndClose(int provisioningPreCondition) {
740         switch (provisioningPreCondition) {
741             case CODE_HAS_DEVICE_OWNER:
742             case CODE_USER_SETUP_COMPLETED:
743                 mUi.showErrorAndClose(R.string.device_already_set_up,
744                         R.string.if_questions_contact_admin, "Device already provisioned.");
745                 return;
746             case CODE_NOT_SYSTEM_USER:
747                 mUi.showErrorAndClose(R.string.cant_set_up_device,
748                         R.string.contact_your_admin_for_help,
749                         "Device owner can only be set up for USER_SYSTEM.");
750                 return;
751             case CODE_NOT_SYSTEM_USER_SPLIT:
752                 mUi.showErrorAndClose(R.string.cant_set_up_device,
753                         R.string.contact_your_admin_for_help,
754                         "System User Device owner can only be set on a split-user system.");
755                 return;
756         }
757         mUi.showErrorAndClose(R.string.cant_set_up_device, R.string.contact_your_admin_for_help,
758                 "Device Owner provisioning not allowed for an unknown reason.");
759     }
760 }
761