Merge "Update role grant flow to be synchronized"
This commit is contained in:
@@ -363,13 +363,6 @@ public class CompanionDeviceActivity extends FragmentActivity implements
|
||||
mCdmServiceReceiver.send(RESULT_CODE_ASSOCIATION_APPROVED, data);
|
||||
}
|
||||
|
||||
private void onAssociationCreated(@NonNull AssociationInfo association) {
|
||||
if (DEBUG) Log.i(TAG, "onAssociationCreated(), association=" + association);
|
||||
|
||||
// Don't need to notify the app, CdmService has already done that. Just finish.
|
||||
setResultAndFinish(association, RESULT_OK);
|
||||
}
|
||||
|
||||
private void cancel(boolean discoveryTimeout, boolean userRejected) {
|
||||
if (DEBUG) {
|
||||
Log.i(TAG, "cancel(), discoveryTimeout="
|
||||
@@ -413,7 +406,9 @@ public class CompanionDeviceActivity extends FragmentActivity implements
|
||||
}
|
||||
|
||||
private void setResultAndFinish(@Nullable AssociationInfo association, int resultCode) {
|
||||
if (DEBUG) Log.i(TAG, "setResultAndFinish(), association=" + association);
|
||||
Log.i(TAG, "setResultAndFinish(), association="
|
||||
+ (association == null ? "null" : association)
|
||||
+ "resultCode=" + resultCode);
|
||||
|
||||
final Intent data = new Intent();
|
||||
if (association != null) {
|
||||
@@ -652,14 +647,14 @@ public class CompanionDeviceActivity extends FragmentActivity implements
|
||||
new ResultReceiver(Handler.getMain()) {
|
||||
@Override
|
||||
protected void onReceiveResult(int resultCode, Bundle data) {
|
||||
if (resultCode != RESULT_CODE_ASSOCIATION_CREATED) {
|
||||
throw new RuntimeException("Unknown result code: " + resultCode);
|
||||
if (resultCode == RESULT_CODE_ASSOCIATION_CREATED) {
|
||||
final AssociationInfo association = data.getParcelable(
|
||||
EXTRA_ASSOCIATION, AssociationInfo.class);
|
||||
requireNonNull(association);
|
||||
setResultAndFinish(association, RESULT_OK);
|
||||
} else {
|
||||
setResultAndFinish(null, resultCode);
|
||||
}
|
||||
|
||||
final AssociationInfo association = data.getParcelable(EXTRA_ASSOCIATION);
|
||||
requireNonNull(association);
|
||||
|
||||
onAssociationCreated(association);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -23,8 +23,10 @@ import static android.companion.CompanionDeviceManager.COMPANION_DEVICE_DISCOVER
|
||||
import static android.content.ComponentName.createRelative;
|
||||
|
||||
import static com.android.server.companion.CompanionDeviceManagerService.DEBUG;
|
||||
import static com.android.server.companion.MetricUtils.logCreateAssociation;
|
||||
import static com.android.server.companion.PackageUtils.enforceUsesCompanionDeviceFeature;
|
||||
import static com.android.server.companion.PermissionsUtils.enforcePermissionsForAssociation;
|
||||
import static com.android.server.companion.RolesUtils.addRoleHolderForAssociation;
|
||||
import static com.android.server.companion.RolesUtils.isRoleHolder;
|
||||
import static com.android.server.companion.Utils.prepareForIpc;
|
||||
|
||||
@@ -35,8 +37,10 @@ import android.annotation.Nullable;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.PendingIntent;
|
||||
import android.companion.AssociatedDevice;
|
||||
import android.companion.AssociationInfo;
|
||||
import android.companion.AssociationRequest;
|
||||
import android.companion.CompanionDeviceManager;
|
||||
import android.companion.IAssociationRequestCallback;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@@ -87,7 +91,7 @@ import java.util.Set;
|
||||
* required.
|
||||
*
|
||||
* If the user's approval is NOT required: an {@link AssociationRequestsProcessor} invokes
|
||||
* {@link #createAssociationAndNotifyApplication(AssociationRequest, String, int, MacAddress, IAssociationRequestCallback)}
|
||||
* {@link #createAssociationAndNotifyApplication(AssociationRequest, String, int, MacAddress, IAssociationRequestCallback, ResultReceiver)}
|
||||
* which after calling to {@link CompanionDeviceManagerService} to create an association, notifies
|
||||
* the requester via
|
||||
* {@link android.companion.CompanionDeviceManager.Callback#onAssociationCreated(AssociationInfo)}.
|
||||
@@ -99,7 +103,7 @@ import java.util.Set;
|
||||
* from the Approval UI in via {@link #mOnRequestConfirmationReceiver} and invokes
|
||||
* {@link #processAssociationRequestApproval(AssociationRequest, IAssociationRequestCallback, ResultReceiver, MacAddress)}
|
||||
* which one more time checks that the packages holds all necessary permissions before proceeding to
|
||||
* {@link #createAssociationAndNotifyApplication(AssociationRequest, String, int, MacAddress, IAssociationRequestCallback)}.
|
||||
* {@link #createAssociationAndNotifyApplication(AssociationRequest, String, int, MacAddress, IAssociationRequestCallback, ResultReceiver)}.
|
||||
*
|
||||
* @see #processNewAssociationRequest(AssociationRequest, String, int, IAssociationRequestCallback)
|
||||
* @see #processAssociationRequestApproval(AssociationRequest, IAssociationRequestCallback,
|
||||
@@ -132,10 +136,10 @@ class AssociationRequestsProcessor {
|
||||
private final @NonNull Context mContext;
|
||||
private final @NonNull CompanionDeviceManagerService mService;
|
||||
private final @NonNull PackageManagerInternal mPackageManager;
|
||||
private final @NonNull AssociationStore mAssociationStore;
|
||||
private final @NonNull AssociationStoreImpl mAssociationStore;
|
||||
|
||||
AssociationRequestsProcessor(@NonNull CompanionDeviceManagerService service,
|
||||
@NonNull AssociationStore associationStore) {
|
||||
@NonNull AssociationStoreImpl associationStore) {
|
||||
mContext = service.getContext();
|
||||
mService = service;
|
||||
mPackageManager = service.mPackageManagerInternal;
|
||||
@@ -174,7 +178,7 @@ class AssociationRequestsProcessor {
|
||||
&& !willAddRoleHolder(request, packageName, userId)) {
|
||||
// 2a. Create association right away.
|
||||
createAssociationAndNotifyApplication(request, packageName, userId,
|
||||
/*macAddress*/ null, callback);
|
||||
/* macAddress */ null, callback, /* resultReceiver */ null);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -253,34 +257,110 @@ class AssociationRequestsProcessor {
|
||||
}
|
||||
|
||||
// 2. Create association and notify the application.
|
||||
final AssociationInfo association = createAssociationAndNotifyApplication(
|
||||
request, packageName, userId, macAddress, callback);
|
||||
|
||||
// 3. Send the association back the Approval Activity, so that it can report back to the app
|
||||
// via Activity.setResult().
|
||||
final Bundle data = new Bundle();
|
||||
data.putParcelable(EXTRA_ASSOCIATION, association);
|
||||
resultReceiver.send(RESULT_CODE_ASSOCIATION_CREATED, data);
|
||||
createAssociationAndNotifyApplication(request, packageName, userId, macAddress, callback,
|
||||
resultReceiver);
|
||||
}
|
||||
|
||||
private AssociationInfo createAssociationAndNotifyApplication(
|
||||
private void createAssociationAndNotifyApplication(
|
||||
@NonNull AssociationRequest request, @NonNull String packageName, @UserIdInt int userId,
|
||||
@Nullable MacAddress macAddress, @NonNull IAssociationRequestCallback callback) {
|
||||
final AssociationInfo association;
|
||||
@Nullable MacAddress macAddress, @NonNull IAssociationRequestCallback callback,
|
||||
@NonNull ResultReceiver resultReceiver) {
|
||||
final long callingIdentity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
association = mService.createAssociation(userId, packageName, macAddress,
|
||||
createAssociation(userId, packageName, macAddress,
|
||||
request.getDisplayName(), request.getDeviceProfile(),
|
||||
request.getAssociatedDevice(), request.isSelfManaged());
|
||||
request.getAssociatedDevice(), request.isSelfManaged(),
|
||||
callback, resultReceiver);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(callingIdentity);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
callback.onAssociationCreated(association);
|
||||
} catch (RemoteException ignore) { }
|
||||
public void createAssociation(@UserIdInt int userId, @NonNull String packageName,
|
||||
@Nullable MacAddress macAddress, @Nullable CharSequence displayName,
|
||||
@Nullable String deviceProfile, @Nullable AssociatedDevice associatedDevice,
|
||||
boolean selfManaged, @Nullable IAssociationRequestCallback callback,
|
||||
@Nullable ResultReceiver resultReceiver) {
|
||||
final int id = mService.getNewAssociationIdForPackage(userId, packageName);
|
||||
final long timestamp = System.currentTimeMillis();
|
||||
|
||||
return association;
|
||||
final AssociationInfo association = new AssociationInfo(id, userId, packageName,
|
||||
macAddress, displayName, deviceProfile, associatedDevice, selfManaged,
|
||||
/* notifyOnDeviceNearby */ false, /* revoked */ false, timestamp, Long.MAX_VALUE);
|
||||
|
||||
if (deviceProfile != null) {
|
||||
// If the "Device Profile" is specified, make the companion application a holder of the
|
||||
// corresponding role.
|
||||
addRoleHolderForAssociation(mService.getContext(), association, success -> {
|
||||
if (success) {
|
||||
addAssociationToStore(association, deviceProfile);
|
||||
|
||||
sendCallbackAndFinish(association, callback, resultReceiver);
|
||||
} else {
|
||||
Slog.e(TAG, "Failed to add u" + userId + "\\" + packageName
|
||||
+ " to the list of " + deviceProfile + " holders.");
|
||||
|
||||
sendCallbackAndFinish(null, callback, resultReceiver);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
addAssociationToStore(association, null);
|
||||
|
||||
sendCallbackAndFinish(association, callback, resultReceiver);
|
||||
}
|
||||
|
||||
// Don't need to update the mRevokedAssociationsPendingRoleHolderRemoval since
|
||||
// maybeRemoveRoleHolderForAssociation in PackageInactivityListener will handle the case
|
||||
// that there are other devices with the same profile, so the role holder won't be removed.
|
||||
}
|
||||
|
||||
private void addAssociationToStore(@NonNull AssociationInfo association,
|
||||
@Nullable String deviceProfile) {
|
||||
Slog.i(TAG, "New CDM association created=" + association);
|
||||
|
||||
mAssociationStore.addAssociation(association);
|
||||
|
||||
mService.updateSpecialAccessPermissionForAssociatedPackage(association);
|
||||
|
||||
logCreateAssociation(deviceProfile);
|
||||
}
|
||||
|
||||
private void sendCallbackAndFinish(@Nullable AssociationInfo association,
|
||||
@Nullable IAssociationRequestCallback callback,
|
||||
@Nullable ResultReceiver resultReceiver) {
|
||||
if (association != null) {
|
||||
// Send the association back via the app's callback
|
||||
if (callback != null) {
|
||||
try {
|
||||
callback.onAssociationCreated(association);
|
||||
} catch (RemoteException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
// Send the association back to CompanionDeviceActivity, so that it can report
|
||||
// back to the app via Activity.setResult().
|
||||
if (resultReceiver != null) {
|
||||
final Bundle data = new Bundle();
|
||||
data.putParcelable(EXTRA_ASSOCIATION, association);
|
||||
resultReceiver.send(RESULT_CODE_ASSOCIATION_CREATED, data);
|
||||
}
|
||||
} else {
|
||||
// Send the association back via the app's callback
|
||||
if (callback != null) {
|
||||
try {
|
||||
// TODO: update to INTERNAL_ERROR once it's added.
|
||||
callback.onFailure(CompanionDeviceManager.REASON_CANCELED);
|
||||
} catch (RemoteException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
// Send the association back to CompanionDeviceActivity, so that it can report
|
||||
// back to the app via Activity.setResult().
|
||||
if (resultReceiver != null) {
|
||||
final Bundle data = new Bundle();
|
||||
resultReceiver.send(CompanionDeviceManager.RESULT_INTERNAL_ERROR, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean willAddRoleHolder(@NonNull AssociationRequest request,
|
||||
|
||||
@@ -28,7 +28,6 @@ import static com.android.internal.util.CollectionUtils.any;
|
||||
import static com.android.internal.util.Preconditions.checkState;
|
||||
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
|
||||
import static com.android.server.companion.AssociationStore.CHANGE_TYPE_UPDATED_ADDRESS_UNCHANGED;
|
||||
import static com.android.server.companion.MetricUtils.logCreateAssociation;
|
||||
import static com.android.server.companion.MetricUtils.logRemoveAssociation;
|
||||
import static com.android.server.companion.PackageUtils.enforceUsesCompanionDeviceFeature;
|
||||
import static com.android.server.companion.PackageUtils.getPackageInfo;
|
||||
@@ -38,7 +37,6 @@ import static com.android.server.companion.PermissionsUtils.enforceCallerCanMana
|
||||
import static com.android.server.companion.PermissionsUtils.enforceCallerIsSystemOr;
|
||||
import static com.android.server.companion.PermissionsUtils.enforceCallerIsSystemOrCanInteractWithUserId;
|
||||
import static com.android.server.companion.PermissionsUtils.sanitizeWithCallerChecks;
|
||||
import static com.android.server.companion.RolesUtils.addRoleHolderForAssociation;
|
||||
import static com.android.server.companion.RolesUtils.removeRoleHolderForAssociation;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
@@ -55,7 +53,6 @@ import android.app.ActivityManagerInternal;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.companion.AssociatedDevice;
|
||||
import android.companion.AssociationInfo;
|
||||
import android.companion.AssociationRequest;
|
||||
import android.companion.DeviceNotAssociatedException;
|
||||
@@ -819,7 +816,8 @@ public class CompanionDeviceManagerService extends SystemService {
|
||||
getContext().enforceCallingOrSelfPermission(
|
||||
android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES, "createAssociation");
|
||||
|
||||
legacyCreateAssociation(userId, macAddress, packageName, null);
|
||||
final MacAddress macAddressObj = MacAddress.fromString(macAddress);
|
||||
createNewAssociation(userId, packageName, macAddressObj, null, null, false);
|
||||
}
|
||||
|
||||
private void checkCanCallNotificationApi(String callingPackage) {
|
||||
@@ -871,45 +869,12 @@ public class CompanionDeviceManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use
|
||||
* {@link #createAssociation(int, String, MacAddress, CharSequence, String, AssociatedDevice,
|
||||
* boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
void legacyCreateAssociation(@UserIdInt int userId, @NonNull String deviceMacAddress,
|
||||
@NonNull String packageName, @Nullable String deviceProfile) {
|
||||
final MacAddress macAddress = MacAddress.fromString(deviceMacAddress);
|
||||
createAssociation(userId, packageName, macAddress, null, deviceProfile, null, false);
|
||||
}
|
||||
|
||||
AssociationInfo createAssociation(@UserIdInt int userId, @NonNull String packageName,
|
||||
void createNewAssociation(@UserIdInt int userId, @NonNull String packageName,
|
||||
@Nullable MacAddress macAddress, @Nullable CharSequence displayName,
|
||||
@Nullable String deviceProfile, @Nullable AssociatedDevice associatedDevice,
|
||||
boolean selfManaged) {
|
||||
final int id = getNewAssociationIdForPackage(userId, packageName);
|
||||
final long timestamp = System.currentTimeMillis();
|
||||
|
||||
final AssociationInfo association = new AssociationInfo(id, userId, packageName,
|
||||
macAddress, displayName, deviceProfile, associatedDevice, selfManaged,
|
||||
/* notifyOnDeviceNearby */ false, /* revoked */ false, timestamp, Long.MAX_VALUE);
|
||||
Slog.i(TAG, "New CDM association created=" + association);
|
||||
mAssociationStore.addAssociation(association);
|
||||
|
||||
// If the "Device Profile" is specified, make the companion application a holder of the
|
||||
// corresponding role.
|
||||
if (deviceProfile != null) {
|
||||
addRoleHolderForAssociation(getContext(), association);
|
||||
}
|
||||
|
||||
updateSpecialAccessPermissionForAssociatedPackage(association);
|
||||
logCreateAssociation(deviceProfile);
|
||||
|
||||
// Don't need to update the mRevokedAssociationsPendingRoleHolderRemoval since
|
||||
// maybeRemoveRoleHolderForAssociation in PackageInactivityListener will handle the case
|
||||
// that there are other devices with the same profile, so the role holder won't be removed.
|
||||
|
||||
return association;
|
||||
@Nullable String deviceProfile, boolean isSelfManaged) {
|
||||
mAssociationRequestsProcessor.createAssociation(userId, packageName, macAddress,
|
||||
displayName, deviceProfile, /* associatedDevice */ null, isSelfManaged,
|
||||
/* callback */ null, /* resultReceiver */ null);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -946,7 +911,7 @@ public class CompanionDeviceManagerService extends SystemService {
|
||||
return usedIdsForPackage;
|
||||
}
|
||||
|
||||
private int getNewAssociationIdForPackage(@UserIdInt int userId, @NonNull String packageName) {
|
||||
int getNewAssociationIdForPackage(@UserIdInt int userId, @NonNull String packageName) {
|
||||
synchronized (mPreviouslyUsedIds) {
|
||||
// First: collect all IDs currently in use for this user's Associations.
|
||||
final SparseBooleanArray usedIds = new SparseBooleanArray();
|
||||
@@ -1170,7 +1135,7 @@ public class CompanionDeviceManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSpecialAccessPermissionForAssociatedPackage(AssociationInfo association) {
|
||||
void updateSpecialAccessPermissionForAssociatedPackage(AssociationInfo association) {
|
||||
final PackageInfo packageInfo =
|
||||
getPackageInfo(getContext(), association.getUserId(), association.getPackageName());
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server.companion;
|
||||
|
||||
import android.companion.AssociationInfo;
|
||||
import android.net.MacAddress;
|
||||
import android.os.Binder;
|
||||
import android.os.ShellCommand;
|
||||
|
||||
@@ -63,7 +64,9 @@ class CompanionDeviceShellCommand extends ShellCommand {
|
||||
int userId = getNextIntArgRequired();
|
||||
String packageName = getNextArgRequired();
|
||||
String address = getNextArgRequired();
|
||||
mService.legacyCreateAssociation(userId, address, packageName, null);
|
||||
final MacAddress macAddress = MacAddress.fromString(address);
|
||||
mService.createNewAssociation(userId, packageName, macAddress,
|
||||
null, null, false);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import android.util.Log;
|
||||
import android.util.Slog;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/** Utility methods for accessing {@link RoleManager} APIs. */
|
||||
@SuppressLint("LongLogTag")
|
||||
@@ -46,7 +47,8 @@ final class RolesUtils {
|
||||
}
|
||||
|
||||
static void addRoleHolderForAssociation(
|
||||
@NonNull Context context, @NonNull AssociationInfo associationInfo) {
|
||||
@NonNull Context context, @NonNull AssociationInfo associationInfo,
|
||||
@NonNull Consumer<Boolean> roleGrantResult) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "addRoleHolderForAssociation() associationInfo=" + associationInfo);
|
||||
}
|
||||
@@ -62,12 +64,7 @@ final class RolesUtils {
|
||||
|
||||
roleManager.addRoleHolderAsUser(deviceProfile, packageName,
|
||||
MANAGE_HOLDERS_FLAG_DONT_KILL_APP, userHandle, context.getMainExecutor(),
|
||||
success -> {
|
||||
if (!success) {
|
||||
Slog.e(TAG, "Failed to add u" + userId + "\\" + packageName
|
||||
+ " to the list of " + deviceProfile + " holders.");
|
||||
}
|
||||
});
|
||||
roleGrantResult);
|
||||
}
|
||||
|
||||
static void removeRoleHolderForAssociation(
|
||||
|
||||
Reference in New Issue
Block a user