Merge "Allow to specify the admin component for provisioning."
diff --git a/src/com/android/managedprovisioning/BootReminder.java b/src/com/android/managedprovisioning/BootReminder.java
index 85c6511..202cb80 100644
--- a/src/com/android/managedprovisioning/BootReminder.java
+++ b/src/com/android/managedprovisioning/BootReminder.java
@@ -17,7 +17,7 @@
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
-import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
import android.app.Notification;
import android.app.NotificationManager;
@@ -41,9 +41,9 @@
private static final String PROFILE_OWNER_PREFERENCES_NAME =
"profile-owner-provisioning-resume";
- private static final String[] PROFILE_OWNER_STRING_EXTRAS = {
- // Key for the device admin package name
- EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME
+ private static final String[] PROFILE_OWNER_COMPONENT_NAME_EXTRAS = {
+ // Key for the device admin component name
+ EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME
};
private static final String[] PROFILE_OWNER_PERSISTABLE_BUNDLE_EXTRAS = {
@@ -104,8 +104,8 @@
* and {@link EncryptDeviceActivity.TARGET_DEVICE_OWNER}
*
* <p> In case of TARGET_PROFILE_OWNER {@code extras} should further contain a value for at
- * least the key: {@link EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}, a {@link String} which
- * specifies the package to set as profile owner.
+ * least the key: {@link EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}, a {@link String}
+ * which, when unflattened to a componentName, specifies the component to set as profile owner.
*
* <p>
* See {@link MessageParser} for the TARGET_DEVICE_OWNER case.
@@ -142,13 +142,14 @@
private static IntentStore getProfileOwnerIntentStore(Context context) {
return new IntentStore(context,PROFILE_OWNER_INTENT_TARGET, PROFILE_OWNER_PREFERENCES_NAME)
- .setStringKeys(PROFILE_OWNER_STRING_EXTRAS)
+ .setComponentNameKeys(PROFILE_OWNER_COMPONENT_NAME_EXTRAS)
.setPersistableBundleKeys(PROFILE_OWNER_PERSISTABLE_BUNDLE_EXTRAS)
.setAccountKeys(PROFILE_OWNER_ACCOUNT_EXTRAS);
}
private static IntentStore getDeviceOwnerIntentStore(Context context) {
return new IntentStore(context, DEVICE_OWNER_INTENT_TARGET, DEVICE_OWNER_PREFERENCES_NAME)
+ .setComponentNameKeys(MessageParser.DEVICE_OWNER_COMPONENT_NAME_EXTRAS)
.setStringKeys(MessageParser.DEVICE_OWNER_STRING_EXTRAS)
.setLongKeys(MessageParser.DEVICE_OWNER_LONG_EXTRAS)
.setIntKeys(MessageParser.DEVICE_OWNER_INT_EXTRAS)
diff --git a/src/com/android/managedprovisioning/DeviceOwnerProvisioningActivity.java b/src/com/android/managedprovisioning/DeviceOwnerProvisioningActivity.java
index ba7685b..65cbe6c 100644
--- a/src/com/android/managedprovisioning/DeviceOwnerProvisioningActivity.java
+++ b/src/com/android/managedprovisioning/DeviceOwnerProvisioningActivity.java
@@ -36,6 +36,7 @@
import android.widget.TextView;
import com.android.managedprovisioning.task.AddWifiNetworkTask;
+import com.android.managedprovisioning.Utils.IllegalProvisioningArgumentException;
import com.android.setupwizard.navigationbar.SetupWizardNavBar;
import com.android.setupwizard.navigationbar.SetupWizardNavBar.NavigationBarListener;
@@ -147,10 +148,10 @@
// Parse the incoming intent.
MessageParser parser = new MessageParser();
try {
- mParams = parser.parseIntent(getIntent());
- } catch (MessageParser.ParseException e) {
+ mParams = parser.parseIntent(getIntent(), this);
+ } catch (Utils.IllegalProvisioningArgumentException e) {
ProvisionLogger.loge("Could not read data from intent", e);
- error(e.getErrorMessageId(), false /* no factory reset */);
+ error(R.string.device_owner_error_general, false /* no factory reset */);
return;
}
diff --git a/src/com/android/managedprovisioning/DeviceOwnerProvisioningService.java b/src/com/android/managedprovisioning/DeviceOwnerProvisioningService.java
index 0f59f71..06f2773 100644
--- a/src/com/android/managedprovisioning/DeviceOwnerProvisioningService.java
+++ b/src/com/android/managedprovisioning/DeviceOwnerProvisioningService.java
@@ -126,7 +126,7 @@
// Send success if provisioning was succesful.
if (mDone) {
- onProvisioningSuccess(mParams.mDeviceAdminPackageName);
+ onProvisioningSuccess();
}
} else {
mProvisioningInFlight = true;
@@ -176,7 +176,7 @@
// Send complete intent to mdm.
Intent result = new Intent(ACTION_PROFILE_PROVISIONING_COMPLETE);
- result.setPackage(mParams.mDeviceAdminPackageName);
+ result.setPackage(mParams.mDeviceAdminComponentName.getPackageName());
result.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES |
Intent.FLAG_RECEIVER_FOREGROUND);
if (mParams.mAdminExtrasBundle != null) {
@@ -240,7 +240,7 @@
});
mInstallPackageTask = new InstallPackageTask(this,
- params.mDeviceAdminPackageName, params.mDeviceAdminPackageDownloadLocation,
+ params.getDeviceAdminPackageName(), params.mDeviceAdminPackageDownloadLocation,
new InstallPackageTask.Callback() {
@Override
public void onSuccess() {
@@ -265,7 +265,7 @@
});
mSetDevicePolicyTask = new SetDevicePolicyTask(this,
- params.mDeviceAdminPackageName,
+ params.mDeviceAdminComponentName,
getResources().getString(R.string.default_owned_device_username),
new SetDevicePolicyTask.Callback() {
@Override
@@ -290,13 +290,13 @@
});
mDeleteNonRequiredAppsTask = new DeleteNonRequiredAppsTask(
- this, params.mDeviceAdminPackageName, R.array.required_apps_managed_device,
+ this, params.getDeviceAdminPackageName(), R.array.required_apps_managed_device,
R.array.vendor_required_apps_managed_device, true /* creating new profile */,
UserHandle.USER_OWNER, params.mLeaveAllSystemAppsEnabled,
new DeleteNonRequiredAppsTask.Callback() {
public void onSuccess() {
// Done with provisioning. Success.
- onProvisioningSuccess(params.mDeviceAdminPackageName);
+ onProvisioningSuccess();
}
@Override
@@ -343,7 +343,7 @@
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
- private void onProvisioningSuccess(String deviceAdminPackage) {
+ private void onProvisioningSuccess() {
if (DEBUG) ProvisionLogger.logd("Reporting success.");
mDone = true;
diff --git a/src/com/android/managedprovisioning/IntentStore.java b/src/com/android/managedprovisioning/IntentStore.java
index ae5839a..8e0ad74 100644
--- a/src/com/android/managedprovisioning/IntentStore.java
+++ b/src/com/android/managedprovisioning/IntentStore.java
@@ -49,6 +49,7 @@
private String[] mBooleanKeys = new String[0];
private String[] mPersistableBundleKeys = new String[0];
private String[] mAccountKeys = new String[0];
+ private String[] mComponentNameKeys = new String[0];
private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle";
private static final String TAG_ACCOUNT = "account";
@@ -94,6 +95,11 @@
return this;
}
+ public IntentStore setComponentNameKeys(String[] keys) {
+ mComponentNameKeys = (keys == null) ? new String[0] : keys;
+ return this;
+ }
+
public void clear() {
mPrefs.edit().clear().commit();
}
@@ -130,6 +136,10 @@
editor.putString(key, bundleString);
}
}
+ for (String key : mComponentNameKeys) {
+ ComponentName cn = (ComponentName) data.getParcelable(key);
+ editor.putString(key, cn.flattenToString());
+ }
editor.putBoolean(IS_SET, true);
editor.commit();
}
@@ -179,6 +189,12 @@
}
}
}
+ for (String key : mComponentNameKeys) {
+ if (mPrefs.contains(key)) {
+ result.putExtra(key, ComponentName.unflattenFromString(
+ mPrefs.getString(key, null)));
+ }
+ }
return result;
}
diff --git a/src/com/android/managedprovisioning/MessageParser.java b/src/com/android/managedprovisioning/MessageParser.java
index c73685c..d379e86 100644
--- a/src/com/android/managedprovisioning/MessageParser.java
+++ b/src/com/android/managedprovisioning/MessageParser.java
@@ -28,15 +28,18 @@
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PROXY_BYPASS;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PAC_URL;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
-import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER;
-import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION;
import static android.app.admin.DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC;
import static java.nio.charset.StandardCharsets.UTF_8;
+import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
@@ -47,6 +50,8 @@
import android.text.TextUtils;
import android.util.Base64;
+import com.android.managedprovisioning.Utils.IllegalProvisioningArgumentException;
+
import java.io.IOException;
import java.io.StringReader;
import java.util.Enumeration;
@@ -71,8 +76,9 @@
*
* <p>
* Intent was received directly.
- * The intent contains the extra {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME},
- * and may contain {@link #EXTRA_PROVISIONING_TIME_ZONE},
+ * The intent contains the extra {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME} or
+ * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME} (which is deprecated but that we still
+ * support), and may contain {@link #EXTRA_PROVISIONING_TIME_ZONE},
* {@link #EXTRA_PROVISIONING_LOCAL_TIME}, and {@link #EXTRA_PROVISIONING_LOCALE}. A download
* location may be specified in {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}
* together with an optional http cookie header
@@ -108,7 +114,7 @@
EXTRA_PROVISIONING_WIFI_PROXY_HOST,
EXTRA_PROVISIONING_WIFI_PROXY_BYPASS,
EXTRA_PROVISIONING_WIFI_PAC_URL,
- EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,
+ EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION,
EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER,
EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM
@@ -133,6 +139,10 @@
EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE
};
+ protected static final String[] DEVICE_OWNER_COMPONENT_NAME_EXTRAS = {
+ EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME
+ };
+
public void addProvisioningParamsToBundle(Bundle bundle, ProvisioningParams params) {
bundle.putString(EXTRA_PROVISIONING_TIME_ZONE, params.mTimeZone);
bundle.putString(EXTRA_PROVISIONING_LOCALE, params.getLocaleAsString());
@@ -142,8 +152,8 @@
bundle.putString(EXTRA_PROVISIONING_WIFI_PROXY_HOST, params.mWifiProxyHost);
bundle.putString(EXTRA_PROVISIONING_WIFI_PROXY_BYPASS, params.mWifiProxyBypassHosts);
bundle.putString(EXTRA_PROVISIONING_WIFI_PAC_URL, params.mWifiPacUrl);
- bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,
- params.mDeviceAdminPackageName);
+ bundle.putParcelable(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
+ params.mDeviceAdminComponentName);
bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION,
params.mDeviceAdminPackageDownloadLocation);
bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER,
@@ -164,17 +174,18 @@
bundle.putBoolean(EXTRA_PROVISIONING_SKIP_ENCRYPTION, params.mSkipEncryption);
}
- public ProvisioningParams parseIntent(Intent intent) throws ParseException {
+ public ProvisioningParams parseIntent(Intent intent, Context c)
+ throws IllegalProvisioningArgumentException {
ProvisionLogger.logi("Processing intent.");
if (intent.hasExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)) {
- return parseNfcIntent(intent);
+ return parseNfcIntent(intent, c);
} else {
- return parseNonNfcIntent(intent);
+ return parseNonNfcIntent(intent, c);
}
}
- public ProvisioningParams parseNfcIntent(Intent nfcIntent)
- throws ParseException {
+ public ProvisioningParams parseNfcIntent(Intent nfcIntent, Context c)
+ throws IllegalProvisioningArgumentException {
ProvisionLogger.logi("Processing Nfc Payload.");
// Only one first message with NFC_MIME_TYPE is used.
for (Parcelable rawMsg : nfcIntent
@@ -187,21 +198,20 @@
if (MIME_TYPE_PROVISIONING_NFC.equals(mimeType)) {
ProvisioningParams params = parseProperties(new String(firstRecord.getPayload()
- , UTF_8));
+ , UTF_8), c);
params.mStartedByNfc = true;
return params;
}
}
- throw new ParseException(
- "Intent does not contain NfcRecord with the correct MIME type.",
- R.string.device_owner_error_general);
+ throw new IllegalProvisioningArgumentException(
+ "Intent does not contain NfcRecord with the correct MIME type.");
}
// Note: EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE property contains a Properties object
// serialized into String. See Properties.store() and Properties.load() for more details.
// The property value is optional.
- private ProvisioningParams parseProperties(String data)
- throws ParseException {
+ private ProvisioningParams parseProperties(String data, Context c)
+ throws IllegalProvisioningArgumentException {
ProvisioningParams params = new ProvisioningParams();
try {
Properties props = new Properties();
@@ -219,8 +229,7 @@
params.mWifiProxyHost = props.getProperty(EXTRA_PROVISIONING_WIFI_PROXY_HOST);
params.mWifiProxyBypassHosts = props.getProperty(EXTRA_PROVISIONING_WIFI_PROXY_BYPASS);
params.mWifiPacUrl = props.getProperty(EXTRA_PROVISIONING_WIFI_PAC_URL);
- params.mDeviceAdminPackageName
- = props.getProperty(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME);
+ params.mDeviceAdminComponentName = findDeviceAdminFromProperties(props, c);
params.mDeviceAdminPackageDownloadLocation
= props.getProperty(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION);
params.mDeviceAdminPackageDownloadCookieHeader = props.getProperty(
@@ -253,14 +262,11 @@
checkValidityOfProvisioningParams(params);
return params;
} catch (IOException e) {
- throw new ParseException("Couldn't load payload",
- R.string.device_owner_error_general, e);
+ throw new Utils.IllegalProvisioningArgumentException("Couldn't load payload", e);
} catch (NumberFormatException e) {
- throw new ParseException("Incorrect numberformat.",
- R.string.device_owner_error_general, e);
+ throw new Utils.IllegalProvisioningArgumentException("Incorrect numberformat.", e);
} catch (IllformedLocaleException e) {
- throw new ParseException("Invalid locale.",
- R.string.device_owner_error_general, e);
+ throw new Utils.IllegalProvisioningArgumentException("Invalid locale.", e);
}
}
@@ -278,8 +284,8 @@
}
}
- public ProvisioningParams parseNonNfcIntent(Intent intent)
- throws ParseException {
+ public ProvisioningParams parseNonNfcIntent(Intent intent, Context c)
+ throws IllegalProvisioningArgumentException {
ProvisionLogger.logi("Processing intent.");
ProvisioningParams params = new ProvisioningParams();
@@ -294,8 +300,7 @@
params.mWifiProxyHost = intent.getStringExtra(EXTRA_PROVISIONING_WIFI_PROXY_HOST);
params.mWifiProxyBypassHosts = intent.getStringExtra(EXTRA_PROVISIONING_WIFI_PROXY_BYPASS);
params.mWifiPacUrl = intent.getStringExtra(EXTRA_PROVISIONING_WIFI_PAC_URL);
- params.mDeviceAdminPackageName
- = intent.getStringExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME);
+ params.mDeviceAdminComponentName = Utils.findDeviceAdminFromIntent(intent, c);
params.mDeviceAdminPackageDownloadLocation
= intent.getStringExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION);
params.mDeviceAdminPackageDownloadCookieHeader = intent.getStringExtra(
@@ -326,58 +331,42 @@
params.mAdminExtrasBundle = (PersistableBundle) intent.getParcelableExtra(
EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE);
} catch (ClassCastException e) {
- throw new ParseException("Extra " + EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE
- + " must be of type PersistableBundle.",
- R.string.device_owner_error_general, e);
+ throw new IllegalProvisioningArgumentException("Extra "
+ + EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE
+ + " must be of type PersistableBundle.", e);
}
checkValidityOfProvisioningParams(params);
return params;
}
+ private ComponentName findDeviceAdminFromProperties(Properties props, Context c)
+ throws IllegalProvisioningArgumentException {
+ String packageName = props.getProperty(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME);
+ ComponentName component = null;
+ String s;
+ if ((s = props.getProperty(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME)) != null) {
+ component = ComponentName.unflattenFromString(s);
+ }
+ return Utils.findDeviceAdmin(packageName, component, c);
+ }
+
/**
* Check whether necessary fields are set.
*/
private void checkValidityOfProvisioningParams(ProvisioningParams params)
- throws ParseException {
- if (TextUtils.isEmpty(params.mDeviceAdminPackageName)) {
- throw new ParseException("Must provide the name of the device admin package.",
- R.string.device_owner_error_general);
- }
+ throws IllegalProvisioningArgumentException {
+ // The presence of the device admin component name was already checked when calling
+ // Utils.findDeviceAdmin()
if (!TextUtils.isEmpty(params.mDeviceAdminPackageDownloadLocation)) {
if (params.mDeviceAdminPackageChecksum == null ||
params.mDeviceAdminPackageChecksum.length == 0) {
- throw new ParseException("Checksum of installer file is required for downloading " +
- "device admin file, but not provided.",
- R.string.device_owner_error_general);
+ throw new IllegalProvisioningArgumentException("Checksum of installer file is"
+ + " required for downloading device admin file, but not provided.");
}
}
}
- /**
- * Exception thrown when the ProvisioningParams initialization failed completely.
- *
- * Note: We're using a custom exception to avoid catching subsequent exceptions that might be
- * significant.
- */
- public static class ParseException extends Exception {
- private int mErrorMessageId;
-
- public ParseException(String message, int errorMessageId) {
- super(message);
- mErrorMessageId = errorMessageId;
- }
-
- public ParseException(String message, int errorMessageId, Throwable t) {
- super(message, t);
- mErrorMessageId = errorMessageId;
- }
-
- public int getErrorMessageId() {
- return mErrorMessageId;
- }
- }
-
public static byte[] stringToByteArray(String s)
throws NumberFormatException {
try {
diff --git a/src/com/android/managedprovisioning/ProfileOwnerPreProvisioningActivity.java b/src/com/android/managedprovisioning/ProfileOwnerPreProvisioningActivity.java
index 5ad071e..efac6e0 100644
--- a/src/com/android/managedprovisioning/ProfileOwnerPreProvisioningActivity.java
+++ b/src/com/android/managedprovisioning/ProfileOwnerPreProvisioningActivity.java
@@ -17,7 +17,7 @@
package com.android.managedprovisioning;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
-import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
import static com.android.managedprovisioning.EncryptDeviceActivity.EXTRA_RESUME;
import static com.android.managedprovisioning.EncryptDeviceActivity.EXTRA_RESUME_TARGET;
import static com.android.managedprovisioning.EncryptDeviceActivity.TARGET_PROFILE_OWNER;
@@ -29,7 +29,9 @@
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -49,6 +51,7 @@
import android.widget.TextView;
import android.widget.Button;
+import com.android.managedprovisioning.Utils.IllegalProvisioningArgumentException;
import com.android.setupwizard.navigationbar.SetupWizardNavBar;
import com.android.setupwizard.navigationbar.SetupWizardNavBar.NavigationBarListener;
@@ -86,6 +89,8 @@
private String mMdmPackageName;
+ private ComponentName mMdmComponentName;
+
private Button mSetupButton;
@Override
@@ -115,7 +120,7 @@
// Initialize member variables from the intent, stop if the intent wasn't valid.
try {
initialize(getIntent());
- } catch (ProvisioningFailedException e) {
+ } catch (IllegalProvisioningArgumentException e) {
showErrorAndClose(R.string.managed_provisioning_error_text, e.getMessage());
return;
}
@@ -239,30 +244,20 @@
*
* @param intent The intent that started provisioning
*/
- private void initialize(Intent intent) throws ProvisioningFailedException {
+ private void initialize(Intent intent) throws IllegalProvisioningArgumentException {
// Check if the admin extras bundle is of the right type.
try {
PersistableBundle bundle = (PersistableBundle) getIntent().getParcelableExtra(
EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE);
} catch (ClassCastException e) {
- throw new ProvisioningFailedException("Extra "
+ throw new IllegalProvisioningArgumentException("Extra "
+ EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE
+ " must be of type PersistableBundle.", e);
}
- // Validate package name and check if the package is installed
- mMdmPackageName = intent.getStringExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME);
- if (TextUtils.isEmpty(mMdmPackageName)) {
- throw new ProvisioningFailedException("Missing intent extra: "
- + EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME);
- } else {
- try {
- this.getPackageManager().getPackageInfo(mMdmPackageName, 0);
- } catch (NameNotFoundException e) {
- throw new ProvisioningFailedException("Mdm "+ mMdmPackageName
- + " is not installed. ", e);
- }
- }
+ mMdmComponentName = Utils.findDeviceAdminFromIntent(intent, this);
+ mMdmPackageName = mMdmComponentName.getPackageName();
+
}
/**
@@ -278,7 +273,7 @@
UserConsentDialog.newInstance(UserConsentDialog.PROFILE_OWNER)
.show(getFragmentManager(), "UserConsentDialogFragment");
} else {
- Bundle resumeExtras = getIntent().getExtras();
+ Bundle resumeExtras = getNewExtras();
resumeExtras.putString(EXTRA_RESUME_TARGET, TARGET_PROFILE_OWNER);
Intent encryptIntent = new Intent(this, EncryptDeviceActivity.class)
.putExtra(EXTRA_RESUME, resumeExtras);
@@ -318,12 +313,21 @@
private void startProfileOwnerProvisioning() {
Intent intent = new Intent(this, ProfileOwnerProvisioningActivity.class);
- intent.putExtras(getIntent());
+ intent.putExtras(getNewExtras());
startActivityForResult(intent, PROVISIONING_REQUEST_CODE);
// Set cross-fade transition animation into the interstitial progress activity.
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
}
+ private Bundle getNewExtras() {
+ Bundle bundle = getIntent().getExtras();
+ // The original intent may have contained the package name but not the component name.
+ // But now, we know what the component name is. So let's pass it.
+ bundle.putParcelable(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
+ mMdmComponentName);
+ return bundle;
+ }
+
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == ENCRYPT_DEVICE_REQUEST_CODE) {
@@ -437,22 +441,6 @@
.getWindow().getDecorView().setSystemUiVisibility(IMMERSIVE_FLAGS);
}
- /**
- * Exception thrown when the provisioning has failed completely.
- *
- * We're using a custom exception to avoid catching subsequent exceptions that might be
- * significant.
- */
- private class ProvisioningFailedException extends Exception {
- public ProvisioningFailedException(String message) {
- super(message);
- }
-
- public ProvisioningFailedException(String message, Throwable t) {
- super(message, t);
- }
- }
-
@Override
public void onNavigationBarCreated(SetupWizardNavBar bar) {
mSetupButton = bar.getNextButton();
diff --git a/src/com/android/managedprovisioning/ProfileOwnerProvisioningService.java b/src/com/android/managedprovisioning/ProfileOwnerProvisioningService.java
index 0c538f9..ecd32f3 100644
--- a/src/com/android/managedprovisioning/ProfileOwnerProvisioningService.java
+++ b/src/com/android/managedprovisioning/ProfileOwnerProvisioningService.java
@@ -19,7 +19,7 @@
import static android.app.admin.DeviceAdminReceiver.ACTION_PROFILE_PROVISIONING_COMPLETE;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
-import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
import static android.Manifest.permission.BIND_DEVICE_ADMIN;
import android.accounts.Account;
@@ -231,8 +231,10 @@
}
}
- private void initialize(Intent intent) throws ProvisioningException {
- mMdmPackageName = intent.getStringExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME);
+ private void initialize(Intent intent) {
+ mActiveAdminComponentName = (ComponentName) intent.getParcelableExtra(
+ EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME);
+ mMdmPackageName = mActiveAdminComponentName.getPackageName();
mAccountToMigrate = (Account) intent.getParcelableExtra(
EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE);
if (mAccountToMigrate != null) {
@@ -242,31 +244,6 @@
// Cast is guaranteed by check in Activity.
mAdminExtrasBundle = (PersistableBundle) intent.getParcelableExtra(
EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE);
-
- mActiveAdminComponentName = getAdminReceiverComponent(mMdmPackageName);
- }
-
- /**
- * Find the Device admin receiver component from the manifest.
- */
- private ComponentName getAdminReceiverComponent(String packageName)
- throws ProvisioningException {
- try {
- PackageInfo pi = getPackageManager().getPackageInfo(packageName,
- PackageManager.GET_RECEIVERS);
- for (ActivityInfo ai : pi.receivers) {
- if (!TextUtils.isEmpty(ai.permission) &&
- ai.permission.equals(BIND_DEVICE_ADMIN)) {
- return new ComponentName(packageName, ai.name);
- }
- }
-
- throw raiseError("Didn't find admin receiver component with BIND_DEVICE_ADMIN "
- + "permissions");
- } catch (NameNotFoundException e) {
- throw raiseError("Error: The provided mobile device management package does not define "
- + "a device admin receiver component in its manifest.");
- }
}
/**
diff --git a/src/com/android/managedprovisioning/ProvisioningParams.java b/src/com/android/managedprovisioning/ProvisioningParams.java
index cd6374a..16238a6 100644
--- a/src/com/android/managedprovisioning/ProvisioningParams.java
+++ b/src/com/android/managedprovisioning/ProvisioningParams.java
@@ -16,13 +16,13 @@
package com.android.managedprovisioning;
+import android.content.ComponentName;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
import android.util.Base64;
import java.util.Locale;
-
/**
* Provisioning Parameters for DeviceOwner Provisioning
*/
@@ -46,7 +46,7 @@
public String mWifiProxyBypassHosts;
public String mWifiPacUrl;
- public String mDeviceAdminPackageName; // Package name of the device admin package.
+ public ComponentName mDeviceAdminComponentName;
public String mDeviceAdminPackageDownloadLocation; // Url of the device admin .apk
public String mDeviceAdminPackageDownloadCookieHeader; // Cookie header for http request
@@ -59,6 +59,10 @@
public boolean mLeaveAllSystemAppsEnabled;
public boolean mSkipEncryption;
+ public String getDeviceAdminPackageName() {
+ return mDeviceAdminComponentName.getPackageName();
+ }
+
public String getLocaleAsString() {
if (mLocale != null) {
return mLocale.getLanguage() + "_" + mLocale.getCountry();
@@ -89,7 +93,7 @@
out.writeString(mWifiProxyHost);
out.writeInt(mWifiProxyPort);
out.writeString(mWifiProxyBypassHosts);
- out.writeString(mDeviceAdminPackageName);
+ out.writeParcelable(mDeviceAdminComponentName, 0 /* default */);
out.writeString(mDeviceAdminPackageDownloadLocation);
out.writeString(mDeviceAdminPackageDownloadCookieHeader);
out.writeInt(mDeviceAdminPackageChecksum.length);
@@ -115,7 +119,8 @@
params.mWifiProxyHost = in.readString();
params.mWifiProxyPort = in.readInt();
params.mWifiProxyBypassHosts = in.readString();
- params.mDeviceAdminPackageName = in.readString();
+ params.mDeviceAdminComponentName = (ComponentName)
+ in.readParcelable(null /* use default classloader */);
params.mDeviceAdminPackageDownloadLocation = in.readString();
params.mDeviceAdminPackageDownloadCookieHeader = in.readString();
int checksumLength = in.readInt();
diff --git a/src/com/android/managedprovisioning/Utils.java b/src/com/android/managedprovisioning/Utils.java
index a74fdf3..bd05bc5 100644
--- a/src/com/android/managedprovisioning/Utils.java
+++ b/src/com/android/managedprovisioning/Utils.java
@@ -16,12 +16,21 @@
package com.android.managedprovisioning;
-import android.content.ComponentName;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
+
+import android.content.Context;
+import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.ComponentName;
+import android.content.Intent;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.text.TextUtils;
import java.util.List;
import java.util.HashSet;
@@ -65,4 +74,104 @@
+ toDisable.toShortString());
}
}
+
+ public static ComponentName findDeviceAdminFromIntent(Intent intent, Context c)
+ throws IllegalProvisioningArgumentException {
+ ComponentName mdmComponentName = intent.getParcelableExtra(
+ EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME);
+ String mdmPackageName = intent.getStringExtra(
+ EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME);
+ return findDeviceAdmin(mdmPackageName, mdmComponentName, c);
+ }
+
+ /**
+ * Exception thrown when the provisioning has failed completely.
+ *
+ * We're using a custom exception to avoid catching subsequent exceptions that might be
+ * significant.
+ */
+ public static class IllegalProvisioningArgumentException extends Exception {
+ public IllegalProvisioningArgumentException(String message) {
+ super(message);
+ }
+
+ public IllegalProvisioningArgumentException(String message, Throwable t) {
+ super(message, t);
+ }
+ }
+
+ /**
+ * Check the validity of the admin component name supplied, or try to infer this componentName
+ * from the package.
+ *
+ * We are supporting lookup by package name for legacy reasons.
+ *
+ * If mdmComponentName is supplied (not null):
+ * mdmPackageName is ignored.
+ * Check that the package of mdmComponentName is installed, that mdmComponentName is a
+ * receiver in this package, and return it.
+ *
+ * Otherwise:
+ * mdmPackageName must be supplied (not null).
+ * Check that this package is installed, try to infer a potential device admin in this package,
+ * and return it.
+ */
+ public static ComponentName findDeviceAdmin(String mdmPackageName,
+ ComponentName mdmComponentName, Context c) throws IllegalProvisioningArgumentException {
+ if (mdmComponentName != null) {
+ mdmPackageName = mdmComponentName.getPackageName();
+ }
+ if (mdmPackageName == null) {
+ throw new IllegalProvisioningArgumentException("Neither the package name nor the"
+ + " component name of the admin are supplied");
+ }
+ PackageInfo pi;
+ try {
+ pi = c.getPackageManager().getPackageInfo(mdmPackageName,
+ PackageManager.GET_RECEIVERS);
+ } catch (NameNotFoundException e) {
+ throw new IllegalProvisioningArgumentException("Mdm "+ mdmPackageName
+ + " is not installed. ", e);
+ }
+ if (mdmComponentName != null) {
+ // If the component was specified in the intent: check that it is in the manifest.
+ checkAdminComponent(mdmComponentName, pi);
+ return mdmComponentName;
+ } else {
+ // Otherwise: try to find a potential device admin in the manifest.
+ return findDeviceAdminInPackage(mdmPackageName, pi);
+ }
+ }
+
+ private static void checkAdminComponent(ComponentName mdmComponentName, PackageInfo pi)
+ throws IllegalProvisioningArgumentException{
+ for (ActivityInfo ai : pi.receivers) {
+ if (mdmComponentName.getClassName().equals(ai.name)) {
+ return;
+ }
+ }
+ throw new IllegalProvisioningArgumentException("The component " + mdmComponentName
+ + " cannot be found");
+ }
+
+ private static ComponentName findDeviceAdminInPackage(String mdmPackageName, PackageInfo pi)
+ throws IllegalProvisioningArgumentException {
+ ComponentName mdmComponentName = null;
+ for (ActivityInfo ai : pi.receivers) {
+ if (!TextUtils.isEmpty(ai.permission) &&
+ ai.permission.equals(android.Manifest.permission.BIND_DEVICE_ADMIN)) {
+ if (mdmComponentName != null) {
+ throw new IllegalProvisioningArgumentException("There are several "
+ + "device admins in " + mdmPackageName + " but no one in specified");
+ } else {
+ mdmComponentName = new ComponentName(mdmPackageName, ai.name);
+ }
+ }
+ }
+ if (mdmComponentName == null) {
+ throw new IllegalProvisioningArgumentException("There are no device admins in"
+ + mdmPackageName);
+ }
+ return mdmComponentName;
+ }
}
diff --git a/src/com/android/managedprovisioning/task/SetDevicePolicyTask.java b/src/com/android/managedprovisioning/task/SetDevicePolicyTask.java
index 7fe13bd..29b8a96 100644
--- a/src/com/android/managedprovisioning/task/SetDevicePolicyTask.java
+++ b/src/com/android/managedprovisioning/task/SetDevicePolicyTask.java
@@ -35,18 +35,19 @@
private final Callback mCallback;
private final Context mContext;
- private final String mPackageName;
+ private final String mAdminPackage;
+ private final ComponentName mAdminComponent;
private final String mOwner;
- private String mAdminReceiver;
private PackageManager mPackageManager;
private DevicePolicyManager mDevicePolicyManager;
- public SetDevicePolicyTask(Context context, String packageName, String owner,
+ public SetDevicePolicyTask(Context context, ComponentName adminComponent, String owner,
Callback callback) {
mCallback = callback;
mContext = context;
- mPackageName = packageName;
+ mAdminComponent = adminComponent;
+ mAdminPackage = adminComponent.getPackageName();
mOwner = owner;
mPackageManager = mContext.getPackageManager();
mDevicePolicyManager = (DevicePolicyManager) mContext.
@@ -54,53 +55,30 @@
}
public void run() {
- // Check whether package is installed and find the admin receiver.
- if (isPackageInstalled()) {
- enableDevicePolicyApp();
- setActiveAdmin();
- setDeviceOwner();
- mCallback.onSuccess();
- }
- }
-
- private boolean isPackageInstalled() {
- try {
- PackageInfo pi = mPackageManager.getPackageInfo(mPackageName,
- PackageManager.GET_RECEIVERS);
- for (ActivityInfo ai : pi.receivers) {
- if (!TextUtils.isEmpty(ai.permission) &&
- ai.permission.equals(android.Manifest.permission.BIND_DEVICE_ADMIN)) {
- mAdminReceiver = ai.name;
- return true;
- }
- }
- mCallback.onError(ERROR_NO_RECEIVER);
- return false;
- } catch (NameNotFoundException e) {
- mCallback.onError(ERROR_PACKAGE_NOT_INSTALLED);
- return false;
- }
+ enableDevicePolicyApp();
+ setActiveAdmin();
+ setDeviceOwner();
+ mCallback.onSuccess();
}
private void enableDevicePolicyApp() {
int enabledSetting = mPackageManager
- .getApplicationEnabledSetting(mPackageName);
+ .getApplicationEnabledSetting(mAdminPackage);
if (enabledSetting != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
- mPackageManager.setApplicationEnabledSetting(mPackageName,
+ mPackageManager.setApplicationEnabledSetting(mAdminPackage,
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0);
}
}
public void setActiveAdmin() {
- ProvisionLogger.logd("Setting " + mPackageName + " as active admin.");
- ComponentName component = new ComponentName(mPackageName, mAdminReceiver);
- mDevicePolicyManager.setActiveAdmin(component, true);
+ ProvisionLogger.logd("Setting " + mAdminComponent + " as active admin.");
+ mDevicePolicyManager.setActiveAdmin(mAdminComponent, true);
}
public void setDeviceOwner() {
- ProvisionLogger.logd("Setting " + mPackageName + " as device owner " + mOwner + ".");
- if (!mDevicePolicyManager.isDeviceOwner(mPackageName)) {
- mDevicePolicyManager.setDeviceOwner(mPackageName, mOwner);
+ ProvisionLogger.logd("Setting " + mAdminPackage + " as device owner " + mOwner + ".");
+ if (!mDevicePolicyManager.isDeviceOwner(mAdminPackage)) {
+ mDevicePolicyManager.setDeviceOwner(mAdminPackage, mOwner);
}
}