Merge "Add proper error handling to the device owner provisioning."
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 77e0602..0c87bba 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -85,7 +85,17 @@
<!-- Title of the error dialog. [CHAR LIMIT=45] -->
<string name="device_owner_error_title">Provisioning failed</string>
- <!-- Message of the error dialog. [CHAR LIMIT=NONE] -->
+ <!-- Title of the cancel provisioning dialog. [CHAR LIMIT=45] -->
+ <string name="device_owner_cancel_title">Stop provisioning?</string>
+ <!-- Message of the cancel dialog. [CHAR LIMIT=NONE] -->
+ <string name="device_owner_cancel_message">Are you sure you want to stop provisioning and factory reset the device? The factory reset can take a while.</string>
+ <!-- Cancel button text of the cancel dialog. [CHAR LIMIT=45] -->
+ <string name="device_owner_cancel_cancel">Cancel</string>
+ <!-- OK button text of the error dialog. [CHAR LIMIT=45] -->
+ <string name="device_owner_error_ok">Ok</string>
+ <!-- Reset button text of the error dialog. [CHAR LIMIT=45] -->
+ <string name="device_owner_error_reset">Reset</string>
+ <!-- Message of the error dialog in case of an unspecified error. [CHAR LIMIT=NONE] -->
<string name="device_owner_error_general">An error occured.</string>
<!-- Message of the error dialog when already provisioned. [CHAR LIMIT=NONE] -->
<string name="device_owner_error_already_provisioned">The device is already provisioned.</string>
diff --git a/src/com/android/managedprovisioning/DeviceOwnerProvisioningActivity.java b/src/com/android/managedprovisioning/DeviceOwnerProvisioningActivity.java
index 23f55b9..fce781b 100644
--- a/src/com/android/managedprovisioning/DeviceOwnerProvisioningActivity.java
+++ b/src/com/android/managedprovisioning/DeviceOwnerProvisioningActivity.java
@@ -16,8 +16,11 @@
package com.android.managedprovisioning;
+import static android.app.admin.DeviceAdminReceiver.ACTION_PROFILE_PROVISIONING_COMPLETE;
+
import android.app.Activity;
import android.app.AlertDialog;
+import android.app.Dialog;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -26,6 +29,7 @@
import android.content.IntentFilter;
import android.os.Bundle;
import android.provider.Settings.Global;
+import android.provider.Settings.Secure;
import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater;
import android.view.View;
@@ -60,6 +64,9 @@
private BroadcastReceiver mServiceMessageReceiver;
private TextView mProgressTextView;
+ private Dialog mDialog; // The cancel or error dialog that is currently shown.
+ private boolean mDone; // Indicates whether the service has sent ACTION_PROVISIONING_SUCCESS.
+ private String mDeviceAdminPackageName;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -68,20 +75,20 @@
ProvisionLogger.logd("Device owner provisioning activity ONCREATE");
// Check whether we can provision.
- if (Global.getInt(getContentResolver(), Global.DEVICE_PROVISIONED, /* default */ 0) != 0) {
+ if (Global.getInt(getContentResolver(), Global.DEVICE_PROVISIONED, 0 /* default */) != 0) {
ProvisionLogger.loge("Device already provisioned.");
- error(R.string.device_owner_error_already_provisioned);
+ error(R.string.device_owner_error_already_provisioned, false /* no factory reset */);
return;
}
-
DevicePolicyManager dpm = (DevicePolicyManager)
getSystemService(Context.DEVICE_POLICY_SERVICE);
if (dpm.getDeviceOwner() != null) {
ProvisionLogger.loge("Device owner already present.");
- error(R.string.device_owner_error_already_owned);
+ error(R.string.device_owner_error_already_owned, false /* no factory reset */);
return;
}
+ // Setup the UI.
final LayoutInflater inflater = getLayoutInflater();
final View contentView = inflater.inflate(R.layout.progress, null);
setContentView(contentView);
@@ -93,15 +100,48 @@
filter.addAction(DeviceOwnerProvisioningService.ACTION_PROVISIONING_SUCCESS);
filter.addAction(DeviceOwnerProvisioningService.ACTION_PROVISIONING_ERROR);
filter.addAction(DeviceOwnerProvisioningService.ACTION_PROGRESS_UPDATE);
- filter.addAction(DeviceOwnerProvisioningService.ACTION_REQUEST_ENCRYPTION);
LocalBroadcastManager.getInstance(this).registerReceiver(mServiceMessageReceiver, filter);
+ // Parse the incoming intent.
+ MessageParser parser = new MessageParser();
+ ProvisioningParams params;
+ try {
+ params = parser.parseIntent(getIntent());
+ } catch (MessageParser.ParseException e) {
+ ProvisionLogger.loge("Could not read data from intent", e);
+ error(e.getErrorMessageId(), false /* no factory reset */);
+ return;
+ }
+ mDeviceAdminPackageName = params.mDeviceAdminPackageName;
+
+ // Ask to encrypt the device before proceeding
+ if (!EncryptDeviceActivity.isDeviceEncrypted()) {
+ requestEncryption(parser.getCachedProvisioningProperties());
+ finish();
+ return;
+ }
+
// Start service.
Intent intent = new Intent(this, DeviceOwnerProvisioningService.class);
+ intent.putExtra(DeviceOwnerProvisioningService.EXTRA_PROVISIONING_PARAMS, params);
intent.putExtras(getIntent());
startService(intent);
}
+ private void requestEncryption(String propertiesForResume) {
+ Intent encryptIntent = new Intent(DeviceOwnerProvisioningActivity.this,
+ EncryptDeviceActivity.class);
+
+ Bundle resumeExtras = new Bundle();
+ resumeExtras.putString(EncryptDeviceActivity.EXTRA_RESUME_TARGET,
+ EncryptDeviceActivity.TARGET_DEVICE_OWNER);
+ resumeExtras.putString(MessageParser.EXTRA_PROVISIONING_PROPERTIES,
+ propertiesForResume);
+ encryptIntent.putExtra(EncryptDeviceActivity.EXTRA_RESUME, resumeExtras);
+
+ startActivityForResult(encryptIntent, ENCRYPT_DEVICE_REQUEST_CODE);
+ }
+
class ServiceMessageReceiver extends BroadcastReceiver
{
@Override
@@ -110,19 +150,24 @@
String action = intent.getAction();
if (action.equals(DeviceOwnerProvisioningService.ACTION_PROVISIONING_SUCCESS)) {
ProvisionLogger.logd("Successfully provisioned");
- finish();
+ synchronized(this) {
+ if (mDialog == null) {
+ onProvisioningSuccess();
+ } else {
+ // Postpone finishing this activity till the user has decided whether
+ // he/she wants to reset or not.
+ mDone = true;
+ }
+ }
return;
} else if (action.equals(DeviceOwnerProvisioningService.ACTION_PROVISIONING_ERROR)) {
- int errorCode = intent.getIntExtra(
- DeviceOwnerProvisioningService.EXTRA_USER_VISIBLE_ERROR_ID_KEY, -1);
+ int errorMessageId = intent.getIntExtra(
+ DeviceOwnerProvisioningService.EXTRA_USER_VISIBLE_ERROR_ID_KEY,
+ R.string.device_owner_error_general);
+
ProvisionLogger.logd("Error reported with code "
- + getResources().getString(errorCode));
- if (errorCode < 0) {
- error(R.string.device_owner_error_general);
- return;
- } else {
- error(errorCode);
- }
+ + getResources().getString(errorMessageId));
+ error(errorMessageId, true /* always factory reset */);
} else if (action.equals(DeviceOwnerProvisioningService.ACTION_PROGRESS_UPDATE)) {
int progressMessage = intent.getIntExtra(
DeviceOwnerProvisioningService.EXTRA_PROGRESS_MESSAGE_ID_KEY, -1);
@@ -131,25 +176,80 @@
if (progressMessage >= 0) {
progressUpdate(progressMessage);
}
- } else if (action.equals(DeviceOwnerProvisioningService.ACTION_REQUEST_ENCRYPTION)) {
- ProvisionLogger.logd("Received request to encrypt device.");
- Intent encryptIntent = new Intent(DeviceOwnerProvisioningActivity.this,
- EncryptDeviceActivity.class);
- encryptIntent.putExtras(intent);
- startActivityForResult(encryptIntent, ENCRYPT_DEVICE_REQUEST_CODE);
}
}
}
+ private void onProvisioningSuccess() {
+ stopService(new Intent(DeviceOwnerProvisioningActivity.this,
+ DeviceOwnerProvisioningService.class));
+
+ // Skip the setup wizard.
+ Global.putInt(getContentResolver(), Global.DEVICE_PROVISIONED, 1);
+ Secure.putInt(getContentResolver(), Secure.USER_SETUP_COMPLETE, 1);
+
+ Intent completeIntent = new Intent(ACTION_PROFILE_PROVISIONING_COMPLETE);
+ completeIntent.setPackage(mDeviceAdminPackageName);
+ completeIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES |
+ Intent.FLAG_RECEIVER_FOREGROUND);
+ sendBroadcast(completeIntent);
+ finish();
+ }
+
@Override
public void onBackPressed() {
- // TODO: Handle this graciously by stopping the provisioning flow and cleaning up.
+ showCancelResetDialog();
+ }
+
+ private void showCancelResetDialog() {
+ AlertDialog.Builder alertBuilder =
+ new AlertDialog.Builder(DeviceOwnerProvisioningActivity.this)
+ .setTitle(R.string.device_owner_cancel_title)
+ .setMessage(R.string.device_owner_cancel_message)
+ .setNegativeButton(R.string.device_owner_cancel_cancel,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog,int id) {
+ dialog.dismiss();
+ synchronized(this) {
+ mDialog = null;
+ if (mDone) {
+ onProvisioningSuccess();
+ }
+ }
+ }
+ })
+ .setPositiveButton(R.string.device_owner_error_reset,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog,int id) {
+ // Factory reset the device.
+ sendBroadcast(
+ new Intent("android.intent.action.MASTER_CLEAR"));
+ stopService(new Intent(DeviceOwnerProvisioningActivity.this,
+ DeviceOwnerProvisioningService.class));
+ finish();
+ }
+ });
+
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
+ mDialog = alertBuilder.create();
+ mDialog.show();
}
@Override
public void onDestroy() {
ProvisionLogger.logd("Device owner provisioning activity ONDESTROY");
- LocalBroadcastManager.getInstance(this).unregisterReceiver(mServiceMessageReceiver);
+ if (mServiceMessageReceiver != null) {
+ LocalBroadcastManager.getInstance(this).unregisterReceiver(mServiceMessageReceiver);
+ mServiceMessageReceiver = null;
+ }
+ if (mDialog != null) {
+ mDialog.dismiss();
+ mDialog = null;
+ }
super.onDestroy();
}
@@ -167,20 +267,37 @@
}
}
- private void error(int dialogMessage) {
- AlertDialog dlg = new AlertDialog.Builder(this)
+ private void error(int dialogMessage, boolean resetRequired) {
+ AlertDialog.Builder alertBuilder = new AlertDialog.Builder(this)
.setTitle(R.string.device_owner_error_title)
.setMessage(dialogMessage)
- .setCancelable(false)
- .setPositiveButton("OK", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog,int id) {
- // Close activity
- finish();
- }
- })
- .create();
- dlg.show();
+ .setCancelable(false);
+ if (resetRequired) {
+ alertBuilder.setPositiveButton(R.string.device_owner_error_reset,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog,int id) {
+ // Factory reset the device.
+ sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));
+ stopService(new Intent(DeviceOwnerProvisioningActivity.this,
+ DeviceOwnerProvisioningService.class));
+ finish();
+ }
+ });
+ } else {
+ alertBuilder.setPositiveButton(R.string.device_owner_error_ok,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog,int id) {
+ // Close activity.
+ stopService(new Intent(DeviceOwnerProvisioningActivity.this,
+ DeviceOwnerProvisioningService.class));
+ finish();
+ }
+ });
+ }
+ mDialog = alertBuilder.create();
+ mDialog.show();
}
@Override
diff --git a/src/com/android/managedprovisioning/DeviceOwnerProvisioningService.java b/src/com/android/managedprovisioning/DeviceOwnerProvisioningService.java
index e002a92..dfdd312 100644
--- a/src/com/android/managedprovisioning/DeviceOwnerProvisioningService.java
+++ b/src/com/android/managedprovisioning/DeviceOwnerProvisioningService.java
@@ -16,8 +16,6 @@
package com.android.managedprovisioning;
-import static android.app.admin.DeviceAdminReceiver.ACTION_PROFILE_PROVISIONING_COMPLETE;
-
import android.app.AlarmManager;
import android.app.Service;
import android.content.ComponentName;
@@ -25,8 +23,6 @@
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
-import android.provider.Settings.Global;
-import android.provider.Settings.Secure;
import android.support.v4.content.LocalBroadcastManager;
import com.android.internal.app.LocalePicker;
@@ -38,7 +34,6 @@
import java.lang.Runnable;
import java.util.Locale;
-import java.util.concurrent.atomic.AtomicBoolean;
/**
* This service does the work for the DeviceOwnerProvisioningActivity.
@@ -60,20 +55,23 @@
"com.android.phone.PERFORM_CDMA_PROVISIONING";
// Intent actions for communication with DeviceOwnerProvisioningService.
- public static final String ACTION_PROVISIONING_SUCCESS =
+ protected static final String ACTION_PROVISIONING_SUCCESS =
"com.android.managedprovisioning.provisioning_success";
- public static final String ACTION_PROVISIONING_ERROR =
+ protected static final String ACTION_PROVISIONING_ERROR =
"com.android.managedprovisioning.error";
- public static final String EXTRA_USER_VISIBLE_ERROR_ID_KEY = "UserVisibleErrorMessage-Id";
- public static final String ACTION_PROGRESS_UPDATE =
+ protected static final String EXTRA_USER_VISIBLE_ERROR_ID_KEY =
+ "UserVisibleErrorMessage-Id";
+ protected static final String ACTION_PROGRESS_UPDATE =
"com.android.managedprovisioning.progress_update";
- public static final String EXTRA_PROGRESS_MESSAGE_ID_KEY = "ProgressMessageId";
- public static final String ACTION_REQUEST_ENCRYPTION =
- "com.android.managedprovisioning.request_encryption";
+ protected static final String EXTRA_PROGRESS_MESSAGE_ID_KEY =
+ "ProgressMessageId";
+ protected static final String EXTRA_PROVISIONING_PARAMS =
+ "ProvisioningParams";
- private AtomicBoolean mProvisioningInFlight = new AtomicBoolean(false);
- private int mLastProgressMessage;
- private int mStartIdProvisioning;
+ private boolean mProvisioningInFlight = false;
+ private int mLastProgressMessage = -1;
+ private int mLastErrorMessage = -1;
+ private boolean mDone = false;
// Provisioning tasks.
private AddWifiNetworkTask mAddWifiNetworkTask;
@@ -82,43 +80,42 @@
private SetDevicePolicyTask mSetDevicePolicyTask;
private DeleteNonRequiredAppsTask mDeleteNonRequiredAppsTask;
+ private ProvisioningParams mParams;
+
@Override
public int onStartCommand(final Intent intent, int flags, int startId) {
- if (mProvisioningInFlight.getAndSet(true)) {
- ProvisionLogger.logd("Provisioning already in flight. Ignoring intent.");
- sendProgressUpdateToActivity();
- stopSelf(startId);
- } else {
- progressUpdate(R.string.progress_data_process);
+ ProvisionLogger.logd("Device owner provisioning service ONSTARTCOMMAND.");
- mStartIdProvisioning = startId;
+ synchronized (this) { // Make operations on mProvisioningInFlight atomic.
+ if (mProvisioningInFlight) {
+ ProvisionLogger.logd("Provisioning already in flight.");
- // Load the ProvisioningParams (from message in Intent).
- MessageParser parser = new MessageParser();
- final ProvisioningParams params;
- try {
- params = parser.parseIntent(intent);
- } catch (MessageParser.ParseException e) {
- ProvisionLogger.loge("Could not read data from intent", e);
- error(e.getErrorMessageId());
- return START_NOT_STICKY;
+ sendProgressUpdateToActivity();
+
+ // Send error message if currently in error state.
+ if (mLastErrorMessage >= 0) {
+ sendError();
+ }
+
+ if (mDone) {
+ onProvisioningSuccess(mParams.mDeviceAdminPackageName);
+ }
+ } else {
+ mProvisioningInFlight = true;
+ ProvisionLogger.logd("First start of the service.");
+ progressUpdate(R.string.progress_data_process);
+
+ // Load the ProvisioningParams (from message in Intent).
+ mParams = (ProvisioningParams) intent.getParcelableExtra(EXTRA_PROVISIONING_PARAMS);
+
+ // Do the work on a separate thread.
+ new Thread(new Runnable() {
+ public void run() {
+ initializeProvisioningEnvironment(mParams);
+ startDeviceOwnerProvisioning(mParams);
+ }
+ }).start();
}
-
- // Ask to encrypt the device before proceeding
- if (!EncryptDeviceActivity.isDeviceEncrypted()) {
- requestEncryption(parser.getCachedProvisioningProperties());
- stopSelf(startId);
- return START_NOT_STICKY;
- }
-
- // Do the work on a separate thread.
- new Thread(new Runnable() {
- @Override
- public void run() {
- initializeProvisioningEnvironment(params);
- startDeviceOwnerProvisioning(params);
- }
- }).start();
}
return START_NOT_STICKY;
}
@@ -158,10 +155,8 @@
public void onSuccess() {
String downloadLocation =
mDownloadPackageTask.getDownloadedPackageLocation();
- Runnable cleanupRunnable =
- mDownloadPackageTask.getCleanUpDownloadRunnable();
progressUpdate(R.string.progress_install);
- mInstallPackageTask.run(downloadLocation, cleanupRunnable);
+ mInstallPackageTask.run(downloadLocation);
}
@Override
@@ -255,15 +250,17 @@
}
private void error(int dialogMessage) {
+ mLastErrorMessage = dialogMessage;
+ sendError();
+ // Wait for stopService() call from the activity.
+ }
- ProvisionLogger.logd("Reporting Error: " + getResources().getString(dialogMessage));
-
+ private void sendError() {
+ ProvisionLogger.logd("Reporting Error: " + getResources().getString(mLastErrorMessage));
Intent intent = new Intent(ACTION_PROVISIONING_ERROR);
intent.setClass(this, DeviceOwnerProvisioningActivity.ServiceMessageReceiver.class);
- intent.putExtra(EXTRA_USER_VISIBLE_ERROR_ID_KEY, dialogMessage);
+ intent.putExtra(EXTRA_USER_VISIBLE_ERROR_ID_KEY, mLastErrorMessage);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
-
- stopSelf(mStartIdProvisioning);
}
private void progressUpdate(int progressMessage) {
@@ -280,33 +277,14 @@
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
- private void requestEncryption(String propertiesForResume) {
- Bundle resumeExtras = new Bundle();
- resumeExtras.putString(EncryptDeviceActivity.EXTRA_RESUME_TARGET,
- EncryptDeviceActivity.TARGET_DEVICE_OWNER);
- resumeExtras.putString(MessageParser.EXTRA_PROVISIONING_PROPERTIES,
- propertiesForResume);
- Intent intent = new Intent(ACTION_REQUEST_ENCRYPTION);
- intent.putExtra(EncryptDeviceActivity.EXTRA_RESUME, resumeExtras);
- sendBroadcast(intent);
- }
private void onProvisioningSuccess(String deviceAdminPackage) {
+ ProvisionLogger.logv("Reporting success.");
+ mDone = true;
Intent successIntent = new Intent(ACTION_PROVISIONING_SUCCESS);
successIntent.setClass(this, DeviceOwnerProvisioningActivity.ServiceMessageReceiver.class);
LocalBroadcastManager.getInstance(this).sendBroadcast(successIntent);
-
- // Skip the setup wizard.
- Global.putInt(getContentResolver(), Global.DEVICE_PROVISIONED, 1);
- Secure.putInt(getContentResolver(), Secure.USER_SETUP_COMPLETE, 1);
-
- Intent completeIntent = new Intent(ACTION_PROFILE_PROVISIONING_COMPLETE);
- completeIntent.setPackage(deviceAdminPackage);
- completeIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES |
- Intent.FLAG_RECEIVER_FOREGROUND);
- sendBroadcast(completeIntent);
-
- stopSelf(mStartIdProvisioning);
+ // Wait for stopService() call from the activity.
}
private void initializeProvisioningEnvironment(ProvisioningParams params) {
@@ -320,14 +298,14 @@
startActivity(intent); // Activity will be a Nop if not a CDMA device.
}
- private void setTimeAndTimezone(String timeZone, Long localTime) {
+ private void setTimeAndTimezone(String timeZone, long localTime) {
try {
final AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
if (timeZone != null) {
ProvisionLogger.logd("Setting time zone to " + timeZone);
am.setTimeZone(timeZone);
}
- if (localTime != null) {
+ if (localTime > 0) {
ProvisionLogger.logd("Setting time to " + localTime);
am.setTime(localTime);
}
@@ -353,9 +331,18 @@
}
@Override
+ public void onCreate () {
+ ProvisionLogger.logd("Device owner provisioning service ONCREATE.");
+ }
+
+ @Override
public void onDestroy () {
+ ProvisionLogger.logd("Device owner provisioning service ONDESTROY");
if (mAddWifiNetworkTask != null) {
- mAddWifiNetworkTask.unRegister();
+ mAddWifiNetworkTask.cleanUp();
+ }
+ if (mDownloadPackageTask != null) {
+ mDownloadPackageTask.cleanUp();
}
}
diff --git a/src/com/android/managedprovisioning/MessageParser.java b/src/com/android/managedprovisioning/MessageParser.java
index 98dc0ec..5e1383f 100644
--- a/src/com/android/managedprovisioning/MessageParser.java
+++ b/src/com/android/managedprovisioning/MessageParser.java
@@ -23,6 +23,7 @@
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.os.Parcelable;
+import android.text.TextUtils;
import java.io.IOException;
import java.io.StringReader;
@@ -262,17 +263,17 @@
*/
private void checkValidityOfProvisioningParams(ProvisioningParams params)
throws ParseException {
- if (params.mDeviceAdminPackageName == null) {
+ if (TextUtils.isEmpty(params.mDeviceAdminPackageName)) {
throw new ParseException("Must provide the name of the device admin package.",
R.string.device_owner_error_no_package_name);
}
- if (params.mDownloadLocation != null) {
- if (params.mHash == null) {
+ if (!TextUtils.isEmpty(params.mDownloadLocation)) {
+ if (params.mHash == null || params.mHash.length == 0) {
throw new ParseException("Hash of installer file is required for downloading " +
"device admin file, but not provided.",
R.string.device_owner_error_no_hash);
}
- if (params.mWifiSsid == null) {
+ if (TextUtils.isEmpty(params.mWifiSsid)) {
throw new ParseException("Wifi ssid is required for downloading device admin " +
"file, but not provided.",
R.string.device_owner_error_no_wifi_ssid);
@@ -307,4 +308,4 @@
return mErrorMessageId;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/managedprovisioning/ProvisioningParams.java b/src/com/android/managedprovisioning/ProvisioningParams.java
index 072a4ba..f4562d1 100644
--- a/src/com/android/managedprovisioning/ProvisioningParams.java
+++ b/src/com/android/managedprovisioning/ProvisioningParams.java
@@ -16,14 +16,16 @@
package com.android.managedprovisioning;
+import android.os.Parcel;
+import android.os.Parcelable;
import java.util.Locale;
/**
* Provisioning Parameters for DeviceOwner Provisioning
*/
-public class ProvisioningParams {
+public class ProvisioningParams implements Parcelable {
public static String mTimeZone;
- public static Long mLocalTime;
+ public static long mLocalTime = -1;
public static Locale mLocale;
public static String mWifiSsid;
@@ -39,5 +41,56 @@
public static String mOwner; // Human readable name of the institution that owns this device.
public static String mDownloadLocation; // Url where the device admin .apk is downloaded from.
- public static byte[] mHash; // Hash of the .apk file (see {@link DownloadPackageTask).
+ public static byte[] mHash = new byte[0]; // Hash of the .apk file.
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mTimeZone);
+ out.writeLong(mLocalTime);
+ out.writeSerializable(mLocale);
+ out.writeString(mWifiSsid);
+ out.writeInt(mWifiHidden ? 1 : 0);
+ out.writeString(mWifiSecurityType);
+ out.writeString(mWifiPassword);
+ out.writeString(mWifiProxyHost);
+ out.writeInt(mWifiProxyPort);
+ out.writeString(mWifiProxyBypassHosts);
+ out.writeString(mDeviceAdminPackageName);
+ out.writeString(mOwner);
+ out.writeString(mDownloadLocation);
+ out.writeByteArray(mHash);
+ }
+
+ public static final Parcelable.Creator<ProvisioningParams> CREATOR
+ = new Parcelable.Creator<ProvisioningParams>() {
+ @Override
+ public ProvisioningParams createFromParcel(Parcel in) {
+ ProvisioningParams params = new ProvisioningParams();
+ params.mTimeZone = in.readString();
+ params.mLocalTime = in.readLong();
+ params.mLocale = (Locale) in.readSerializable();
+ params.mWifiSsid = in.readString();
+ params.mWifiHidden = in.readInt()==1;
+ params.mWifiSecurityType = in.readString();
+ params.mWifiPassword = in.readString();
+ params.mWifiProxyHost = in.readString();
+ params.mWifiProxyPort = in.readInt();
+ params.mWifiProxyBypassHosts = in.readString();
+ params.mDeviceAdminPackageName = in.readString();
+ params.mOwner = in.readString();
+ params.mDownloadLocation = in.readString();
+ in.readByteArray(params.mHash);
+ return params;
+ }
+
+ @Override
+ public ProvisioningParams[] newArray(int size) {
+ return new ProvisioningParams[size];
+ }
+ };
}
diff --git a/src/com/android/managedprovisioning/task/AddWifiNetworkTask.java b/src/com/android/managedprovisioning/task/AddWifiNetworkTask.java
index 6756bbc..20cf6d4 100644
--- a/src/com/android/managedprovisioning/task/AddWifiNetworkTask.java
+++ b/src/com/android/managedprovisioning/task/AddWifiNetworkTask.java
@@ -119,7 +119,7 @@
}
}
- public void unRegister() {
+ public void cleanUp() {
if (mNetworkMonitor != null) {
mNetworkMonitor.close();
mNetworkMonitor = null;
diff --git a/src/com/android/managedprovisioning/task/DownloadPackageTask.java b/src/com/android/managedprovisioning/task/DownloadPackageTask.java
index 387c8dc..7e79e52 100644
--- a/src/com/android/managedprovisioning/task/DownloadPackageTask.java
+++ b/src/com/android/managedprovisioning/task/DownloadPackageTask.java
@@ -34,7 +34,6 @@
import java.io.InputStream;
import java.io.IOException;
import java.io.FileInputStream;
-import java.lang.Runnable;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
@@ -58,6 +57,7 @@
private boolean mDoneDownloading;
private String mDownloadLocationTo;
private long mDownloadId;
+ private BroadcastReceiver mReceiver;
public DownloadPackageTask (Context context, String downloadLocation, byte[] hash,
Callback callback) {
@@ -73,7 +73,8 @@
}
public void run() {
- mContext.registerReceiver(createDownloadReceiver(),
+ mReceiver = createDownloadReceiver();
+ mContext.registerReceiver(mReceiver,
new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
ProvisionLogger.logd("Starting download from " + mDownloadLocationFrom);
@@ -96,13 +97,11 @@
if (c.moveToFirst()) {
int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
- mContext.unregisterReceiver(this);
String location = c.getString(
c.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
c.close();
onDownloadSuccess(location);
} else if (DownloadManager.STATUS_FAILED == c.getInt(columnIndex)){
- mContext.unregisterReceiver(this);
int reason = c.getColumnIndex(DownloadManager.COLUMN_REASON);
c.close();
onDownloadFail(reason);
@@ -197,21 +196,23 @@
return mDownloadLocationTo;
}
- public Runnable getCleanUpDownloadRunnable() {
- return new Runnable() {
- @Override
- public void run() {
- DownloadManager dm = (DownloadManager) mContext
- .getSystemService(Context.DOWNLOAD_SERVICE);
- boolean removeSuccess = dm.remove(mDownloadId) == 1;
- if (removeSuccess) {
- ProvisionLogger.logd("Successfully removed the device owner installer file.");
- } else {
- ProvisionLogger.loge("Could not remove the device owner installer file.");
- // Ignore this error. Failing cleanup should not stop provisioning flow.
- }
+ public void cleanUp() {
+ if (mReceiver != null) {
+ //Unregister receiver.
+ mContext.unregisterReceiver(mReceiver);
+ mReceiver = null;
+
+ //Remove download.
+ DownloadManager dm = (DownloadManager) mContext
+ .getSystemService(Context.DOWNLOAD_SERVICE);
+ boolean removeSuccess = dm.remove(mDownloadId) == 1;
+ if (removeSuccess) {
+ ProvisionLogger.logd("Successfully removed the device owner installer file.");
+ } else {
+ ProvisionLogger.loge("Could not remove the device owner installer file.");
+ // Ignore this error. Failing cleanup should not stop provisioning flow.
}
- };
+ }
}
// For logging purposes only.
diff --git a/src/com/android/managedprovisioning/task/InstallPackageTask.java b/src/com/android/managedprovisioning/task/InstallPackageTask.java
index 45b9ce9..6d38b2a 100644
--- a/src/com/android/managedprovisioning/task/InstallPackageTask.java
+++ b/src/com/android/managedprovisioning/task/InstallPackageTask.java
@@ -29,7 +29,6 @@
import com.android.managedprovisioning.ProvisionLogger;
import java.io.File;
-import java.lang.Runnable;
/**
* Installs a device owner package from a given path.
@@ -41,7 +40,6 @@
public class InstallPackageTask {
public static final int ERROR_PACKAGE_INVALID = 0;
public static final int ERROR_INSTALLATION_FAILED = 1;
- public static final int ERROR_OTHER = 2;
private final Context mContext;
private final Callback mCallback;
@@ -49,7 +47,6 @@
private String mPackageLocation;
private PackageManager mPm;
- private Runnable mCleanUpDownloadRunnable;
private int mPackageVerifierEnable;
public InstallPackageTask (Context context, String packageName,
@@ -60,14 +57,13 @@
mPackageName = packageName;
}
- public void run(String packageLocation, Runnable cleanUpDownloadRunnable) {
+ public void run(String packageLocation) {
if (TextUtils.isEmpty(packageLocation)) {
ProvisionLogger.loge("Package Location is empty.");
mCallback.onError(ERROR_PACKAGE_INVALID);
return;
}
mPackageLocation = packageLocation;
- mCleanUpDownloadRunnable = cleanUpDownloadRunnable;
PackageInstallObserver observer = new PackageInstallObserver();
mPm = mContext.getPackageManager();
@@ -117,25 +113,22 @@
private class PackageInstallObserver extends IPackageInstallObserver.Stub {
@Override
public void packageInstalled(String packageName, int returnCode) {
+ if (!packageName.equals(mPackageName)) {
+ return;
+ }
+
// Set package verification flag to its original value.
Global.putInt(mContext.getContentResolver(), Global.PACKAGE_VERIFIER_ENABLE,
mPackageVerifierEnable);
- if (!packageName.equals(mPackageName)) {
- ProvisionLogger.loge("Something went wrong: Installed package " + packageName
- + " and not " + mPackageName + ".");
- mCallback.onError(ERROR_OTHER);
- return;
- }
if (returnCode == PackageManager.INSTALL_SUCCEEDED) {
ProvisionLogger.logd("Package " + packageName + " is succesfully installed.");
- mCleanUpDownloadRunnable.run();
+
mCallback.onSuccess();
} else {
ProvisionLogger.logd("Installing package " + packageName + " failed.");
ProvisionLogger.logd("Errorcode returned by IPackageInstallObserver = "
+ returnCode);
- mCleanUpDownloadRunnable.run();
mCallback.onError(ERROR_INSTALLATION_FAILED);
}
}