• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.managedprovisioning.parser;
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.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE;
25 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
26 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
27 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE;
28 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM;
29 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER;
30 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION;
31 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_ICON_URI;
32 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL;
33 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
34 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM;
35 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DISCLAIMERS;
36 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION;
37 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED;
38 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCALE;
39 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCAL_TIME;
40 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOGO_URI;
41 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_MAIN_COLOR;
42 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ORGANIZATION_NAME;
43 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION;
44 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_USER_CONSENT;
45 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_USER_SETUP;
46 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SUPPORT_URL;
47 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_TIME_ZONE;
48 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_HIDDEN;
49 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PAC_URL;
50 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PASSWORD;
51 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PROXY_BYPASS;
52 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PROXY_HOST;
53 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PROXY_PORT;
54 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_SECURITY_TYPE;
55 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_SSID;
56 import static com.android.internal.util.Preconditions.checkNotNull;
57 import static com.android.managedprovisioning.common.Globals.ACTION_RESUME_PROVISIONING;
58 import static com.android.managedprovisioning.model.ProvisioningParams.inferStaticDeviceAdminPackageName;
59 
60 import android.app.admin.DevicePolicyManager;
61 import android.content.ComponentName;
62 import android.content.Context;
63 import android.content.Intent;
64 import android.net.Uri;
65 import android.os.Bundle;
66 import android.os.PersistableBundle;
67 import android.support.annotation.Nullable;
68 import android.support.annotation.VisibleForTesting;
69 import com.android.managedprovisioning.common.IllegalProvisioningArgumentException;
70 import com.android.managedprovisioning.common.LogoUtils;
71 import com.android.managedprovisioning.common.ManagedProvisioningSharedPreferences;
72 import com.android.managedprovisioning.common.ProvisionLogger;
73 import com.android.managedprovisioning.common.StoreUtils;
74 import com.android.managedprovisioning.common.Utils;
75 import com.android.managedprovisioning.model.DisclaimersParam;
76 import com.android.managedprovisioning.model.PackageDownloadInfo;
77 import com.android.managedprovisioning.model.ProvisioningParams;
78 import com.android.managedprovisioning.model.WifiInfo;
79 import java.util.Arrays;
80 import java.util.Collections;
81 import java.util.HashSet;
82 import java.util.Set;
83 
84 /**
85  * A parser which parses provisioning data from intent which stores in {@link Bundle} extras.
86  */
87 
88 @VisibleForTesting
89 public class ExtrasProvisioningDataParser implements ProvisioningDataParser {
90     private static final Set<String> PROVISIONING_ACTIONS_SUPPORT_ALL_PROVISIONING_DATA =
91             new HashSet<>(Collections.singletonList(
92                     ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE));
93 
94     private static final Set<String> PROVISIONING_ACTIONS_SUPPORT_MIN_PROVISIONING_DATA =
95             new HashSet<>(Arrays.asList(
96                     ACTION_PROVISION_MANAGED_DEVICE,
97                     ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
98                     ACTION_PROVISION_MANAGED_USER,
99                     ACTION_PROVISION_MANAGED_PROFILE));
100 
101     private final Utils mUtils;
102     private final Context mContext;
103     private final ManagedProvisioningSharedPreferences mSharedPreferences;
104 
ExtrasProvisioningDataParser(Context context, Utils utils)105     ExtrasProvisioningDataParser(Context context, Utils utils) {
106         this(context, utils, new ManagedProvisioningSharedPreferences(context));
107     }
108 
109     @VisibleForTesting
ExtrasProvisioningDataParser(Context context, Utils utils, ManagedProvisioningSharedPreferences sharedPreferences)110     ExtrasProvisioningDataParser(Context context, Utils utils,
111             ManagedProvisioningSharedPreferences sharedPreferences) {
112         mContext = checkNotNull(context);
113         mUtils = checkNotNull(utils);
114         mSharedPreferences = checkNotNull(sharedPreferences);
115     }
116 
117     @Override
parse(Intent provisioningIntent)118     public ProvisioningParams parse(Intent provisioningIntent)
119             throws IllegalProvisioningArgumentException{
120         String provisioningAction = provisioningIntent.getAction();
121         if (ACTION_RESUME_PROVISIONING.equals(provisioningAction)) {
122             return provisioningIntent.getParcelableExtra(
123                     ProvisioningParams.EXTRA_PROVISIONING_PARAMS);
124         }
125         if (PROVISIONING_ACTIONS_SUPPORT_MIN_PROVISIONING_DATA.contains(provisioningAction)) {
126             ProvisionLogger.logi("Processing mininalist extras intent.");
127             return parseMinimalistSupportedProvisioningDataInternal(provisioningIntent, mContext)
128                     .build();
129         } else if (PROVISIONING_ACTIONS_SUPPORT_ALL_PROVISIONING_DATA.contains(
130                 provisioningAction)) {
131             return parseAllSupportedProvisioningData(provisioningIntent, mContext);
132         } else {
133             throw new IllegalProvisioningArgumentException("Unsupported provisioning action: "
134                     + provisioningAction);
135         }
136     }
137 
138     /**
139      * Parses minimal supported set of parameters from bundle extras of a provisioning intent.
140      *
141      * <p>Here is the list of supported parameters.
142      * <ul>
143      *     <li>{@link EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}</li>
144      *     <li>
145      *         {@link EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME} only in
146      *         {@link ACTION_PROVISION_MANAGED_PROFILE}.
147      *     </li>
148      *     <li>{@link EXTRA_PROVISIONING_LOGO_URI}</li>
149      *     <li>{@link EXTRA_PROVISIONING_MAIN_COLOR}</li>
150      *     <li>
151      *         {@link EXTRA_PROVISIONING_SKIP_USER_SETUP} only in
152      *         {@link ACTION_PROVISION_MANAGED_USER} and {@link ACTION_PROVISION_MANAGED_DEVICE}.
153      *     </li>
154      *     <li>{@link EXTRA_PROVISIONING_SKIP_ENCRYPTION}</li>
155      *     <li>{@link EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED}</li>
156      *     <li>{@link EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE}</li>
157      *     <li>{@link EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}</li>
158      *     <li>{@link EXTRA_PROVISIONING_SKIP_USER_CONSENT}</li>
159      * </ul>
160      */
parseMinimalistSupportedProvisioningDataInternal( Intent intent, Context context)161     private ProvisioningParams.Builder parseMinimalistSupportedProvisioningDataInternal(
162             Intent intent, Context context)
163             throws IllegalProvisioningArgumentException {
164         final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
165         boolean isProvisionManagedDeviceFromTrustedSourceIntent =
166                 ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE.equals(intent.getAction());
167         try {
168             final long provisioningId = mSharedPreferences.incrementAndGetProvisioningId();
169             String provisioningAction = mUtils.mapIntentToDpmAction(intent);
170             final boolean isManagedProfileAction =
171                     ACTION_PROVISION_MANAGED_PROFILE.equals(provisioningAction);
172 
173             // Parse device admin package name and component name.
174             ComponentName deviceAdminComponentName = (ComponentName) intent.getParcelableExtra(
175                     EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME);
176             // Device admin package name is deprecated. It is only supported in Profile Owner
177             // provisioning and when resuming NFC provisioning.
178             String deviceAdminPackageName = null;
179             if (isManagedProfileAction) {
180                 // In L, we only support package name. This means some DPC may still send us the
181                 // device admin package name only. Attempts to obtain the package name from extras.
182                 deviceAdminPackageName = intent.getStringExtra(
183                         EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME);
184                 // For profile owner, the device admin package should be installed. Verify the
185                 // device admin package.
186                 deviceAdminComponentName = mUtils.findDeviceAdmin(
187                         deviceAdminPackageName, deviceAdminComponentName, context);
188                 // Since the device admin package must be installed at this point and its component
189                 // name has been obtained, it should be safe to set the deprecated package name
190                 // value to null.
191                 deviceAdminPackageName = null;
192             }
193 
194             // Parse skip user setup in ACTION_PROVISION_MANAGED_USER and
195             // ACTION_PROVISION_MANAGED_DEVICE (sync auth) only. This extra is not supported if
196             // provisioning was started by trusted source, as it is not clear where SUW should
197             // continue from.
198             boolean skipUserSetup = ProvisioningParams.DEFAULT_SKIP_USER_SETUP;
199             if (!isProvisionManagedDeviceFromTrustedSourceIntent
200                     && (provisioningAction.equals(ACTION_PROVISION_MANAGED_USER)
201                             || provisioningAction.equals(ACTION_PROVISION_MANAGED_DEVICE))) {
202                 skipUserSetup = intent.getBooleanExtra(EXTRA_PROVISIONING_SKIP_USER_SETUP,
203                         ProvisioningParams.DEFAULT_SKIP_USER_SETUP);
204             }
205 
206             // Only current DeviceOwner can specify EXTRA_PROVISIONING_SKIP_USER_CONSENT when
207             // provisioning PO with ACTION_PROVISION_MANAGED_PROFILE
208             final boolean skipUserConsent = isManagedProfileAction
209                             && intent.getBooleanExtra(EXTRA_PROVISIONING_SKIP_USER_CONSENT,
210                                     ProvisioningParams.DEFAULT_EXTRA_PROVISIONING_SKIP_USER_CONSENT)
211                             && mUtils.isPackageDeviceOwner(dpm, inferStaticDeviceAdminPackageName(
212                                     deviceAdminComponentName, deviceAdminPackageName));
213 
214             // Only when provisioning PO with ACTION_PROVISION_MANAGED_PROFILE
215             final boolean keepAccountMigrated = isManagedProfileAction
216                             && intent.getBooleanExtra(EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION,
217                             ProvisioningParams.DEFAULT_EXTRA_PROVISIONING_KEEP_ACCOUNT_MIGRATED);
218 
219             // Parse main color and organization's logo. This is not supported in managed device
220             // from trusted source provisioning because, currently, there is no way to send
221             // organization logo to the device at this stage.
222             Integer mainColor = ProvisioningParams.DEFAULT_MAIN_COLOR;
223             if (!isProvisionManagedDeviceFromTrustedSourceIntent) {
224                 if (intent.hasExtra(EXTRA_PROVISIONING_MAIN_COLOR)) {
225                     mainColor = intent.getIntExtra(EXTRA_PROVISIONING_MAIN_COLOR, 0 /* not used */);
226                 }
227                 parseOrganizationLogoUrlFromExtras(context, intent);
228             }
229 
230             DisclaimersParam disclaimersParam = new DisclaimersParser(context, provisioningId)
231                     .parse(intent.getParcelableArrayExtra(EXTRA_PROVISIONING_DISCLAIMERS));
232 
233             String deviceAdminLabel = null;
234             String organizationName = null;
235             String supportUrl = null;
236             String deviceAdminIconFilePath = null;
237             if (isProvisionManagedDeviceFromTrustedSourceIntent) {
238                 deviceAdminLabel = intent.getStringExtra(
239                         EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL);
240                 organizationName = intent.getStringExtra(EXTRA_PROVISIONING_ORGANIZATION_NAME);
241                 supportUrl = intent.getStringExtra(EXTRA_PROVISIONING_SUPPORT_URL);
242                 deviceAdminIconFilePath = new DeviceAdminIconParser(context, provisioningId).parse(
243                         intent.getParcelableExtra(
244                                 EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_ICON_URI));
245             }
246 
247             final boolean leaveAllSystemAppsEnabled = isManagedProfileAction
248                     ? false
249                     : intent.getBooleanExtra(
250                             EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED,
251                             ProvisioningParams.DEFAULT_LEAVE_ALL_SYSTEM_APPS_ENABLED);
252 
253             return ProvisioningParams.Builder.builder()
254                     .setProvisioningId(provisioningId)
255                     .setProvisioningAction(provisioningAction)
256                     .setDeviceAdminComponentName(deviceAdminComponentName)
257                     .setDeviceAdminPackageName(deviceAdminPackageName)
258                     .setSkipEncryption(intent.getBooleanExtra(EXTRA_PROVISIONING_SKIP_ENCRYPTION,
259                             ProvisioningParams.DEFAULT_EXTRA_PROVISIONING_SKIP_ENCRYPTION))
260                     .setLeaveAllSystemAppsEnabled(leaveAllSystemAppsEnabled)
261                     .setAdminExtrasBundle((PersistableBundle) intent.getParcelableExtra(
262                             EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE))
263                     .setMainColor(mainColor)
264                     .setDisclaimersParam(disclaimersParam)
265                     .setSkipUserConsent(skipUserConsent)
266                     .setKeepAccountMigrated(keepAccountMigrated)
267                     .setSkipUserSetup(skipUserSetup)
268                     .setAccountToMigrate(intent.getParcelableExtra(
269                             EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE))
270                     .setDeviceAdminLabel(deviceAdminLabel)
271                     .setOrganizationName(organizationName)
272                     .setSupportUrl(supportUrl)
273                     .setDeviceAdminIconFilePath(deviceAdminIconFilePath);
274         } catch (ClassCastException e) {
275             throw new IllegalProvisioningArgumentException("Extra has invalid type", e);
276         } catch (IllegalArgumentException e) {
277             throw new IllegalProvisioningArgumentException("Invalid parameter found!", e);
278         } catch (NullPointerException e) {
279             throw new IllegalProvisioningArgumentException("Compulsory parameter not found!", e);
280         }
281     }
282 
283     /**
284      * Parses an intent and return a corresponding {@link ProvisioningParams} object.
285      *
286      * @param intent intent to be parsed.
287      * @param context a context
288      */
parseAllSupportedProvisioningData(Intent intent, Context context)289     private ProvisioningParams parseAllSupportedProvisioningData(Intent intent, Context context)
290             throws IllegalProvisioningArgumentException {
291         try {
292             ProvisionLogger.logi("Processing all supported extras intent: " + intent.getAction());
293             return parseMinimalistSupportedProvisioningDataInternal(intent, context)
294                     // Parse time zone, local time and locale.
295                     .setTimeZone(intent.getStringExtra(EXTRA_PROVISIONING_TIME_ZONE))
296                     .setLocalTime(intent.getLongExtra(EXTRA_PROVISIONING_LOCAL_TIME,
297                             ProvisioningParams.DEFAULT_LOCAL_TIME))
298                     .setLocale(StoreUtils.stringToLocale(
299                             intent.getStringExtra(EXTRA_PROVISIONING_LOCALE)))
300                     // Parse WiFi configuration.
301                     .setWifiInfo(parseWifiInfoFromExtras(intent))
302                     // Parse device admin package download info.
303                     .setDeviceAdminDownloadInfo(parsePackageDownloadInfoFromExtras(intent))
304                     // Cases where startedByTrustedSource can be true are
305                     // 1. We are reloading a stored provisioning intent, either Nfc bump or
306                     //    PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE, after encryption reboot,
307                     //    which is a self-originated intent.
308                     // 2. the intent is from a trusted source, for example QR provisioning.
309                     .setStartedByTrustedSource(ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE
310                             .equals(intent.getAction()))
311                     .build();
312         }  catch (IllegalArgumentException e) {
313             throw new IllegalProvisioningArgumentException("Invalid parameter found!", e);
314         } catch (NullPointerException e) {
315             throw new IllegalProvisioningArgumentException("Compulsory parameter not found!", e);
316         }
317     }
318 
319     /**
320      * Parses Wifi configuration from an Intent and returns the result in {@link WifiInfo}.
321      */
322     @Nullable
parseWifiInfoFromExtras(Intent intent)323     private WifiInfo parseWifiInfoFromExtras(Intent intent) {
324         if (intent.getStringExtra(EXTRA_PROVISIONING_WIFI_SSID) == null) {
325             return null;
326         }
327         return WifiInfo.Builder.builder()
328                 .setSsid(intent.getStringExtra(EXTRA_PROVISIONING_WIFI_SSID))
329                 .setSecurityType(intent.getStringExtra(EXTRA_PROVISIONING_WIFI_SECURITY_TYPE))
330                 .setPassword(intent.getStringExtra(EXTRA_PROVISIONING_WIFI_PASSWORD))
331                 .setProxyHost(intent.getStringExtra(EXTRA_PROVISIONING_WIFI_PROXY_HOST))
332                 .setProxyBypassHosts(intent.getStringExtra(EXTRA_PROVISIONING_WIFI_PROXY_BYPASS))
333                 .setPacUrl(intent.getStringExtra(EXTRA_PROVISIONING_WIFI_PAC_URL))
334                 .setProxyPort(intent.getIntExtra(EXTRA_PROVISIONING_WIFI_PROXY_PORT,
335                         WifiInfo.DEFAULT_WIFI_PROXY_PORT))
336                 .setHidden(intent.getBooleanExtra(EXTRA_PROVISIONING_WIFI_HIDDEN,
337                         WifiInfo.DEFAULT_WIFI_HIDDEN))
338                 .build();
339     }
340 
341     /**
342      * Parses device admin package download info configuration from an Intent and returns the result
343      * in {@link PackageDownloadInfo}.
344      */
345     @Nullable
parsePackageDownloadInfoFromExtras(Intent intent)346     private PackageDownloadInfo parsePackageDownloadInfoFromExtras(Intent intent) {
347         if (intent.getStringExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION)
348                 == null) {
349             return null;
350         }
351         PackageDownloadInfo.Builder downloadInfoBuilder = PackageDownloadInfo.Builder.builder()
352                 .setMinVersion(intent.getIntExtra(
353                         EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE,
354                         PackageDownloadInfo.DEFAULT_MINIMUM_VERSION))
355                 .setLocation(intent.getStringExtra(
356                         EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION))
357                 .setCookieHeader(intent.getStringExtra(
358                         EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER));
359         String packageHash =
360                 intent.getStringExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM);
361         if (packageHash != null) {
362             downloadInfoBuilder.setPackageChecksum(StoreUtils.stringToByteArray(packageHash));
363         }
364         String sigHash = intent.getStringExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM);
365         if (sigHash != null) {
366             downloadInfoBuilder.setSignatureChecksum(StoreUtils.stringToByteArray(sigHash));
367         }
368         return downloadInfoBuilder.build();
369     }
370 
371     /**
372      * Parses the organization logo url from intent.
373      */
parseOrganizationLogoUrlFromExtras(Context context, Intent intent)374     private void parseOrganizationLogoUrlFromExtras(Context context, Intent intent) {
375         Uri logoUri = intent.getParcelableExtra(EXTRA_PROVISIONING_LOGO_URI);
376         if (logoUri != null) {
377             // If we go through encryption, and if the uri is a content uri:
378             // We'll lose the grant to this uri. So we need to save it to a local file.
379             LogoUtils.saveOrganisationLogo(context, logoUri);
380         }
381     }
382 }
383