Merge "Allow the device initializer to perform user setup tasks."
This commit is contained in:
committed by
Android (Google) Code Review
commit
aa7e7318e3
@@ -5429,6 +5429,7 @@ package android.app.admin {
|
||||
method public void onPasswordFailed(android.content.Context, android.content.Intent);
|
||||
method public void onPasswordSucceeded(android.content.Context, android.content.Intent);
|
||||
method public void onProfileProvisioningComplete(android.content.Context, android.content.Intent);
|
||||
method public void onReadyForUserInitialization(android.content.Context, android.content.Intent);
|
||||
method public void onReceive(android.content.Context, android.content.Intent);
|
||||
field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED";
|
||||
field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED";
|
||||
@@ -5440,6 +5441,7 @@ package android.app.admin {
|
||||
field public static final java.lang.String ACTION_PASSWORD_FAILED = "android.app.action.ACTION_PASSWORD_FAILED";
|
||||
field public static final java.lang.String ACTION_PASSWORD_SUCCEEDED = "android.app.action.ACTION_PASSWORD_SUCCEEDED";
|
||||
field public static final java.lang.String ACTION_PROFILE_PROVISIONING_COMPLETE = "android.app.action.PROFILE_PROVISIONING_COMPLETE";
|
||||
field public static final java.lang.String ACTION_READY_FOR_USER_INITIALIZATION = "android.app.action.READY_FOR_USER_INITIALIZATION";
|
||||
field public static final java.lang.String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
|
||||
field public static final java.lang.String EXTRA_DISABLE_WARNING = "android.app.extra.DISABLE_WARNING";
|
||||
field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
|
||||
@@ -5451,6 +5453,7 @@ package android.app.admin {
|
||||
method public void addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName);
|
||||
method public void addUserRestriction(android.content.ComponentName, java.lang.String);
|
||||
method public void clearCrossProfileIntentFilters(android.content.ComponentName);
|
||||
method public void clearDeviceInitializerApp();
|
||||
method public void clearDeviceOwnerApp(java.lang.String);
|
||||
method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
|
||||
method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
|
||||
@@ -5489,11 +5492,13 @@ package android.app.admin {
|
||||
method public int getStorageEncryptionStatus();
|
||||
method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]);
|
||||
method public boolean hasGrantedPolicy(android.content.ComponentName, int);
|
||||
method public boolean hasUserSetupCompleted();
|
||||
method public boolean installCaCert(android.content.ComponentName, byte[]);
|
||||
method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, java.lang.String);
|
||||
method public boolean isActivePasswordSufficient();
|
||||
method public boolean isAdminActive(android.content.ComponentName);
|
||||
method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String);
|
||||
method public boolean isDeviceInitializerApp(java.lang.String);
|
||||
method public boolean isDeviceOwnerApp(java.lang.String);
|
||||
method public boolean isLockTaskPermitted(java.lang.String);
|
||||
method public boolean isMasterVolumeMuted(android.content.ComponentName);
|
||||
@@ -5510,6 +5515,7 @@ package android.app.admin {
|
||||
method public void setAutoTimeRequired(android.content.ComponentName, boolean);
|
||||
method public void setCameraDisabled(android.content.ComponentName, boolean);
|
||||
method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
|
||||
method public boolean setDeviceInitializer(android.content.ComponentName, android.content.ComponentName, java.lang.String) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
|
||||
method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
|
||||
method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
|
||||
method public void setLockTaskPackages(android.content.ComponentName, java.lang.String[]) throws java.lang.SecurityException;
|
||||
@@ -5536,6 +5542,7 @@ package android.app.admin {
|
||||
method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
|
||||
method public int setStorageEncryption(android.content.ComponentName, boolean);
|
||||
method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean);
|
||||
method public boolean setUserEnabled(android.content.ComponentName);
|
||||
method public boolean switchUser(android.content.ComponentName, android.os.UserHandle);
|
||||
method public void uninstallAllUserCaCerts(android.content.ComponentName);
|
||||
method public void uninstallCaCert(android.content.ComponentName, byte[]);
|
||||
@@ -5557,6 +5564,10 @@ package android.app.admin {
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME";
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM";
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER";
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION";
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.PROVISIONING_EMAIL_ADDRESS";
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
|
||||
|
||||
@@ -5523,6 +5523,7 @@ package android.app.admin {
|
||||
method public void onPasswordFailed(android.content.Context, android.content.Intent);
|
||||
method public void onPasswordSucceeded(android.content.Context, android.content.Intent);
|
||||
method public void onProfileProvisioningComplete(android.content.Context, android.content.Intent);
|
||||
method public void onReadyForUserInitialization(android.content.Context, android.content.Intent);
|
||||
method public void onReceive(android.content.Context, android.content.Intent);
|
||||
field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED";
|
||||
field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED";
|
||||
@@ -5534,6 +5535,7 @@ package android.app.admin {
|
||||
field public static final java.lang.String ACTION_PASSWORD_FAILED = "android.app.action.ACTION_PASSWORD_FAILED";
|
||||
field public static final java.lang.String ACTION_PASSWORD_SUCCEEDED = "android.app.action.ACTION_PASSWORD_SUCCEEDED";
|
||||
field public static final java.lang.String ACTION_PROFILE_PROVISIONING_COMPLETE = "android.app.action.PROFILE_PROVISIONING_COMPLETE";
|
||||
field public static final java.lang.String ACTION_READY_FOR_USER_INITIALIZATION = "android.app.action.READY_FOR_USER_INITIALIZATION";
|
||||
field public static final java.lang.String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
|
||||
field public static final java.lang.String EXTRA_DISABLE_WARNING = "android.app.extra.DISABLE_WARNING";
|
||||
field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
|
||||
@@ -5545,6 +5547,7 @@ package android.app.admin {
|
||||
method public void addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName);
|
||||
method public void addUserRestriction(android.content.ComponentName, java.lang.String);
|
||||
method public void clearCrossProfileIntentFilters(android.content.ComponentName);
|
||||
method public void clearDeviceInitializerApp();
|
||||
method public void clearDeviceOwnerApp(java.lang.String);
|
||||
method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
|
||||
method public void clearProfileOwner(android.content.ComponentName);
|
||||
@@ -5561,6 +5564,7 @@ package android.app.admin {
|
||||
method public boolean getCrossProfileCallerIdDisabled(android.content.ComponentName);
|
||||
method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName);
|
||||
method public int getCurrentFailedPasswordAttempts();
|
||||
method public java.lang.String getDeviceInitializerApp();
|
||||
method public java.lang.String getDeviceOwner();
|
||||
method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
|
||||
method public int getKeyguardDisabledFeatures(android.content.ComponentName);
|
||||
@@ -5589,11 +5593,13 @@ package android.app.admin {
|
||||
method public int getStorageEncryptionStatus();
|
||||
method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]);
|
||||
method public boolean hasGrantedPolicy(android.content.ComponentName, int);
|
||||
method public boolean hasUserSetupCompleted();
|
||||
method public boolean installCaCert(android.content.ComponentName, byte[]);
|
||||
method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, java.lang.String);
|
||||
method public boolean isActivePasswordSufficient();
|
||||
method public boolean isAdminActive(android.content.ComponentName);
|
||||
method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String);
|
||||
method public boolean isDeviceInitializerApp(java.lang.String);
|
||||
method public boolean isDeviceOwnerApp(java.lang.String);
|
||||
method public boolean isLockTaskPermitted(java.lang.String);
|
||||
method public boolean isMasterVolumeMuted(android.content.ComponentName);
|
||||
@@ -5611,6 +5617,7 @@ package android.app.admin {
|
||||
method public void setAutoTimeRequired(android.content.ComponentName, boolean);
|
||||
method public void setCameraDisabled(android.content.ComponentName, boolean);
|
||||
method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
|
||||
method public boolean setDeviceInitializer(android.content.ComponentName, android.content.ComponentName, java.lang.String) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
|
||||
method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
|
||||
method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
|
||||
method public void setLockTaskPackages(android.content.ComponentName, java.lang.String[]) throws java.lang.SecurityException;
|
||||
@@ -5637,6 +5644,7 @@ package android.app.admin {
|
||||
method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
|
||||
method public int setStorageEncryption(android.content.ComponentName, boolean);
|
||||
method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean);
|
||||
method public boolean setUserEnabled(android.content.ComponentName);
|
||||
method public boolean switchUser(android.content.ComponentName, android.os.UserHandle);
|
||||
method public void uninstallAllUserCaCerts(android.content.ComponentName);
|
||||
method public void uninstallCaCert(android.content.ComponentName, byte[]);
|
||||
@@ -5660,6 +5668,10 @@ package android.app.admin {
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME";
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM";
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER";
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION";
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.PROVISIONING_EMAIL_ADDRESS";
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
|
||||
field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
|
||||
|
||||
@@ -215,7 +215,8 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* <p>A device admin application which listens to this intent can find out if the device was
|
||||
* provisioned for the device owner or profile owner case by calling respectively
|
||||
* {@link android.app.admin.DevicePolicyManager#isDeviceOwnerApp} and
|
||||
* {@link android.app.admin.DevicePolicyManager#isProfileOwnerApp}.
|
||||
* {@link android.app.admin.DevicePolicyManager#isProfileOwnerApp}. You will generally handle
|
||||
* this in {@link DeviceAdminReceiver#onProfileProvisioningComplete}.
|
||||
*
|
||||
* <p>Input: Nothing.</p>
|
||||
* <p>Output: Nothing</p>
|
||||
@@ -224,6 +225,23 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
public static final String ACTION_PROFILE_PROVISIONING_COMPLETE =
|
||||
"android.app.action.PROFILE_PROVISIONING_COMPLETE";
|
||||
|
||||
/**
|
||||
* Broadcast Action: This broadcast is sent to indicate that the system is ready for the device
|
||||
* initializer to perform user setup tasks. This is only applicable to devices managed by a
|
||||
* device owner app.
|
||||
*
|
||||
* <p>The broadcast will be limited to the {@link DeviceAdminReceiver} component specified in
|
||||
* the (@link DevicePolicyManager#EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME) field
|
||||
* of the original intent or NFC bump that started the provisioning process. You will generally
|
||||
* handle this in {@link DeviceAdminReceiver#onReadyForUserInitialization}.
|
||||
*
|
||||
* <p>Input: Nothing.</p>
|
||||
* <p>Output: Nothing</p>
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
public static final String ACTION_READY_FOR_USER_INITIALIZATION =
|
||||
"android.app.action.READY_FOR_USER_INITIALIZATION";
|
||||
|
||||
/** @hide */
|
||||
public static final String ACTION_CHOOSE_PRIVATE_KEY_ALIAS = "android.app.action.CHOOSE_PRIVATE_KEY_ALIAS";
|
||||
|
||||
@@ -245,7 +263,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
/** @hide */
|
||||
public static final String EXTRA_CHOOSE_PRIVATE_KEY_RESPONSE = "android.app.extra.CHOOSE_PRIVATE_KEY_RESPONSE";
|
||||
|
||||
/**
|
||||
/**
|
||||
* Name under which a DevicePolicy component publishes information
|
||||
* about itself. This meta-data must reference an XML resource containing
|
||||
* a device-admin tag.
|
||||
@@ -382,20 +400,20 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
/**
|
||||
* Called when provisioning of a managed profile or managed device has completed successfully.
|
||||
*
|
||||
* <p> As a prerequisit for the execution of this callback the (@link DeviceAdminReceiver} has
|
||||
* <p> As a prerequisite for the execution of this callback the {@link DeviceAdminReceiver} has
|
||||
* to declare an intent filter for {@link #ACTION_PROFILE_PROVISIONING_COMPLETE}.
|
||||
* Its component must also be specified in the {@link DevicePolicyManager#EXTRA_DEVICE_ADMIN}
|
||||
* of the {@link DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE} intent that started the
|
||||
* managed provisioning.
|
||||
*
|
||||
* <p>When provisioning is complete, the managed profile is hidden until the profile owner
|
||||
* calls {DevicePolicyManager#setProfileEnabled(ComponentName admin)}. Typically a profile
|
||||
* owner will enable the profile when it has finished any additional setup such as adding an
|
||||
* account by using the {@link AccountManager} and calling apis to bring the profile into the
|
||||
* desired state.
|
||||
* <p>When provisioning of a managed profile is complete, the managed profile is hidden until
|
||||
* the profile owner calls {DevicePolicyManager#setProfileEnabled(ComponentName admin)}.
|
||||
* Typically a profile owner will enable the profile when it has finished any additional setup
|
||||
* such as adding an account by using the {@link AccountManager} and calling apis to bring the
|
||||
* profile into the desired state.
|
||||
*
|
||||
* <p> Note that provisioning completes without waiting for any server interactions, so the
|
||||
* profile owner needs to wait for data to be available if required (e.g android device ids or
|
||||
* profile owner needs to wait for data to be available if required (e.g. android device ids or
|
||||
* other data that is set as a result of server interactions).
|
||||
*
|
||||
* @param context The running context as per {@link #onReceive}.
|
||||
@@ -404,6 +422,30 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
public void onProfileProvisioningComplete(Context context, Intent intent) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called during provisioning of a managed device to allow the device initializer to perform
|
||||
* user setup steps. Only device initializers should override this method.
|
||||
*
|
||||
* <p> Called when the DeviceAdminReceiver receives a
|
||||
* {@link #ACTION_READY_FOR_USER_INITIALIZATION} broadcast. As a prerequisite for the execution
|
||||
* of this callback the {@link DeviceAdminReceiver} has
|
||||
* to declare an intent filter for {@link #ACTION_READY_FOR_USER_INITIALIZATION}. Only the
|
||||
* component specified in the
|
||||
* {@link DevicePolicyManager#EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME} field of the
|
||||
* original intent or NFC bump that started the provisioning process will receive this callback.
|
||||
*
|
||||
* <p>It is not assumed that the device initializer is finished when it returns from
|
||||
* this call, as it may do additional setup asynchronously. The device initializer must call
|
||||
* {DevicePolicyManager#setUserEnabled(ComponentName admin)} when it has finished any additional
|
||||
* setup (such as adding an account by using the {@link AccountManager}) in order for the user
|
||||
* to be functional.
|
||||
*
|
||||
* @param context The running context as per {@link #onReceive}.
|
||||
* @param intent The received intent as per {@link #onReceive}.
|
||||
*/
|
||||
public void onReadyForUserInitialization(Context context, Intent intent) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a device is entering lock task mode by a package authorized
|
||||
* by {@link DevicePolicyManager#isLockTaskPermitted(String)}
|
||||
@@ -488,6 +530,8 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
onLockTaskModeEntering(context, intent, pkg);
|
||||
} else if (ACTION_LOCK_TASK_EXITING.equals(action)) {
|
||||
onLockTaskModeExiting(context, intent);
|
||||
} else if (ACTION_READY_FOR_USER_INITIALIZATION.equals(action)) {
|
||||
onReadyForUserInitialization(context, intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,6 +356,52 @@ public class DevicePolicyManager {
|
||||
public static final String EXTRA_PROVISIONING_SKIP_ENCRYPTION =
|
||||
"android.app.extra.PROVISIONING_SKIP_ENCRYPTION";
|
||||
|
||||
/**
|
||||
* On devices managed by a device owner app, a String representation of a Component name extra
|
||||
* indicating the component of the application that is temporarily granted device owner
|
||||
* privileges during device initialization and profile owner privileges during secondary user
|
||||
* initialization.
|
||||
*
|
||||
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
|
||||
* provisioning via an NFC bump.
|
||||
* @see ComponentName#unflattenFromString()
|
||||
*/
|
||||
public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME
|
||||
= "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME";
|
||||
|
||||
/**
|
||||
* A String extra holding an http url that specifies the download location of the device
|
||||
* initializer package. When not provided it is assumed that the device initializer package is
|
||||
* already installed.
|
||||
*
|
||||
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
|
||||
* provisioning via an NFC bump.
|
||||
*/
|
||||
public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION
|
||||
= "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION";
|
||||
|
||||
/**
|
||||
* A String extra holding a http cookie header which should be used in the http request to the
|
||||
* url specified in {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}.
|
||||
*
|
||||
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
|
||||
* provisioning via an NFC bump.
|
||||
*/
|
||||
public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER
|
||||
= "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER";
|
||||
|
||||
/**
|
||||
* A String extra holding the SHA-1 checksum of the file at download location specified in
|
||||
* {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}. If this doesn't
|
||||
* match the file at the download location an error will be shown to the user and the user will
|
||||
* be asked to factory reset the device.
|
||||
*
|
||||
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
|
||||
* provisioning via an NFC bump.
|
||||
*/
|
||||
public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM
|
||||
= "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM";
|
||||
|
||||
/**
|
||||
* This MIME type is used for starting the Device Owner provisioning.
|
||||
*
|
||||
@@ -2381,6 +2427,112 @@ public class DevicePolicyManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given component as the device initializer. The package must already be installed and
|
||||
* set as an active device administrator, and there must not be an existing device initializer,
|
||||
* for this call to succeed. This method can only be called by an app holding the
|
||||
* MANAGE_DEVICE_ADMINS permission before the device is provisioned or by a device owner app. A
|
||||
* device initializer app is granted device owner privileges during device initialization and
|
||||
* profile owner privileges during secondary user initialization.
|
||||
* @param who Which {@link DeviceAdminReceiver} this request is associated with, or null if not
|
||||
* called by the device owner.
|
||||
* @param initializer Which {@link DeviceAdminReceiver} to make device initializer.
|
||||
* @param initializerName The user-visible name of the device initializer.
|
||||
* @return whether the package was successfully registered as the device initializer.
|
||||
* @throws IllegalArgumentException if the package name is null or invalid
|
||||
* @throws IllegalStateException if the caller is not device owner or the device has
|
||||
* already been provisioned or a device initializer already exists.
|
||||
*/
|
||||
public boolean setDeviceInitializer(ComponentName who, ComponentName initializer,
|
||||
String initializerName) throws IllegalArgumentException, IllegalStateException {
|
||||
if (mService != null) {
|
||||
try {
|
||||
return mService.setDeviceInitializer(who, initializer, initializerName);
|
||||
} catch (RemoteException re) {
|
||||
Log.w(TAG, "Failed to set device initializer");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine if a particular package has been registered as the device initializer.
|
||||
*
|
||||
* @param packageName the package name of the app, to compare with the registered device
|
||||
* initializer app, if any.
|
||||
* @return whether or not the caller is registered as the device initializer app.
|
||||
*/
|
||||
public boolean isDeviceInitializerApp(String packageName) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
return mService.isDeviceInitializer(packageName);
|
||||
} catch (RemoteException re) {
|
||||
Log.w(TAG, "Failed to check device initializer");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the current device initializer. The caller must be the device initializer.
|
||||
*
|
||||
* This function should be used cautiously as once it is called it cannot
|
||||
* be undone.
|
||||
*/
|
||||
public void clearDeviceInitializerApp() {
|
||||
if (mService != null) {
|
||||
try {
|
||||
mService.clearDeviceInitializer(mContext.getPackageName());
|
||||
} catch (RemoteException re) {
|
||||
Log.w(TAG, "Failed to clear device initializer");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Gets the device initializer of the system.
|
||||
*
|
||||
* @return the package name of the device initializer.
|
||||
*/
|
||||
@SystemApi
|
||||
public String getDeviceInitializerApp() {
|
||||
if (mService != null) {
|
||||
try {
|
||||
return mService.getDeviceInitializer();
|
||||
} catch (RemoteException re) {
|
||||
Log.w(TAG, "Failed to get device initializer");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the enabled state of the user. A user should be enabled only once it is ready to
|
||||
* be used.
|
||||
*
|
||||
* <p>Device initializer must call this method to mark the user as functional.
|
||||
* Only the device initializer agent can call this.
|
||||
*
|
||||
* <p>When the user is enabled, if the device initializer is not also the device owner, the
|
||||
* device initializer will no longer have elevated permissions to call methods in this class.
|
||||
* Additionally, it will be removed as an active administrator and its
|
||||
* {@link DeviceAdminReceiver} will be disabled.
|
||||
*
|
||||
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
|
||||
* @return whether the user is now enabled.
|
||||
*/
|
||||
public boolean setUserEnabled(ComponentName admin) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
return mService.setUserEnabled(admin);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed talking with device policy service", e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* @deprecated Use #ACTION_SET_PROFILE_OWNER
|
||||
@@ -2434,7 +2586,6 @@ public class DevicePolicyManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Checks if the user was already setup.
|
||||
*/
|
||||
public boolean hasUserSetupCompleted() {
|
||||
@@ -3119,8 +3270,7 @@ public class DevicePolicyManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by a profile or device owner to set a user restriction specified
|
||||
* by the key.
|
||||
* Called by a profile or device owner to set a user restriction specified by the key.
|
||||
* <p>
|
||||
* The calling device admin must be a profile or device owner; if it is not,
|
||||
* a security exception will be thrown.
|
||||
@@ -3141,8 +3291,7 @@ public class DevicePolicyManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by a profile or device owner to clear a user restriction specified
|
||||
* by the key.
|
||||
* Called by a profile or device owner to clear a user restriction specified by the key.
|
||||
* <p>
|
||||
* The calling device admin must be a profile or device owner; if it is not,
|
||||
* a security exception will be thrown.
|
||||
@@ -3163,7 +3312,7 @@ public class DevicePolicyManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by device or profile owner to hide or unhide packages. When a package is hidden it
|
||||
* Called by profile or device owners to hide or unhide packages. When a package is hidden it
|
||||
* is unavailable for use, but the data and actual package file remain.
|
||||
*
|
||||
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
|
||||
@@ -3185,7 +3334,7 @@ public class DevicePolicyManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by device or profile owner to determine if a package is hidden.
|
||||
* Called by profile or device owners to determine if a package is hidden.
|
||||
*
|
||||
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
|
||||
* @param packageName The name of the package to retrieve the hidden status of.
|
||||
@@ -3203,7 +3352,7 @@ public class DevicePolicyManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by profile or device owner to re-enable a system app that was disabled by default
|
||||
* Called by profile or device owners to re-enable a system app that was disabled by default
|
||||
* when the user was initialized.
|
||||
*
|
||||
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
|
||||
@@ -3220,7 +3369,7 @@ public class DevicePolicyManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by profile or device owner to re-enable system apps by intent that were disabled
|
||||
* Called by profile or device owners to re-enable system apps by intent that were disabled
|
||||
* by default when the user was initialized.
|
||||
*
|
||||
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
|
||||
|
||||
@@ -199,4 +199,10 @@ interface IDevicePolicyManager {
|
||||
boolean getAutoTimeRequired();
|
||||
|
||||
boolean isRemovingAdmin(in ComponentName adminReceiver, int userHandle);
|
||||
|
||||
boolean setUserEnabled(in ComponentName who);
|
||||
boolean isDeviceInitializer(String packageName);
|
||||
void clearDeviceInitializer(String packageName);
|
||||
boolean setDeviceInitializer(in ComponentName who, in ComponentName initializer, String initializerName);
|
||||
String getDeviceInitializer();
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ class DeviceOwner {
|
||||
|
||||
private static final String DEVICE_OWNER_XML = "device_owner.xml";
|
||||
private static final String TAG_DEVICE_OWNER = "device-owner";
|
||||
private static final String TAG_DEVICE_INITIALIZER = "device-initializer";
|
||||
private static final String TAG_PROFILE_OWNER = "profile-owner";
|
||||
private static final String ATTR_NAME = "name";
|
||||
private static final String ATTR_PACKAGE = "package";
|
||||
@@ -68,6 +69,9 @@ class DeviceOwner {
|
||||
// Internal state for the device owner package.
|
||||
private OwnerInfo mDeviceOwner;
|
||||
|
||||
// Internal state for the device initializer package.
|
||||
private OwnerInfo mDeviceInitializer;
|
||||
|
||||
// Internal state for the profile owner packages.
|
||||
private final HashMap<Integer, OwnerInfo> mProfileOwners = new HashMap<Integer, OwnerInfo>();
|
||||
|
||||
@@ -103,6 +107,15 @@ class DeviceOwner {
|
||||
return owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of the device owner object with the device initializer set.
|
||||
*/
|
||||
static DeviceOwner createWithDeviceInitializer(String packageName, String ownerName) {
|
||||
DeviceOwner owner = new DeviceOwner();
|
||||
owner.mDeviceInitializer = new OwnerInfo(ownerName, packageName);
|
||||
return owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of the device owner object with the profile owner set.
|
||||
*/
|
||||
@@ -128,6 +141,26 @@ class DeviceOwner {
|
||||
mDeviceOwner = null;
|
||||
}
|
||||
|
||||
String getDeviceInitializerPackageName() {
|
||||
return mDeviceInitializer != null ? mDeviceInitializer.packageName : null;
|
||||
}
|
||||
|
||||
String getDeviceInitializerName() {
|
||||
return mDeviceInitializer != null ? mDeviceInitializer.name : null;
|
||||
}
|
||||
|
||||
void setDeviceInitializer(String packageName, String ownerName) {
|
||||
mDeviceInitializer = new OwnerInfo(ownerName, packageName);
|
||||
}
|
||||
|
||||
void clearDeviceInitializer() {
|
||||
mDeviceInitializer = null;
|
||||
}
|
||||
|
||||
boolean hasDeviceInitializer() {
|
||||
return mDeviceInitializer != null;
|
||||
}
|
||||
|
||||
void setProfileOwner(ComponentName admin, String ownerName, int userId) {
|
||||
mProfileOwners.put(userId, new OwnerInfo(ownerName, admin));
|
||||
}
|
||||
@@ -199,6 +232,10 @@ class DeviceOwner {
|
||||
String name = parser.getAttributeValue(null, ATTR_NAME);
|
||||
String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
|
||||
mDeviceOwner = new OwnerInfo(name, packageName);
|
||||
} else if (tag.equals(TAG_DEVICE_INITIALIZER)) {
|
||||
String name = parser.getAttributeValue(null, ATTR_NAME);
|
||||
String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
|
||||
mDeviceInitializer = new OwnerInfo(name, packageName);
|
||||
} else if (tag.equals(TAG_PROFILE_OWNER)) {
|
||||
String profileOwnerPackageName = parser.getAttributeValue(null, ATTR_PACKAGE);
|
||||
String profileOwnerName = parser.getAttributeValue(null, ATTR_NAME);
|
||||
@@ -259,6 +296,16 @@ class DeviceOwner {
|
||||
out.endTag(null, TAG_DEVICE_OWNER);
|
||||
}
|
||||
|
||||
// Write device initializer tag
|
||||
if (mDeviceInitializer != null) {
|
||||
out.startTag(null, TAG_DEVICE_INITIALIZER);
|
||||
out.attribute(null, ATTR_PACKAGE, mDeviceInitializer.packageName);
|
||||
if (mDeviceInitializer.name != null) {
|
||||
out.attribute(null, ATTR_NAME, mDeviceInitializer.name);
|
||||
}
|
||||
out.endTag(null, TAG_DEVICE_INITIALIZER);
|
||||
}
|
||||
|
||||
// Write profile owner tags
|
||||
if (mProfileOwners.size() > 0) {
|
||||
for (HashMap.Entry<Integer, OwnerInfo> owner : mProfileOwners.entrySet()) {
|
||||
|
||||
@@ -1139,13 +1139,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
boolean ownsProfile = (getProfileOwner(userHandle) != null
|
||||
&& getProfileOwner(userHandle).getPackageName()
|
||||
.equals(admin.info.getPackageName()));
|
||||
boolean ownsInitialization = isDeviceInitializer(admin.info.getPackageName())
|
||||
&& !hasUserSetupCompleted(userHandle);
|
||||
|
||||
if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
|
||||
if (ownsDevice) {
|
||||
if (ownsDevice || (userHandle == UserHandle.USER_OWNER && ownsInitialization)) {
|
||||
return admin;
|
||||
}
|
||||
} else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
|
||||
if (ownsDevice || ownsProfile) {
|
||||
if (ownsDevice || ownsProfile || ownsInitialization) {
|
||||
return admin;
|
||||
}
|
||||
} else {
|
||||
@@ -1899,7 +1901,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
return;
|
||||
}
|
||||
if (admin.getUid() != Binder.getCallingUid()) {
|
||||
// If trying to remove device owner, refuse when the caller is not the owner.
|
||||
// Active device owners must remain active admins.
|
||||
if (isDeviceOwner(adminReceiver.getPackageName())) {
|
||||
return;
|
||||
}
|
||||
@@ -3865,6 +3867,112 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setDeviceInitializer(ComponentName who, ComponentName initializer,
|
||||
String ownerName) {
|
||||
if (!mHasFeature) {
|
||||
return false;
|
||||
}
|
||||
if (initializer == null || !DeviceOwner.isInstalled(
|
||||
initializer.getPackageName(), mContext.getPackageManager())) {
|
||||
throw new IllegalArgumentException("Invalid component name " + initializer
|
||||
+ " for device initializer");
|
||||
}
|
||||
synchronized (this) {
|
||||
enforceCanSetDeviceInitializer(who);
|
||||
|
||||
if (mDeviceOwner != null && mDeviceOwner.hasDeviceInitializer()) {
|
||||
throw new IllegalStateException(
|
||||
"Trying to set device initializer but device initializer is already set.");
|
||||
}
|
||||
|
||||
if (mDeviceOwner == null) {
|
||||
// Device owner state does not exist, create it.
|
||||
mDeviceOwner = DeviceOwner.createWithDeviceInitializer(
|
||||
initializer.getPackageName(), ownerName);
|
||||
mDeviceOwner.writeOwnerFile();
|
||||
return true;
|
||||
} else {
|
||||
// Device owner already exists, update it.
|
||||
mDeviceOwner.setDeviceInitializer(initializer.getPackageName(), ownerName);
|
||||
mDeviceOwner.writeOwnerFile();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void enforceCanSetDeviceInitializer(ComponentName who) {
|
||||
if (who == null) {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
android.Manifest.permission.MANAGE_DEVICE_ADMINS, null);
|
||||
if (hasUserSetupCompleted(UserHandle.USER_OWNER)) {
|
||||
throw new IllegalStateException(
|
||||
"Trying to set device initializer but device is already provisioned.");
|
||||
}
|
||||
} else {
|
||||
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeviceInitializer(String packageName) {
|
||||
if (!mHasFeature) {
|
||||
return false;
|
||||
}
|
||||
synchronized (this) {
|
||||
return mDeviceOwner != null
|
||||
&& mDeviceOwner.hasDeviceInitializer()
|
||||
&& mDeviceOwner.getDeviceInitializerPackageName().equals(packageName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeviceInitializer() {
|
||||
if (!mHasFeature) {
|
||||
return null;
|
||||
}
|
||||
synchronized (this) {
|
||||
if (mDeviceOwner != null && mDeviceOwner.hasDeviceInitializer()) {
|
||||
return mDeviceOwner.getDeviceInitializerPackageName();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearDeviceInitializer(String packageName) {
|
||||
if (!mHasFeature) {
|
||||
return;
|
||||
}
|
||||
if (packageName == null) {
|
||||
throw new NullPointerException("packageName is null");
|
||||
}
|
||||
try {
|
||||
int uid = mContext.getPackageManager().getPackageUid(packageName, 0);
|
||||
if (uid != Binder.getCallingUid()) {
|
||||
throw new SecurityException(
|
||||
"clearDeviceInitializer can only be called by the device initializer");
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
throw new SecurityException(e);
|
||||
}
|
||||
if (!isDeviceInitializer(packageName)) {
|
||||
throw new SecurityException(
|
||||
"clearDeviceInitializer can only be called by the device initializer");
|
||||
}
|
||||
synchronized (this) {
|
||||
long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (mDeviceOwner != null) {
|
||||
mDeviceOwner.clearDeviceInitializer();
|
||||
mDeviceOwner.writeOwnerFile();
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setProfileOwner(ComponentName who, String ownerName, int userHandle) {
|
||||
if (!mHasFeature) {
|
||||
@@ -3959,6 +4067,51 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
return policy == null || policy.mUserSetupComplete;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setUserEnabled(ComponentName who) {
|
||||
if (!mHasFeature) {
|
||||
return false;
|
||||
}
|
||||
synchronized (this) {
|
||||
if (who == null) {
|
||||
throw new NullPointerException("ComponentName is null");
|
||||
}
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
|
||||
ActiveAdmin activeAdmin =
|
||||
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
|
||||
if (!isDeviceInitializer(activeAdmin.info.getPackageName())) {
|
||||
throw new SecurityException(
|
||||
"This method can only be called by device initializers");
|
||||
}
|
||||
|
||||
long id = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (!isDeviceOwner(activeAdmin.info.getPackageName())) {
|
||||
IPackageManager ipm = AppGlobals.getPackageManager();
|
||||
ipm.setComponentEnabledSetting(who,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
||||
PackageManager.DONT_KILL_APP, userId);
|
||||
|
||||
removeActiveAdmin(who, userId);
|
||||
}
|
||||
|
||||
if (userId == UserHandle.USER_OWNER) {
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.DEVICE_PROVISIONED, 1);
|
||||
}
|
||||
Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
Settings.Secure.USER_SETUP_COMPLETE, 1, userId);
|
||||
} catch (RemoteException e) {
|
||||
Log.i(LOG_TAG, "Can't talk to package manager", e);
|
||||
return false;
|
||||
} finally {
|
||||
restoreCallingIdentity(id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProfileEnabled(ComponentName who) {
|
||||
if (!mHasFeature) {
|
||||
|
||||
Reference in New Issue
Block a user