Clarify requirements for creating a cross-user Channel. (#12181)

The @SystemApi runtime visibility requirement isn't really new. It has always been implicit in the required INTERACT_ACROSS_USERS permission, which (in production) can only be held by system apps.

The SDK_INT >= 30 requirement was also always present, via @RequiresApi() on  BinderChannelBuilder#bindAsUser. This change just updates its replacement APIs (AndroidComponentAddress and TARGET_ANDROID_USER) to require it too.
This commit is contained in:
John Cormie 2025-06-26 17:43:13 -07:00 committed by GitHub
parent 64322c3243
commit 74aee11389
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 26 additions and 8 deletions

View File

@ -250,7 +250,22 @@ public final class AndroidComponentAddress extends SocketAddress {
return this;
}
/** See {@link AndroidComponentAddress#getTargetUser()}. */
/**
* Specifies the Android user in which the built Address' bind Intent will be evaluated.
*
* <p>Connecting to a server in a different Android user is uncommon and requires the client app
* have runtime visibility of &#064;SystemApi's and hold certain &#064;SystemApi permissions.
* The device must also be running Android SDK version 30 or higher.
*
* <p>See https://developer.android.com/guide/app-compatibility/restrictions-non-sdk-interfaces
* for details on which apps can call the underlying &#064;SystemApi's needed to make this type
* of connection.
*
* <p>One of the "android.permission.INTERACT_ACROSS_XXX" permissions is required. The exact one
* depends on the calling user's relationship to the target user, whether client and server are
* in the same or different apps, and the version of Android in use. See {@link
* Context#bindServiceAsUser}, the essential underlying Android API, for details.
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/10173")
public Builder setTargetUser(@Nullable UserHandle targetUser) {
this.targetUser = targetUser;

View File

@ -35,12 +35,15 @@ public final class ApiConstants {
/**
* Specifies the Android user in which target URIs should be resolved.
*
* <p>{@link UserHandle} can't reasonably be encoded in a target URI string. Instead, all
* {@link io.grpc.NameResolverProvider}s producing {@link AndroidComponentAddress}es should let
* clients address servers in another Android user using this argument.
* <p>{@link UserHandle} can't reasonably be encoded in a target URI string. Instead, all {@link
* io.grpc.NameResolverProvider}s producing {@link AndroidComponentAddress}es should let clients
* address servers in another Android user using this argument.
*
* <p>See also {@link AndroidComponentAddress#getTargetUser()}.
* <p>Connecting to a server in a different Android user is uncommon and can only be done by a
* "system app" client with special permissions. See {@link
* AndroidComponentAddress.Builder#setTargetUser(UserHandle)} for details.
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/10173")
public static final NameResolver.Args.Key<UserHandle> TARGET_ANDROID_USER =
NameResolver.Args.Key.create("target-android-user");
}

View File

@ -242,9 +242,9 @@ public final class BinderChannelBuilder extends ForwardingChannelBuilder<BinderC
* specify a {@link UserHandle}. If neither the Channel nor the {@link AndroidComponentAddress}
* specifies a target user, the {@link UserHandle} of the current process will be used.
*
* <p>Targeting a Service in a different Android user is uncommon and requires special permissions
* normally reserved for system apps. See {@link android.content.Context#bindServiceAsUser} for
* details.
* <p>Connecting to a server in a different Android user is uncommon and can only be done by a
* "system app" client with special permissions. See {@link
* AndroidComponentAddress.Builder#setTargetUser(UserHandle)} for details.
*
* @deprecated This method's name is misleading because it implies an impersonated client identity
* when it's actually specifying part of the server's location. It's also no longer necessary