Call PROFILE/DEVICE_OWNER_CHANGED broadcast and onTransferCompleted callback upon a successful transfer.

Test: cts-tradefed run cts-dev --module DevicePolicyManager --test com.android.cts.devicepolicy.MixedProfileOwnerHostSideTransferTest#testTransferOwnerChangedBroadcast
Test: cts-tradefed run cts-dev --module DevicePolicyManager --test com.android.cts.devicepolicy.MixedProfileOwnerHostSideTransferTest#testTransferCompleteCallback
Test: cts-tradefed run cts-dev --module DevicePolicyManager --test com.android.cts.devicepolicy.MixedDeviceOwnerHostSideTransferTest#testTransferOwnerChangedBroadcast
Test: cts-tradefed run cts-dev --module DevicePolicyManager --test com.android.cts.devicepolicy.MixedDeviceOwnerHostSideTransferTest#testTransferCompleteCallback
Bug: 69542936
Bug: 69543044
Change-Id: Ifbe3ac0029794eba185e538e5a490073d5309f0b
This commit is contained in:
arangelov
2017-12-20 20:26:46 +00:00
parent acb394d13a
commit 8bae4eaa4d
7 changed files with 144 additions and 47 deletions

View File

@@ -29,10 +29,14 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.UserHandle;
import android.security.KeyChain;
import libcore.util.NonNull;
import libcore.util.Nullable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -438,6 +442,31 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
// TO DO: describe syntax.
public static final String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
/**
* Broadcast action: notify the newly transferred administrator that the transfer
* from the original administrator was successful.
*
* @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_TRANSFER_OWNERSHIP_COMPLETE =
"android.app.action.TRANSFER_OWNERSHIP_COMPLETE";
/**
* A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that
* allows a mobile device management application to pass data to the management application
* instance after owner transfer.
*
* <p>
* If the transfer is successful, the new device owner receives the data in
* {@link DeviceAdminReceiver#onTransferOwnershipComplete(Context, PersistableBundle)}.
* The bundle is not changed during the ownership transfer.
*
* @see DevicePolicyManager#transferOwnership(ComponentName, ComponentName, PersistableBundle)
*/
public static final String EXTRA_TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE =
"android.app.extra.TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE";
private DevicePolicyManager mManager;
private ComponentName mWho;
@@ -859,6 +888,20 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
public void onUserRemoved(Context context, Intent intent, UserHandle removedUser) {
}
/**
* Called on the newly assigned owner (either device owner or profile owner) when the ownership
* transfer has completed successfully.
*
* <p> The {@code bundle} parameter allows the original owner to pass data
* to the new one.
*
* @param context the running context as per {@link #onReceive}
* @param bundle the data to be passed to the new owner
*/
public void onTransferOwnershipComplete(@NonNull Context context,
@Nullable PersistableBundle bundle) {
}
/**
* Intercept standard device administrator broadcasts. Implementations
* should not override this method; it is better to implement the
@@ -921,6 +964,10 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
onUserAdded(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
} else if (ACTION_USER_REMOVED.equals(action)) {
onUserRemoved(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
} else if (ACTION_TRANSFER_OWNERSHIP_COMPLETE.equals(action)) {
PersistableBundle bundle =
intent.getParcelableExtra(EXTRA_TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE);
onTransferOwnershipComplete(context, bundle);
}
}
}

View File

@@ -1124,6 +1124,7 @@ public class DevicePolicyManager {
*
* This broadcast is sent only to the primary user.
* @see #ACTION_PROVISION_MANAGED_DEVICE
* @see DevicePolicyManager#transferOwnership(ComponentName, ComponentName, PersistableBundle)
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_DEVICE_OWNER_CHANGED
@@ -1708,6 +1709,16 @@ public class DevicePolicyManager {
*/
public static final int ID_TYPE_MEID = 8;
/**
* Broadcast action: sent when the profile owner is set, changed or cleared.
*
* This broadcast is sent only to the user managed by the new profile owner.
* @see DevicePolicyManager#transferOwnership(ComponentName, ComponentName, PersistableBundle)
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_PROFILE_OWNER_CHANGED =
"android.app.action.PROFILE_OWNER_CHANGED";
/**
* Return true if the given administrator component is currently active (enabled) in the system.
*
@@ -8990,41 +9001,34 @@ public class DevicePolicyManager {
}
}
//TODO STOPSHIP Add link to onTransferComplete callback when implemented.
/**
* Transfers the current administrator. All policies from the current administrator are
* migrated to the new administrator. The whole operation is atomic - the transfer is either
* complete or not done at all.
* Changes the current administrator to another one. All policies from the current
* administrator are migrated to the new administrator. The whole operation is atomic -
* the transfer is either complete or not done at all.
*
* Depending on the current administrator (device owner, profile owner, corporate owned
* profile owner), you have the following expected behaviour:
* <p>Depending on the current administrator (device owner, profile owner), you have the
* following expected behaviour:
* <ul>
* <li>A device owner can only be transferred to a new device owner</li>
* <li>A profile owner can only be transferred to a new profile owner</li>
* <li>A corporate owned managed profile can have two cases:
* <ul>
* <li>If the device owner and profile owner are the same package,
* both will be transferred.</li>
* <li>If the device owner and profile owner are different packages,
* and if this method is called from the profile owner, only the profile owner
* is transferred. Similarly, if it is called from the device owner, only
* the device owner is transferred.</li>
* </ul>
* </li>
* </ul>
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param target Which {@link DeviceAdminReceiver} we want the new administrator to be.
* @param bundle Parameters - This bundle allows the current administrator to pass data to the
* new administrator. The parameters will be received in the
* onTransferComplete callback.
* @hide
* <p>Use the {@code bundle} parameter to pass data to the new administrator. The parameters
* will be received in the
* {@link DeviceAdminReceiver#onTransferOwnershipComplete(Context, PersistableBundle)} callback.
*
* @param admin which {@link DeviceAdminReceiver} this request is associated with
* @param target which {@link DeviceAdminReceiver} we want the new administrator to be
* @param bundle data to be sent to the new administrator
* @throws SecurityException if {@code admin} is not a device owner nor a profile owner
* @throws IllegalArgumentException if {@code admin} or {@code target} is {@code null},
* both are components in the same package or {@code target} is not an active admin
*/
public void transferOwner(@NonNull ComponentName admin, @NonNull ComponentName target,
public void transferOwnership(@NonNull ComponentName admin, @NonNull ComponentName target,
PersistableBundle bundle) {
throwIfParentInstance("transferOwner");
throwIfParentInstance("transferOwnership");
try {
mService.transferOwner(admin, target, bundle);
mService.transferOwnership(admin, target, bundle);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}

View File

@@ -387,5 +387,5 @@ interface IDevicePolicyManager {
boolean isLogoutEnabled();
List<String> getDisallowedSystemApps(in ComponentName admin, int userId, String provisioningAction);
void transferOwner(in ComponentName admin, in ComponentName target, in PersistableBundle bundle);
void transferOwnership(in ComponentName admin, in ComponentName target, in PersistableBundle bundle);
}