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