blob: db9b20550394607623aa621096992f1fdf91c212 [file] [log] [blame]
Sander Alewijnseed0883b2014-03-18 15:01:13 +00001/*
2 * Copyright 2014, 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
17package com.android.managedprovisioning;
18
Sander Alewijnse56f71572014-06-23 16:21:33 +010019import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_TIME_ZONE;
20import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCAL_TIME;
21import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCALE;
22import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_SSID;
23import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_HIDDEN;
24import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_SECURITY_TYPE;
25import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PASSWORD;
26import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PROXY_HOST;
27import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PROXY_PORT;
28import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PROXY_BYPASS;
29import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PAC_URL;
Sander Alewijnsef88f7092014-08-20 16:26:09 +010030import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
Nicolas Prevot0b447252015-03-09 14:59:02 +000031import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
Julia Reynoldsf3a5b3b2015-03-20 09:34:37 -040032import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE;
Nicolas Prevot0b447252015-03-09 14:59:02 +000033import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM;
Sander Alewijnse56f71572014-06-23 16:21:33 +010034import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION;
Sander Alewijnsed8dcb1f2014-07-24 15:24:50 +010035import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER;
Nicolas Prevot0b447252015-03-09 14:59:02 +000036import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
Julia Reynolds3f4eb372015-02-11 13:46:42 -050037import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM;
38import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME;
Julia Reynoldsf3a5b3b2015-03-20 09:34:37 -040039import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE;
Julia Reynolds3f4eb372015-02-11 13:46:42 -050040import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION;
41import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER;
42import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM;
Sander Alewijnsefd134872014-11-18 13:28:06 +000043import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED;
Julia Reynolds5d47b652015-02-02 06:47:25 -050044import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION;
Craig Lafayette2fe9d992015-03-24 12:42:05 -040045import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_BT_MAC_ADDRESS;
46import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_BT_UUID;
47import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_BT_DEVICE_ID;
48import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_BT_USE_PROXY;
Esteban Talaverae917d112014-08-20 14:23:53 +010049import static android.app.admin.DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC;
Craig Lafayettea58843e2015-03-27 06:54:28 -040050import static android.app.admin.DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC_V2;
Sander Alewijnse28bffd62014-06-05 10:54:26 +010051import static java.nio.charset.StandardCharsets.UTF_8;
52
Nicolas Prevot0b447252015-03-09 14:59:02 +000053import android.content.ComponentName;
54import android.content.Context;
Sander Alewijnseed0883b2014-03-18 15:01:13 +000055import android.content.Intent;
56import android.nfc.NdefMessage;
57import android.nfc.NdefRecord;
58import android.nfc.NfcAdapter;
Sander Alewijnse9aff1402014-07-18 17:15:32 +010059import android.os.Bundle;
Sander Alewijnseed0883b2014-03-18 15:01:13 +000060import android.os.Parcelable;
Sander Alewijnsef88f7092014-08-20 16:26:09 +010061import android.os.PersistableBundle;
Sander Alewijnsed7043852014-06-17 15:50:48 +010062import android.text.TextUtils;
Sander Alewijnse48fdbe02014-07-03 14:25:45 +010063import android.util.Base64;
Sander Alewijnseed0883b2014-03-18 15:01:13 +000064
Nicolas Prevot0b447252015-03-09 14:59:02 +000065import com.android.managedprovisioning.Utils.IllegalProvisioningArgumentException;
66
Sander Alewijnseed0883b2014-03-18 15:01:13 +000067import java.io.IOException;
68import java.io.StringReader;
69import java.util.Enumeration;
70import java.util.HashMap;
Narayan Kamath53ff3c02014-07-17 14:02:58 +010071import java.util.IllformedLocaleException;
Sander Alewijnse63254f42014-03-21 15:31:12 +000072import java.util.Locale;
Sander Alewijnseed0883b2014-03-18 15:01:13 +000073import java.util.Properties;
74
75/**
Sander Alewijnse8f9bd132014-09-08 12:21:26 +010076 * This class can initialize a {@link ProvisioningParams} object from an intent.
77 * A {@link ProvisioningParams} object stores various parameters for the device owner provisioning.
78 * There are two kinds of intents that can be parsed it into {@link ProvisioningParams}:
Sander Alewijnse28bffd62014-06-05 10:54:26 +010079 *
80 * <p>
Sander Alewijnse56f71572014-06-23 16:21:33 +010081 * Intent was received via Nfc.
82 * The intent contains the extra {@link NfcAdapter.EXTRA_NDEF_MESSAGES}, which indicates that
83 * provisioning was started via Nfc bump. This extra contains an NDEF message, which contains an
Esteban Talaverae917d112014-08-20 14:23:53 +010084 * NfcRecord with mime type {@link MIME_TYPE_PROVISIONING_NFC}. This record stores a serialized
Sander Alewijnse56f71572014-06-23 16:21:33 +010085 * properties object, which contains the serialized extra's described in the next option.
86 * A typical use case would be a programmer application that sends an Nfc bump to start Nfc
87 * provisioning from a programmer device.
Sander Alewijnse28bffd62014-06-05 10:54:26 +010088 *
89 * <p>
Sander Alewijnse56f71572014-06-23 16:21:33 +010090 * Intent was received directly.
Nicolas Prevot0b447252015-03-09 14:59:02 +000091 * The intent contains the extra {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME} or
Julia Reynolds3f4eb372015-02-11 13:46:42 -050092 * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME} (which is deprecated and supported for
93 * legacy reasons only), and may contain {@link #EXTRA_PROVISIONING_TIME_ZONE},
94 * {@link #EXTRA_PROVISIONING_LOCAL_TIME}, {@link #EXTRA_PROVISIONING_LOCALE}, and
95 * {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME}. A download
96 * location for the device admin may be specified in
Julia Reynoldsf3a5b3b2015-03-20 09:34:37 -040097 * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}, together with an optional
98 * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE}, an optional
99 * http cookie header {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER}, and
100 * the SHA-1 sum of the target file {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM}. A
101 * download location for the device initializer may be specified in
102 * {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}, together with an
103 * optional (@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE}, an optional http
104 * cookie header {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER} , and
105 * the SHA-1 sum of the target file {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM}.
Julia Reynolds3f4eb372015-02-11 13:46:42 -0500106 * Additional information to send through to the device initializer and admin may be specified in
Sander Alewijnsef88f7092014-08-20 16:26:09 +0100107 * {@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}.
Julia Reynolds3f4eb372015-02-11 13:46:42 -0500108 * The optional boolean {@link #EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED} indicates whether
109 * system apps should not be disabled. The optional boolean
110 * {@link #EXTRA_PROVISIONING_SKIP_ENCRYPTION} specifies whether the device should be encrypted.
Sander Alewijnsed8dcb1f2014-07-24 15:24:50 +0100111 * Furthermore a wifi network may be specified in {@link #EXTRA_PROVISIONING_WIFI_SSID}, and if
112 * applicable {@link #EXTRA_PROVISIONING_WIFI_HIDDEN},
113 * {@link #EXTRA_PROVISIONING_WIFI_SECURITY_TYPE}, {@link #EXTRA_PROVISIONING_WIFI_PASSWORD},
114 * {@link #EXTRA_PROVISIONING_WIFI_PROXY_HOST}, {@link #EXTRA_PROVISIONING_WIFI_PROXY_PORT},
Craig Lafayette2fe9d992015-03-24 12:42:05 -0400115 * {@link #EXTRA_PROVISIONING_WIFI_PROXY_BYPASS}. The optional fields
116 * {@link #EXTRA_PROVISIONING_BT_MAC_ADDRESS}, {@link #EXTRA_PROVISIONING_BT_UUID}, and
117 * {@link #EXTRA_PROVISIONING_BT_DEVICE_ID} define how to connect to a remote device over Bluetooth.
118 * The boolean {@link #EXTRA_PROVISIONING_BT_USE_PROXY}, if true, will allow this device to proxy
119 * network activity over the defined Bluetooth connection during initial setup.
Sander Alewijnse56f71572014-06-23 16:21:33 +0100120 * A typical use case would be the {@link BootReminder} sending the intent after device encryption
121 * and reboot.
Sander Alewijnse9aff1402014-07-18 17:15:32 +0100122 *
123 * <p>
Sander Alewijnse8f9bd132014-09-08 12:21:26 +0100124 * Furthermore this class can construct the bundle of extras for the second kind of intent given a
125 * {@link ProvisioningParams}, and it keeps track of the types of the extras in the
126 * DEVICE_OWNER_x_EXTRAS, with x the appropriate type.
Sander Alewijnseed0883b2014-03-18 15:01:13 +0000127 */
Sander Alewijnse28bffd62014-06-05 10:54:26 +0100128public class MessageParser {
Sander Alewijnse8f9bd132014-09-08 12:21:26 +0100129 private static final String EXTRA_PROVISIONING_STARTED_BY_NFC =
130 "com.android.managedprovisioning.extra.started_by_nfc";
131
Sander Alewijnse9aff1402014-07-18 17:15:32 +0100132 protected static final String[] DEVICE_OWNER_STRING_EXTRAS = {
133 EXTRA_PROVISIONING_TIME_ZONE,
134 EXTRA_PROVISIONING_LOCALE,
135 EXTRA_PROVISIONING_WIFI_SSID,
136 EXTRA_PROVISIONING_WIFI_SECURITY_TYPE,
137 EXTRA_PROVISIONING_WIFI_PASSWORD,
138 EXTRA_PROVISIONING_WIFI_PROXY_HOST,
139 EXTRA_PROVISIONING_WIFI_PROXY_BYPASS,
140 EXTRA_PROVISIONING_WIFI_PAC_URL,
Nicolas Prevot668d65f2015-03-10 17:58:15 +0000141 EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,
Sander Alewijnse9aff1402014-07-18 17:15:32 +0100142 EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION,
Sander Alewijnsed8dcb1f2014-07-24 15:24:50 +0100143 EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER,
Julia Reynolds3f4eb372015-02-11 13:46:42 -0500144 EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM,
145 EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION,
146 EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER,
Craig Lafayette2fe9d992015-03-24 12:42:05 -0400147 EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM,
148 EXTRA_PROVISIONING_BT_MAC_ADDRESS,
149 EXTRA_PROVISIONING_BT_UUID,
150 EXTRA_PROVISIONING_BT_DEVICE_ID
Sander Alewijnse9aff1402014-07-18 17:15:32 +0100151 };
152
153 protected static final String[] DEVICE_OWNER_LONG_EXTRAS = {
154 EXTRA_PROVISIONING_LOCAL_TIME
155 };
156
157 protected static final String[] DEVICE_OWNER_INT_EXTRAS = {
Julia Reynoldsf3a5b3b2015-03-20 09:34:37 -0400158 EXTRA_PROVISIONING_WIFI_PROXY_PORT,
159 EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE,
160 EXTRA_PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE
Sander Alewijnse9aff1402014-07-18 17:15:32 +0100161 };
162
163 protected static final String[] DEVICE_OWNER_BOOLEAN_EXTRAS = {
Sander Alewijnse8f9bd132014-09-08 12:21:26 +0100164 EXTRA_PROVISIONING_WIFI_HIDDEN,
Sander Alewijnsefd134872014-11-18 13:28:06 +0000165 EXTRA_PROVISIONING_STARTED_BY_NFC,
Julia Reynolds5d47b652015-02-02 06:47:25 -0500166 EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED,
Craig Lafayette2fe9d992015-03-24 12:42:05 -0400167 EXTRA_PROVISIONING_SKIP_ENCRYPTION,
168 EXTRA_PROVISIONING_BT_USE_PROXY
Sander Alewijnse9aff1402014-07-18 17:15:32 +0100169 };
170
Sander Alewijnsef88f7092014-08-20 16:26:09 +0100171 protected static final String[] DEVICE_OWNER_PERSISTABLE_BUNDLE_EXTRAS = {
172 EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE
173 };
174
Nicolas Prevot0b447252015-03-09 14:59:02 +0000175 protected static final String[] DEVICE_OWNER_COMPONENT_NAME_EXTRAS = {
Julia Reynolds3f4eb372015-02-11 13:46:42 -0500176 EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
177 EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME
Nicolas Prevot0b447252015-03-09 14:59:02 +0000178 };
179
Sander Alewijnse9aff1402014-07-18 17:15:32 +0100180 public void addProvisioningParamsToBundle(Bundle bundle, ProvisioningParams params) {
181 bundle.putString(EXTRA_PROVISIONING_TIME_ZONE, params.mTimeZone);
182 bundle.putString(EXTRA_PROVISIONING_LOCALE, params.getLocaleAsString());
183 bundle.putString(EXTRA_PROVISIONING_WIFI_SSID, params.mWifiSsid);
184 bundle.putString(EXTRA_PROVISIONING_WIFI_SECURITY_TYPE, params.mWifiSecurityType);
185 bundle.putString(EXTRA_PROVISIONING_WIFI_PASSWORD, params.mWifiPassword);
186 bundle.putString(EXTRA_PROVISIONING_WIFI_PROXY_HOST, params.mWifiProxyHost);
187 bundle.putString(EXTRA_PROVISIONING_WIFI_PROXY_BYPASS, params.mWifiProxyBypassHosts);
188 bundle.putString(EXTRA_PROVISIONING_WIFI_PAC_URL, params.mWifiPacUrl);
Nicolas Prevot668d65f2015-03-10 17:58:15 +0000189 bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,
190 params.mDeviceAdminPackageName);
Nicolas Prevot0b447252015-03-09 14:59:02 +0000191 bundle.putParcelable(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
192 params.mDeviceAdminComponentName);
Julia Reynoldsf3a5b3b2015-03-20 09:34:37 -0400193 bundle.putInt(EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE,
194 params.mDeviceAdminMinVersion);
Sander Alewijnse9aff1402014-07-18 17:15:32 +0100195 bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION,
196 params.mDeviceAdminPackageDownloadLocation);
Sander Alewijnsed8dcb1f2014-07-24 15:24:50 +0100197 bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER,
198 params.mDeviceAdminPackageDownloadCookieHeader);
Sander Alewijnse9aff1402014-07-18 17:15:32 +0100199 bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM,
200 params.getDeviceAdminPackageChecksumAsString());
Julia Reynolds3f4eb372015-02-11 13:46:42 -0500201 bundle.putParcelable(EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME,
202 params.mDeviceInitializerComponentName);
Julia Reynoldsf3a5b3b2015-03-20 09:34:37 -0400203 bundle.putInt(EXTRA_PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE,
204 params.mDeviceInitializerMinVersion);
Julia Reynolds3f4eb372015-02-11 13:46:42 -0500205 bundle.putString(EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION,
206 params.mDeviceInitializerPackageDownloadLocation);
207 bundle.putString(EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER,
208 params.mDeviceInitializerPackageDownloadCookieHeader);
209 bundle.putString(EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM,
210 params.getDeviceInitializerPackageChecksumAsString());
Sander Alewijnse9aff1402014-07-18 17:15:32 +0100211
212 bundle.putLong(EXTRA_PROVISIONING_LOCAL_TIME, params.mLocalTime);
213
214 bundle.putInt(EXTRA_PROVISIONING_WIFI_PROXY_PORT, params.mWifiProxyPort);
215
216 bundle.putBoolean(EXTRA_PROVISIONING_WIFI_HIDDEN, params.mWifiHidden);
Sander Alewijnse8f9bd132014-09-08 12:21:26 +0100217 bundle.putBoolean(EXTRA_PROVISIONING_STARTED_BY_NFC, params.mStartedByNfc);
Sander Alewijnsefd134872014-11-18 13:28:06 +0000218 bundle.putBoolean(EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED,
219 params.mLeaveAllSystemAppsEnabled);
Sander Alewijnsef88f7092014-08-20 16:26:09 +0100220
221 bundle.putParcelable(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, params.mAdminExtrasBundle);
Julia Reynolds5d47b652015-02-02 06:47:25 -0500222 bundle.putBoolean(EXTRA_PROVISIONING_SKIP_ENCRYPTION, params.mSkipEncryption);
Craig Lafayette2fe9d992015-03-24 12:42:05 -0400223
224 // Bluetooth parameters
225 bundle.putString(EXTRA_PROVISIONING_BT_MAC_ADDRESS, params.mBluetoothMac);
226 bundle.putString(EXTRA_PROVISIONING_BT_UUID, params.mBluetoothUuid);
227 bundle.putString(EXTRA_PROVISIONING_BT_DEVICE_ID, params.mBluetoothDeviceIdentifier);
228 bundle.putBoolean(EXTRA_PROVISIONING_BT_USE_PROXY, params.mUseBluetoothProxy);
Sander Alewijnse9aff1402014-07-18 17:15:32 +0100229 }
230
Nicolas Prevot668d65f2015-03-10 17:58:15 +0000231 public ProvisioningParams parseIntent(Intent intent)
Nicolas Prevot0b447252015-03-09 14:59:02 +0000232 throws IllegalProvisioningArgumentException {
Sander Alewijnse28bffd62014-06-05 10:54:26 +0100233 ProvisionLogger.logi("Processing intent.");
234 if (intent.hasExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)) {
Nicolas Prevot668d65f2015-03-10 17:58:15 +0000235 return parseNfcIntent(intent);
Sander Alewijnseed0883b2014-03-18 15:01:13 +0000236 } else {
Nicolas Prevot668d65f2015-03-10 17:58:15 +0000237 return parseNonNfcIntent(intent);
Sander Alewijnseed0883b2014-03-18 15:01:13 +0000238 }
Sander Alewijnseed0883b2014-03-18 15:01:13 +0000239 }
240
Nicolas Prevot668d65f2015-03-10 17:58:15 +0000241 public ProvisioningParams parseNfcIntent(Intent nfcIntent)
Nicolas Prevot0b447252015-03-09 14:59:02 +0000242 throws IllegalProvisioningArgumentException {
Sander Alewijnse28bffd62014-06-05 10:54:26 +0100243 ProvisionLogger.logi("Processing Nfc Payload.");
244 // Only one first message with NFC_MIME_TYPE is used.
245 for (Parcelable rawMsg : nfcIntent
246 .getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)) {
247 NdefMessage msg = (NdefMessage) rawMsg;
248
249 // Assume only first record of message is used.
250 NdefRecord firstRecord = msg.getRecords()[0];
251 String mimeType = new String(firstRecord.getType(), UTF_8);
252
Craig Lafayettea58843e2015-03-27 06:54:28 -0400253 if (MIME_TYPE_PROVISIONING_NFC.equals(mimeType) ||
254 MIME_TYPE_PROVISIONING_NFC_V2.equals(mimeType)) {
Sander Alewijnse8f9bd132014-09-08 12:21:26 +0100255 ProvisioningParams params = parseProperties(new String(firstRecord.getPayload()
Nicolas Prevot668d65f2015-03-10 17:58:15 +0000256 , UTF_8));
Sander Alewijnse8f9bd132014-09-08 12:21:26 +0100257 params.mStartedByNfc = true;
258 return params;
Sander Alewijnse28bffd62014-06-05 10:54:26 +0100259 }
260 }
Nicolas Prevot0b447252015-03-09 14:59:02 +0000261 throw new IllegalProvisioningArgumentException(
262 "Intent does not contain NfcRecord with the correct MIME type.");
Sander Alewijnse28bffd62014-06-05 10:54:26 +0100263 }
264
Andrei Kapishnikovd75aebb2015-02-02 11:22:19 -0500265 // Note: EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE property contains a Properties object
266 // serialized into String. See Properties.store() and Properties.load() for more details.
267 // The property value is optional.
Nicolas Prevot668d65f2015-03-10 17:58:15 +0000268 private ProvisioningParams parseProperties(String data)
Nicolas Prevot0b447252015-03-09 14:59:02 +0000269 throws IllegalProvisioningArgumentException {
Sander Alewijnseed0883b2014-03-18 15:01:13 +0000270 ProvisioningParams params = new ProvisioningParams();
271 try {
272 Properties props = new Properties();
273 props.load(new StringReader(data));
274
Sander Alewijnse56f71572014-06-23 16:21:33 +0100275 String s; // Used for parsing non-Strings.
Sander Alewijnse56f71572014-06-23 16:21:33 +0100276 params.mTimeZone
277 = props.getProperty(EXTRA_PROVISIONING_TIME_ZONE);
Sander Alewijnse56f71572014-06-23 16:21:33 +0100278 if ((s = props.getProperty(EXTRA_PROVISIONING_LOCALE)) != null) {
279 params.mLocale = stringToLocale(s);
280 }
281 params.mWifiSsid = props.getProperty(EXTRA_PROVISIONING_WIFI_SSID);
Sander Alewijnse56f71572014-06-23 16:21:33 +0100282 params.mWifiSecurityType = props.getProperty(EXTRA_PROVISIONING_WIFI_SECURITY_TYPE);
283 params.mWifiPassword = props.getProperty(EXTRA_PROVISIONING_WIFI_PASSWORD);
284 params.mWifiProxyHost = props.getProperty(EXTRA_PROVISIONING_WIFI_PROXY_HOST);
Sander Alewijnse56f71572014-06-23 16:21:33 +0100285 params.mWifiProxyBypassHosts = props.getProperty(EXTRA_PROVISIONING_WIFI_PROXY_BYPASS);
286 params.mWifiPacUrl = props.getProperty(EXTRA_PROVISIONING_WIFI_PAC_URL);
Nicolas Prevot668d65f2015-03-10 17:58:15 +0000287 params.mDeviceAdminPackageName
288 = props.getProperty(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME);
289 String componentNameString = props.getProperty(
290 EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME);
291 if (componentNameString != null) {
292 params.mDeviceAdminComponentName = ComponentName.unflattenFromString(
293 componentNameString);
294 }
Julia Reynoldsf3a5b3b2015-03-20 09:34:37 -0400295 if ((s = props.getProperty(
296 EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE)) != null) {
297 params.mDeviceAdminMinVersion = Integer.parseInt(s);
298 } else {
299 params.mDeviceAdminMinVersion = ProvisioningParams.DEFAULT_MINIMUM_VERSION;
300 }
Sander Alewijnse56f71572014-06-23 16:21:33 +0100301 params.mDeviceAdminPackageDownloadLocation
302 = props.getProperty(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION);
Sander Alewijnsed8dcb1f2014-07-24 15:24:50 +0100303 params.mDeviceAdminPackageDownloadCookieHeader = props.getProperty(
304 EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER);
Sander Alewijnse56f71572014-06-23 16:21:33 +0100305 if ((s = props.getProperty(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM)) != null) {
306 params.mDeviceAdminPackageChecksum = stringToByteArray(s);
Sander Alewijnseed0883b2014-03-18 15:01:13 +0000307 }
Julia Reynolds3f4eb372015-02-11 13:46:42 -0500308 String name = props.getProperty(
309 EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME);
310 if (name != null) {
311 params.mDeviceInitializerComponentName = ComponentName.unflattenFromString(name);
312 }
Julia Reynoldsf3a5b3b2015-03-20 09:34:37 -0400313 if ((s = props.getProperty(
314 EXTRA_PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE)) != null) {
315 params.mDeviceInitializerMinVersion = Integer.parseInt(s);
316 } else {
317 params.mDeviceInitializerMinVersion = ProvisioningParams.DEFAULT_MINIMUM_VERSION;
318 }
Julia Reynolds3f4eb372015-02-11 13:46:42 -0500319 params.mDeviceInitializerPackageDownloadLocation = props.getProperty(
320 EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION);
321 params.mDeviceInitializerPackageDownloadCookieHeader = props.getProperty(
322 EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER);
323 if ((s = props.getProperty(
324 EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM)) != null) {
325 params.mDeviceInitializerPackageChecksum = stringToByteArray(s);
326 }
Sander Alewijnse885c3492014-04-24 17:30:31 +0100327
Sander Alewijnse9aff1402014-07-18 17:15:32 +0100328 if ((s = props.getProperty(EXTRA_PROVISIONING_LOCAL_TIME)) != null) {
329 params.mLocalTime = Long.parseLong(s);
330 }
331
332 if ((s = props.getProperty(EXTRA_PROVISIONING_WIFI_PROXY_PORT)) != null) {
333 params.mWifiProxyPort = Integer.parseInt(s);
334 }
335
336 if ((s = props.getProperty(EXTRA_PROVISIONING_WIFI_HIDDEN)) != null) {
337 params.mWifiHidden = Boolean.parseBoolean(s);
338 }
339
Sander Alewijnsefd134872014-11-18 13:28:06 +0000340 if ((s = props.getProperty(EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED)) != null) {
341 params.mLeaveAllSystemAppsEnabled = Boolean.parseBoolean(s);
342 }
Julia Reynolds5d47b652015-02-02 06:47:25 -0500343 if ((s = props.getProperty(EXTRA_PROVISIONING_SKIP_ENCRYPTION)) != null) {
344 params.mSkipEncryption = Boolean.parseBoolean(s);
345 }
Sander Alewijnsefd134872014-11-18 13:28:06 +0000346
Craig Lafayette2fe9d992015-03-24 12:42:05 -0400347 params.mBluetoothMac = props.getProperty(EXTRA_PROVISIONING_BT_MAC_ADDRESS);
348 params.mBluetoothUuid = props.getProperty(EXTRA_PROVISIONING_BT_UUID);
349 params.mBluetoothDeviceIdentifier = props.getProperty(EXTRA_PROVISIONING_BT_DEVICE_ID);
350 if ((s = props.getProperty(EXTRA_PROVISIONING_BT_USE_PROXY)) != null) {
351 params.mUseBluetoothProxy = Boolean.parseBoolean(s);
352 }
353
Andrei Kapishnikovd75aebb2015-02-02 11:22:19 -0500354 deserializeAdminExtrasBundle(params, props);
355
Sander Alewijnse885c3492014-04-24 17:30:31 +0100356 checkValidityOfProvisioningParams(params);
Sander Alewijnseed0883b2014-03-18 15:01:13 +0000357 return params;
358 } catch (IOException e) {
Nicolas Prevot0b447252015-03-09 14:59:02 +0000359 throw new Utils.IllegalProvisioningArgumentException("Couldn't load payload", e);
Sander Alewijnseed0883b2014-03-18 15:01:13 +0000360 } catch (NumberFormatException e) {
Nicolas Prevot0b447252015-03-09 14:59:02 +0000361 throw new Utils.IllegalProvisioningArgumentException("Incorrect numberformat.", e);
Narayan Kamath53ff3c02014-07-17 14:02:58 +0100362 } catch (IllformedLocaleException e) {
Nicolas Prevot0b447252015-03-09 14:59:02 +0000363 throw new Utils.IllegalProvisioningArgumentException("Invalid locale.", e);
Sander Alewijnseed0883b2014-03-18 15:01:13 +0000364 }
365 }
366
Andrei Kapishnikovd75aebb2015-02-02 11:22:19 -0500367 private void deserializeAdminExtrasBundle(ProvisioningParams params, Properties props)
368 throws IOException {
369 String serializedExtras = props.getProperty(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE);
370 if (serializedExtras != null) {
371 Properties extrasProp = new Properties();
372 extrasProp.load(new StringReader(serializedExtras));
373 PersistableBundle extrasBundle = new PersistableBundle(extrasProp.size());
374 for (String propName : extrasProp.stringPropertyNames()) {
375 extrasBundle.putString(propName, extrasProp.getProperty(propName));
376 }
377 params.mAdminExtrasBundle = extrasBundle;
378 }
379 }
380
Nicolas Prevot668d65f2015-03-10 17:58:15 +0000381 public ProvisioningParams parseNonNfcIntent(Intent intent)
Nicolas Prevot0b447252015-03-09 14:59:02 +0000382 throws IllegalProvisioningArgumentException {
Sander Alewijnse56f71572014-06-23 16:21:33 +0100383 ProvisionLogger.logi("Processing intent.");
384 ProvisioningParams params = new ProvisioningParams();
Sander Alewijnseed0883b2014-03-18 15:01:13 +0000385
Sander Alewijnse56f71572014-06-23 16:21:33 +0100386 params.mTimeZone = intent.getStringExtra(EXTRA_PROVISIONING_TIME_ZONE);
Sander Alewijnse56f71572014-06-23 16:21:33 +0100387 String localeString = intent.getStringExtra(EXTRA_PROVISIONING_LOCALE);
388 if (localeString != null) {
389 params.mLocale = stringToLocale(localeString);
Sander Alewijnseed0883b2014-03-18 15:01:13 +0000390 }
Sander Alewijnse56f71572014-06-23 16:21:33 +0100391 params.mWifiSsid = intent.getStringExtra(EXTRA_PROVISIONING_WIFI_SSID);
Sander Alewijnse56f71572014-06-23 16:21:33 +0100392 params.mWifiSecurityType = intent.getStringExtra(EXTRA_PROVISIONING_WIFI_SECURITY_TYPE);
393 params.mWifiPassword = intent.getStringExtra(EXTRA_PROVISIONING_WIFI_PASSWORD);
394 params.mWifiProxyHost = intent.getStringExtra(EXTRA_PROVISIONING_WIFI_PROXY_HOST);
Sander Alewijnse56f71572014-06-23 16:21:33 +0100395 params.mWifiProxyBypassHosts = intent.getStringExtra(EXTRA_PROVISIONING_WIFI_PROXY_BYPASS);
396 params.mWifiPacUrl = intent.getStringExtra(EXTRA_PROVISIONING_WIFI_PAC_URL);
Nicolas Prevot668d65f2015-03-10 17:58:15 +0000397 params.mDeviceAdminComponentName = (ComponentName) intent.getParcelableExtra(
398 EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME);
399 params.mDeviceAdminPackageName
400 = intent.getStringExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME);
Julia Reynoldsf3a5b3b2015-03-20 09:34:37 -0400401 params.mDeviceAdminMinVersion = intent.getIntExtra(
402 EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE,
403 ProvisioningParams.DEFAULT_MINIMUM_VERSION);
Sander Alewijnse56f71572014-06-23 16:21:33 +0100404 params.mDeviceAdminPackageDownloadLocation
405 = intent.getStringExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION);
Sander Alewijnsed8dcb1f2014-07-24 15:24:50 +0100406 params.mDeviceAdminPackageDownloadCookieHeader = intent.getStringExtra(
407 EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER);
Sander Alewijnse56f71572014-06-23 16:21:33 +0100408 String hashString = intent.getStringExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM);
409 if (hashString != null) {
410 params.mDeviceAdminPackageChecksum = stringToByteArray(hashString);
Sander Alewijnseed0883b2014-03-18 15:01:13 +0000411 }
Rubin Xuba6e25d2015-03-23 17:26:21 +0000412 params.mDeviceInitializerComponentName = (ComponentName) intent.getParcelableExtra(
Julia Reynolds3f4eb372015-02-11 13:46:42 -0500413 EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME);
Julia Reynoldsf3a5b3b2015-03-20 09:34:37 -0400414 params.mDeviceInitializerMinVersion = intent.getIntExtra(
415 EXTRA_PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE,
416 ProvisioningParams.DEFAULT_MINIMUM_VERSION);
Julia Reynolds3f4eb372015-02-11 13:46:42 -0500417 params.mDeviceInitializerPackageDownloadLocation = intent.getStringExtra(
418 EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION);
419 params.mDeviceInitializerPackageDownloadCookieHeader = intent.getStringExtra(
420 EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER);
421 hashString = intent.getStringExtra(EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM);
422 if (hashString != null) {
423 params.mDeviceInitializerPackageChecksum = stringToByteArray(hashString);
424 }
Sander Alewijnse56f71572014-06-23 16:21:33 +0100425
Sander Alewijnse9aff1402014-07-18 17:15:32 +0100426 params.mLocalTime = intent.getLongExtra(EXTRA_PROVISIONING_LOCAL_TIME,
427 ProvisioningParams.DEFAULT_LOCAL_TIME);
428
429 params.mWifiProxyPort = intent.getIntExtra(EXTRA_PROVISIONING_WIFI_PROXY_PORT,
430 ProvisioningParams.DEFAULT_WIFI_PROXY_PORT);
431
432 params.mWifiHidden = intent.getBooleanExtra(EXTRA_PROVISIONING_WIFI_HIDDEN,
433 ProvisioningParams.DEFAULT_WIFI_HIDDEN);
Sander Alewijnse8f9bd132014-09-08 12:21:26 +0100434 params.mStartedByNfc = intent.getBooleanExtra(EXTRA_PROVISIONING_STARTED_BY_NFC,
435 false);
Sander Alewijnsefd134872014-11-18 13:28:06 +0000436 params.mLeaveAllSystemAppsEnabled = intent.getBooleanExtra(
437 EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED,
438 ProvisioningParams.DEFAULT_LEAVE_ALL_SYSTEM_APPS_ENABLED);
Julia Reynolds5d47b652015-02-02 06:47:25 -0500439 params.mSkipEncryption = intent.getBooleanExtra(
440 EXTRA_PROVISIONING_SKIP_ENCRYPTION,
441 ProvisioningParams.DEFAULT_EXTRA_PROVISIONING_SKIP_ENCRYPTION);
Sander Alewijnse8f9bd132014-09-08 12:21:26 +0100442
Craig Lafayette2fe9d992015-03-24 12:42:05 -0400443 params.mBluetoothMac = intent.getStringExtra(EXTRA_PROVISIONING_BT_MAC_ADDRESS);
444 params.mBluetoothUuid = intent.getStringExtra(EXTRA_PROVISIONING_BT_UUID);
445 params.mBluetoothDeviceIdentifier = intent.getStringExtra(EXTRA_PROVISIONING_BT_DEVICE_ID);
446 params.mUseBluetoothProxy = intent.getBooleanExtra(EXTRA_PROVISIONING_BT_USE_PROXY, false);
447
Sander Alewijnsef88f7092014-08-20 16:26:09 +0100448 try {
449 params.mAdminExtrasBundle = (PersistableBundle) intent.getParcelableExtra(
450 EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE);
451 } catch (ClassCastException e) {
Nicolas Prevot0b447252015-03-09 14:59:02 +0000452 throw new IllegalProvisioningArgumentException("Extra "
453 + EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE
454 + " must be of type PersistableBundle.", e);
Sander Alewijnsef88f7092014-08-20 16:26:09 +0100455 }
Sander Alewijnse9aff1402014-07-18 17:15:32 +0100456
Sander Alewijnse56f71572014-06-23 16:21:33 +0100457 checkValidityOfProvisioningParams(params);
458 return params;
Sander Alewijnseed0883b2014-03-18 15:01:13 +0000459 }
460
461 /**
Sander Alewijnse885c3492014-04-24 17:30:31 +0100462 * Check whether necessary fields are set.
463 */
464 private void checkValidityOfProvisioningParams(ProvisioningParams params)
Nicolas Prevot0b447252015-03-09 14:59:02 +0000465 throws IllegalProvisioningArgumentException {
Nicolas Prevot668d65f2015-03-10 17:58:15 +0000466 if (TextUtils.isEmpty(params.mDeviceAdminPackageName)
467 && params.mDeviceAdminComponentName == null) {
468 throw new IllegalProvisioningArgumentException("Must provide the name of the device"
469 + " admin package or component name");
470 }
Sander Alewijnse56f71572014-06-23 16:21:33 +0100471 if (!TextUtils.isEmpty(params.mDeviceAdminPackageDownloadLocation)) {
472 if (params.mDeviceAdminPackageChecksum == null ||
473 params.mDeviceAdminPackageChecksum.length == 0) {
Nicolas Prevot0b447252015-03-09 14:59:02 +0000474 throw new IllegalProvisioningArgumentException("Checksum of installer file is"
475 + " required for downloading device admin file, but not provided.");
Sander Alewijnse885c3492014-04-24 17:30:31 +0100476 }
Sander Alewijnse885c3492014-04-24 17:30:31 +0100477 }
478 }
479
Sander Alewijnse56f71572014-06-23 16:21:33 +0100480 public static byte[] stringToByteArray(String s)
481 throws NumberFormatException {
Sander Alewijnse48fdbe02014-07-03 14:25:45 +0100482 try {
483 return Base64.decode(s, Base64.URL_SAFE);
484 } catch (IllegalArgumentException e) {
485 throw new NumberFormatException("Incorrect checksum format.");
Sander Alewijnse56f71572014-06-23 16:21:33 +0100486 }
Sander Alewijnse56f71572014-06-23 16:21:33 +0100487 }
488
489 public static Locale stringToLocale(String s)
Narayan Kamath53ff3c02014-07-17 14:02:58 +0100490 throws IllformedLocaleException {
491 return new Locale.Builder().setLanguageTag(s.replace("_", "-")).build();
Sander Alewijnse56f71572014-06-23 16:21:33 +0100492 }
Sander Alewijnse226d36c2014-06-26 16:33:05 +0000493}