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