17079df5a3fb155947004843ee8ec25b36127e3edSteven Ng/*
27079df5a3fb155947004843ee8ec25b36127e3edSteven Ng * Copyright 2016, The Android Open Source Project
37079df5a3fb155947004843ee8ec25b36127e3edSteven Ng *
47079df5a3fb155947004843ee8ec25b36127e3edSteven Ng * Licensed under the Apache License, Version 2.0 (the "License");
57079df5a3fb155947004843ee8ec25b36127e3edSteven Ng * you may not use this file except in compliance with the License.
67079df5a3fb155947004843ee8ec25b36127e3edSteven Ng * You may obtain a copy of the License at
77079df5a3fb155947004843ee8ec25b36127e3edSteven Ng *
87079df5a3fb155947004843ee8ec25b36127e3edSteven Ng *     http://www.apache.org/licenses/LICENSE-2.0
97079df5a3fb155947004843ee8ec25b36127e3edSteven Ng *
107079df5a3fb155947004843ee8ec25b36127e3edSteven Ng * Unless required by applicable law or agreed to in writing, software
117079df5a3fb155947004843ee8ec25b36127e3edSteven Ng * distributed under the License is distributed on an "AS IS" BASIS,
127079df5a3fb155947004843ee8ec25b36127e3edSteven Ng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137079df5a3fb155947004843ee8ec25b36127e3edSteven Ng * See the License for the specific language governing permissions and
147079df5a3fb155947004843ee8ec25b36127e3edSteven Ng * limitations under the License.
157079df5a3fb155947004843ee8ec25b36127e3edSteven Ng */
167079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
177079df5a3fb155947004843ee8ec25b36127e3edSteven Ngpackage com.android.managedprovisioning.parser;
187079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
197079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
207079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
217079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE;
227079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM;
237079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER;
247079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION;
257079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
267079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM;
277079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED;
287079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCALE;
297079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCAL_TIME;
307079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION;
317079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_TIME_ZONE;
327079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_HIDDEN;
337079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PAC_URL;
347079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PASSWORD;
357079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PROXY_BYPASS;
367079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PROXY_HOST;
377079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PROXY_PORT;
387079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_SECURITY_TYPE;
397079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_SSID;
407079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.app.admin.DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC;
417079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static android.nfc.NfcAdapter.ACTION_NDEF_DISCOVERED;
427079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static com.android.internal.util.Preconditions.checkNotNull;
437079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport static java.nio.charset.StandardCharsets.UTF_8;
447079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
457079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport android.content.ComponentName;
467079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport android.content.Context;
477079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport android.content.Intent;
487079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport android.nfc.NdefMessage;
497079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport android.nfc.NdefRecord;
507079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport android.nfc.NfcAdapter;
517079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport android.os.Parcelable;
527079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport android.os.PersistableBundle;
537079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport android.support.annotation.Nullable;
547079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport android.support.annotation.VisibleForTesting;
5590f58ca887207a527c80d7e9ccea97e205c960d4Victor Changimport com.android.managedprovisioning.common.ManagedProvisioningSharedPreferences;
56f7a9eea8fe577f2f5edbbe6e73891a54351286c6Benjamin Franzimport com.android.managedprovisioning.common.ProvisionLogger;
577079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport com.android.managedprovisioning.common.IllegalProvisioningArgumentException;
58d2aa11e5484f3e56cea4ac328b2a0a58c28d4047Nicolas Prevotimport com.android.managedprovisioning.common.StoreUtils;
597079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport com.android.managedprovisioning.common.Utils;
607079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport com.android.managedprovisioning.model.PackageDownloadInfo;
617079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport com.android.managedprovisioning.model.ProvisioningParams;
627079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport com.android.managedprovisioning.model.WifiInfo;
637079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport java.io.IOException;
647079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport java.io.StringReader;
657079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport java.util.IllformedLocaleException;
667079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport java.util.Properties;
677079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
687079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
697079df5a3fb155947004843ee8ec25b36127e3edSteven Ng/**
707079df5a3fb155947004843ee8ec25b36127e3edSteven Ng * A parser which parses provisioning data from intent which stores in {@link Properties}.
717079df5a3fb155947004843ee8ec25b36127e3edSteven Ng *
727079df5a3fb155947004843ee8ec25b36127e3edSteven Ng * <p>It is used to parse an intent contains the extra {@link NfcAdapter.EXTRA_NDEF_MESSAGES}, which
737079df5a3fb155947004843ee8ec25b36127e3edSteven Ng * indicates that provisioning was started via Nfc bump. This extra contains an NDEF message, which
747079df5a3fb155947004843ee8ec25b36127e3edSteven Ng * contains an NfcRecord with mime type {@link MIME_TYPE_PROVISIONING_NFC}. This record stores a
757079df5a3fb155947004843ee8ec25b36127e3edSteven Ng * serialized properties object, which contains the serialized extras described in the next option.
767079df5a3fb155947004843ee8ec25b36127e3edSteven Ng * A typical use case would be a programmer application that sends an Nfc bump to start Nfc
777079df5a3fb155947004843ee8ec25b36127e3edSteven Ng * provisioning from a programmer device.
787079df5a3fb155947004843ee8ec25b36127e3edSteven Ng */
797079df5a3fb155947004843ee8ec25b36127e3edSteven Ng@VisibleForTesting
807079df5a3fb155947004843ee8ec25b36127e3edSteven Ngpublic class PropertiesProvisioningDataParser implements ProvisioningDataParser {
817079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
827079df5a3fb155947004843ee8ec25b36127e3edSteven Ng    private final Utils mUtils;
8390f58ca887207a527c80d7e9ccea97e205c960d4Victor Chang    private final Context mContext;
8490f58ca887207a527c80d7e9ccea97e205c960d4Victor Chang    private final ManagedProvisioningSharedPreferences mSharedPreferences;
857079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
8690f58ca887207a527c80d7e9ccea97e205c960d4Victor Chang    PropertiesProvisioningDataParser(Context context, Utils utils) {
8790f58ca887207a527c80d7e9ccea97e205c960d4Victor Chang        this(context, utils, new ManagedProvisioningSharedPreferences(context));
8890f58ca887207a527c80d7e9ccea97e205c960d4Victor Chang    }
8990f58ca887207a527c80d7e9ccea97e205c960d4Victor Chang
9090f58ca887207a527c80d7e9ccea97e205c960d4Victor Chang    @VisibleForTesting
9190f58ca887207a527c80d7e9ccea97e205c960d4Victor Chang    PropertiesProvisioningDataParser(Context context, Utils utils,
9290f58ca887207a527c80d7e9ccea97e205c960d4Victor Chang            ManagedProvisioningSharedPreferences sharedPreferences) {
9390f58ca887207a527c80d7e9ccea97e205c960d4Victor Chang        mContext = checkNotNull(context);
947079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        mUtils = checkNotNull(utils);
9590f58ca887207a527c80d7e9ccea97e205c960d4Victor Chang        mSharedPreferences = checkNotNull(sharedPreferences);
967079df5a3fb155947004843ee8ec25b36127e3edSteven Ng    }
977079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
9890f58ca887207a527c80d7e9ccea97e205c960d4Victor Chang    public ProvisioningParams parse(Intent nfcIntent)
997079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            throws IllegalProvisioningArgumentException {
1007079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        if (!ACTION_NDEF_DISCOVERED.equals(nfcIntent.getAction())) {
1017079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            throw new IllegalProvisioningArgumentException(
1027079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                    "Only NFC action is supported in this parser.");
1037079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        }
1047079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
1057079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        ProvisionLogger.logi("Processing Nfc Payload.");
1067079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        NdefRecord firstRecord = getFirstNdefRecord(nfcIntent);
1077079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        if (firstRecord != null) {
1087079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            try {
1097079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                Properties props = new Properties();
1107079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                props.load(new StringReader(new String(firstRecord.getPayload(), UTF_8)));
1117079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
1127079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                // For parsing non-string parameters.
1137079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                String s = null;
1147079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
1157079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                ProvisioningParams.Builder builder = ProvisioningParams.Builder.builder()
11690f58ca887207a527c80d7e9ccea97e205c960d4Victor Chang                        .setProvisioningId(mSharedPreferences.incrementAndGetProvisioningId())
1177079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                        .setStartedByTrustedSource(true)
1187079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                        .setProvisioningAction(mUtils.mapIntentToDpmAction(nfcIntent))
1197079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                        .setDeviceAdminPackageName(props.getProperty(
1207079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                                EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME));
1217079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                if ((s = props.getProperty(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME))
1227079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                        != null) {
1237079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                    builder.setDeviceAdminComponentName(ComponentName.unflattenFromString(s));
1247079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                }
1257079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
1267079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                // Parse time zone, locale and local time.
1277079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                builder.setTimeZone(props.getProperty(EXTRA_PROVISIONING_TIME_ZONE))
128d2aa11e5484f3e56cea4ac328b2a0a58c28d4047Nicolas Prevot                        .setLocale(StoreUtils.stringToLocale(
1297079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                                props.getProperty(EXTRA_PROVISIONING_LOCALE)));
1307079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                if ((s = props.getProperty(EXTRA_PROVISIONING_LOCAL_TIME)) != null) {
1317079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                    builder.setLocalTime(Long.parseLong(s));
1327079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                }
1337079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
1347079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                // Parse WiFi configuration.
1357079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                builder.setWifiInfo(parseWifiInfoFromProperties(props))
1367079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                        // Parse device admin package download info.
1377079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                        .setDeviceAdminDownloadInfo(parsePackageDownloadInfoFromProperties(props))
1387079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                        // Parse EMM customized key-value pairs.
1397079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                        // Note: EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE property contains a
1407079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                        // Properties object serialized into String. See Properties.store() and
1417079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                        // Properties.load() for more details. The property value is optional.
1427079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                        .setAdminExtrasBundle(deserializeExtrasBundle(props,
1437079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                                EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE));
1447079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                if ((s = props.getProperty(EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED))
1457079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                        != null) {
1467079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                    builder.setLeaveAllSystemAppsEnabled(Boolean.parseBoolean(s));
1477079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                }
1487079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                if ((s = props.getProperty(EXTRA_PROVISIONING_SKIP_ENCRYPTION)) != null) {
1497079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                    builder.setSkipEncryption(Boolean.parseBoolean(s));
1507079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                }
1517079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                ProvisionLogger.logi("End processing Nfc Payload.");
1527079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                return builder.build();
1537079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            } catch (IOException e) {
1547079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                throw new IllegalProvisioningArgumentException("Couldn't load payload", e);
1557079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            } catch (NumberFormatException e) {
1567079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                throw new IllegalProvisioningArgumentException("Incorrect numberformat.", e);
1577079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            } catch (IllformedLocaleException e) {
1587079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                throw new IllegalProvisioningArgumentException("Invalid locale.", e);
1597079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            } catch (IllegalArgumentException e) {
1607079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                throw new IllegalProvisioningArgumentException("Invalid parameter found!", e);
1617079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            } catch (NullPointerException e) {
1627079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                throw new IllegalProvisioningArgumentException(
1637079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                        "Compulsory parameter not found!", e);
1647079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            }
1657079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        }
1667079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        throw new IllegalProvisioningArgumentException(
1677079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                "Intent does not contain NfcRecord with the correct MIME type.");
1687079df5a3fb155947004843ee8ec25b36127e3edSteven Ng    }
1697079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
1707079df5a3fb155947004843ee8ec25b36127e3edSteven Ng    /**
1717079df5a3fb155947004843ee8ec25b36127e3edSteven Ng     * Parses Wifi configuration from an {@link Properties} and returns the result in
1727079df5a3fb155947004843ee8ec25b36127e3edSteven Ng     * {@link WifiInfo}.
1737079df5a3fb155947004843ee8ec25b36127e3edSteven Ng     */
1747079df5a3fb155947004843ee8ec25b36127e3edSteven Ng    @Nullable
1757079df5a3fb155947004843ee8ec25b36127e3edSteven Ng    private WifiInfo parseWifiInfoFromProperties(Properties props) {
1767079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        if (props.getProperty(EXTRA_PROVISIONING_WIFI_SSID) == null) {
1777079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            return null;
1787079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        }
1797079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        WifiInfo.Builder builder = WifiInfo.Builder.builder()
1807079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                .setSsid(props.getProperty(EXTRA_PROVISIONING_WIFI_SSID))
1817079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                .setSecurityType(props.getProperty(EXTRA_PROVISIONING_WIFI_SECURITY_TYPE))
1827079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                .setPassword(props.getProperty(EXTRA_PROVISIONING_WIFI_PASSWORD))
1837079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                .setProxyHost(props.getProperty(EXTRA_PROVISIONING_WIFI_PROXY_HOST))
1847079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                .setProxyBypassHosts(props.getProperty(EXTRA_PROVISIONING_WIFI_PROXY_BYPASS))
1857079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                .setPacUrl(props.getProperty(EXTRA_PROVISIONING_WIFI_PAC_URL));
1867079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        // For parsing non-string parameters.
1877079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        String s = null;
1887079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        if ((s = props.getProperty(EXTRA_PROVISIONING_WIFI_PROXY_PORT)) != null) {
1897079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            builder.setProxyPort(Integer.parseInt(s));
1907079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        }
1917079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        if ((s = props.getProperty(EXTRA_PROVISIONING_WIFI_HIDDEN)) != null) {
1927079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            builder.setHidden(Boolean.parseBoolean(s));
1937079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        }
1947079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
1957079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        return builder.build();
1967079df5a3fb155947004843ee8ec25b36127e3edSteven Ng    }
1977079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
1987079df5a3fb155947004843ee8ec25b36127e3edSteven Ng    /**
1997079df5a3fb155947004843ee8ec25b36127e3edSteven Ng     * Parses device admin package download info from an {@link Properties} and returns the result
2007079df5a3fb155947004843ee8ec25b36127e3edSteven Ng     * in {@link PackageDownloadInfo}.
2017079df5a3fb155947004843ee8ec25b36127e3edSteven Ng     */
2027079df5a3fb155947004843ee8ec25b36127e3edSteven Ng    @Nullable
2037079df5a3fb155947004843ee8ec25b36127e3edSteven Ng    private PackageDownloadInfo parsePackageDownloadInfoFromProperties(Properties props) {
2047079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        if (props.getProperty(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION) == null) {
2057079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            return null;
2067079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        }
2077079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        PackageDownloadInfo.Builder builder = PackageDownloadInfo.Builder.builder()
2087079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                .setLocation(props.getProperty(
2097079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                        EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION))
2107079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                .setCookieHeader(props.getProperty(
2117079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                        EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER));
2127079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        // For parsing non-string parameters.
2137079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        String s = null;
2147079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        if ((s = props.getProperty(EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE)) != null) {
2157079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            builder.setMinVersion(Integer.parseInt(s));
2167079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        }
2177079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        if ((s = props.getProperty(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM)) != null) {
2187079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            // Still support SHA-1 for device admin package hash if we are provisioned by a Nfc
2197079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            // programmer.
2207079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            // TODO: remove once SHA-1 is fully deprecated.
221d2aa11e5484f3e56cea4ac328b2a0a58c28d4047Nicolas Prevot            builder.setPackageChecksum(StoreUtils.stringToByteArray(s))
2227079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                    .setPackageChecksumSupportsSha1(true);
2237079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        }
2247079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        if ((s = props.getProperty(EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM))
2257079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                != null) {
226d2aa11e5484f3e56cea4ac328b2a0a58c28d4047Nicolas Prevot            builder.setSignatureChecksum(StoreUtils.stringToByteArray(s));
2277079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        }
2287079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        return builder.build();
2297079df5a3fb155947004843ee8ec25b36127e3edSteven Ng    }
2307079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
2317079df5a3fb155947004843ee8ec25b36127e3edSteven Ng    /**
2327079df5a3fb155947004843ee8ec25b36127e3edSteven Ng     * Get a {@link PersistableBundle} from a String property in a Properties object.
2337079df5a3fb155947004843ee8ec25b36127e3edSteven Ng     * @param props the source of the extra
2347079df5a3fb155947004843ee8ec25b36127e3edSteven Ng     * @param extraName key into the Properties object
2357079df5a3fb155947004843ee8ec25b36127e3edSteven Ng     * @return the bundle or {@code null} if there was no property with the given name
2367079df5a3fb155947004843ee8ec25b36127e3edSteven Ng     * @throws IOException if there was an error parsing the propery
2377079df5a3fb155947004843ee8ec25b36127e3edSteven Ng     */
2387079df5a3fb155947004843ee8ec25b36127e3edSteven Ng    private PersistableBundle deserializeExtrasBundle(Properties props, String extraName)
2397079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            throws IOException {
2407079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        PersistableBundle extrasBundle = null;
2417079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        String serializedExtras = props.getProperty(extraName);
2427079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        if (serializedExtras != null) {
2437079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            Properties extrasProp = new Properties();
2447079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            extrasProp.load(new StringReader(serializedExtras));
2457079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            extrasBundle = new PersistableBundle(extrasProp.size());
2467079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            for (String propName : extrasProp.stringPropertyNames()) {
2477079df5a3fb155947004843ee8ec25b36127e3edSteven Ng                extrasBundle.putString(propName, extrasProp.getProperty(propName));
2487079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            }
2497079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        }
2507079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        return extrasBundle;
2517079df5a3fb155947004843ee8ec25b36127e3edSteven Ng    }
2527079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
2537079df5a3fb155947004843ee8ec25b36127e3edSteven Ng    /**
2547079df5a3fb155947004843ee8ec25b36127e3edSteven Ng     * @return the first {@link NdefRecord} found with a recognized MIME-type
2557079df5a3fb155947004843ee8ec25b36127e3edSteven Ng     */
2568a0cbf851f45b0df553854788a53902619af08f3Mahaver Chopra    public static NdefRecord getFirstNdefRecord(Intent nfcIntent) {
2577079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        // Only one first message with NFC_MIME_TYPE is used.
2588a0cbf851f45b0df553854788a53902619af08f3Mahaver Chopra        final Parcelable[] ndefMessages = nfcIntent.getParcelableArrayExtra(
2598a0cbf851f45b0df553854788a53902619af08f3Mahaver Chopra                NfcAdapter.EXTRA_NDEF_MESSAGES);
2608a0cbf851f45b0df553854788a53902619af08f3Mahaver Chopra        if (ndefMessages != null) {
2618a0cbf851f45b0df553854788a53902619af08f3Mahaver Chopra            for (Parcelable rawMsg : ndefMessages) {
2628a0cbf851f45b0df553854788a53902619af08f3Mahaver Chopra                NdefMessage msg = (NdefMessage) rawMsg;
2638a0cbf851f45b0df553854788a53902619af08f3Mahaver Chopra                for (NdefRecord record : msg.getRecords()) {
2648a0cbf851f45b0df553854788a53902619af08f3Mahaver Chopra                    String mimeType = new String(record.getType(), UTF_8);
2657079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
2668a0cbf851f45b0df553854788a53902619af08f3Mahaver Chopra                    if (MIME_TYPE_PROVISIONING_NFC.equals(mimeType)) {
2678a0cbf851f45b0df553854788a53902619af08f3Mahaver Chopra                        return record;
2688a0cbf851f45b0df553854788a53902619af08f3Mahaver Chopra                    }
2697079df5a3fb155947004843ee8ec25b36127e3edSteven Ng
2708a0cbf851f45b0df553854788a53902619af08f3Mahaver Chopra                    // Assume only first record of message is used.
2718a0cbf851f45b0df553854788a53902619af08f3Mahaver Chopra                    break;
2728a0cbf851f45b0df553854788a53902619af08f3Mahaver Chopra                }
2737079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            }
2747079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        }
2757079df5a3fb155947004843ee8ec25b36127e3edSteven Ng        return null;
2767079df5a3fb155947004843ee8ec25b36127e3edSteven Ng    }
2777079df5a3fb155947004843ee8ec25b36127e3edSteven Ng}
278