Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
c11f45d
Pre-factor out the guts of the BinderClientTransport handshake
jdcormie Aug 20, 2025
8486ac1
don't rename binder
jdcormie Aug 20, 2025
efd855f
ComponentName
jdcormie Aug 20, 2025
68535c1
Merge branch 'master' into isolated-process-2
jdcormie Aug 21, 2025
7bbfd42
binder: Move BinderTransport's inner classes to the top level (#12303)
jdcormie Aug 21, 2025
1e1a69b
Implement new handshake
jdcormie Aug 27, 2025
80eee58
Pre-factor out the guts of the BinderClientTransport handshake
jdcormie Aug 20, 2025
aa7eff3
Merge remote-tracking branch 'upstream/master' into isolated-process-3
jdcormie Aug 28, 2025
6fd88de
Merge branch 'isolated-process-2' of https://github.com/jdcormie/grpc…
jdcormie Aug 28, 2025
643144c
Pre-factor out the guts of the BinderClientTransport handshake
jdcormie Aug 20, 2025
aedc3bc
ComponentName
jdcormie Aug 20, 2025
6c73cca
Merge remote-tracking branch 'origin/master' into isolated-process-2
jdcormie Aug 28, 2025
18beaeb
Merge remote-tracking branch 'origin/master' into isolated-process-3
jdcormie Aug 28, 2025
ddf4f2f
Merge branch 'master' of https://github.com/grpc/grpc-java into isola…
jdcormie Aug 29, 2025
57ee60f
Merge branch 'master' of https://github.com/grpc/grpc-java into isola…
jdcormie Aug 29, 2025
53bb3c4
use the new getContextForTargetUser()
jdcormie Aug 29, 2025
b7eb448
keep ComponentName private
jdcormie Aug 29, 2025
c208ab3
factor out the decorate() and wrap() calls common to all handshakes
jdcormie Aug 29, 2025
188c962
Merge branch 'isolated-process-2' into isolated-process-3
jdcormie Aug 29, 2025
6ae3230
undo some stuff
jdcormie Aug 29, 2025
57466ad
handshakeimpl
jdcormie Aug 29, 2025
c1ba7bf
vestigial
jdcormie Aug 30, 2025
118d03e
expand javadoc
jdcormie Aug 30, 2025
a5a6057
Pre-factor out the guts of the BinderClientTransport handshake
jdcormie Aug 20, 2025
0400204
Pre-factor out the guts of the BinderClientTransport handshake
jdcormie Aug 20, 2025
1bb363c
don't rename binder
jdcormie Aug 20, 2025
d77c6f5
ComponentName
jdcormie Aug 20, 2025
1cfb40b
Pre-factor out the guts of the BinderClientTransport handshake
jdcormie Aug 20, 2025
beb8f6e
ComponentName
jdcormie Aug 20, 2025
3baa4b9
factor out the decorate() and wrap() calls common to all handshakes
jdcormie Aug 29, 2025
24e3ba1
Pre-factor out the guts of the BinderClientTransport handshake
jdcormie Aug 20, 2025
9ff81d9
Pre-factor out the guts of the BinderClientTransport handshake
jdcormie Aug 20, 2025
72024df
ComponentName
jdcormie Aug 20, 2025
0e2e9bc
Pre-factor out the guts of the BinderClientTransport handshake
jdcormie Aug 20, 2025
b60b721
ComponentName
jdcormie Aug 20, 2025
883e471
factor out the decorate() and wrap() calls common to all handshakes
jdcormie Aug 29, 2025
9e86b35
Merge branch 'isolated-process-2' of https://github.com/jdcormie/grpc…
jdcormie Sep 13, 2025
1896db3
Merge remote-tracking branch 'refs/remotes/origin/isolated-process-2'…
jdcormie Sep 16, 2025
25df7e8
fix imports
jdcormie Sep 16, 2025
9711907
Merge branch 'grpc:master' into isolated-process-2
jdcormie Sep 16, 2025
2086335
interface -> abstract class
jdcormie Sep 16, 2025
d53fe91
sync comments
jdcormie Sep 16, 2025
77ff019
merge
jdcormie Sep 17, 2025
137f437
Merge remote-tracking branch 'refs/remotes/origin/isolated-process-3'…
jdcormie Sep 17, 2025
01f46c7
address review comments
jdcormie Oct 2, 2025
bed0137
Merge branch 'isolated-process-2' into isolated-process-3
jdcormie Oct 2, 2025
1cb3259
Use two named useXXX() BinderChannelBuilder methods instead of a bool
jdcormie Oct 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ public final class BinderChannelSmokeTest {
.setType(MethodDescriptor.MethodType.BIDI_STREAMING)
.build();

AndroidComponentAddress serverAddress;
ManagedChannel channel;
AtomicReference<Metadata> headersCapture = new AtomicReference<>();
AtomicReference<PeerUid> clientUidCapture = new AtomicReference<>();
Expand Down Expand Up @@ -134,7 +135,7 @@ public void setUp() throws Exception {
TestUtils.recordRequestHeadersInterceptor(headersCapture),
PeerUids.newPeerIdentifyingServerInterceptor());

AndroidComponentAddress serverAddress = HostServices.allocateService(appContext);
serverAddress = HostServices.allocateService(appContext);
HostServices.configureService(
serverAddress,
HostServices.serviceParamsBuilder()
Expand All @@ -149,13 +150,15 @@ public void setUp() throws Exception {
.build())
.build());

channel =
BinderChannelBuilder.forAddress(serverAddress, appContext)
channel = newBinderChannelBuilder().build();
}

BinderChannelBuilder newBinderChannelBuilder() {
return BinderChannelBuilder.forAddress(serverAddress, appContext)
.inboundParcelablePolicy(
InboundParcelablePolicy.newBuilder()
.setAcceptParcelableMetadataValues(true)
.build())
.build();
InboundParcelablePolicy.newBuilder()
.setAcceptParcelableMetadataValues(true)
.build());
}

@After
Expand Down Expand Up @@ -185,6 +188,18 @@ public void testBasicCall() throws Exception {
assertThat(doCall("Hello").get()).isEqualTo("Hello");
}

@Test
public void testBasicCallWithLegacyAuthStrategy() throws Exception {
channel = newBinderChannelBuilder().useLegacyAuthStrategy().build();
assertThat(doCall("Hello").get()).isEqualTo("Hello");
}

@Test
public void testBasicCallWithV2AuthStrategy() throws Exception {
channel = newBinderChannelBuilder().useV2AuthStrategy().build();
assertThat(doCall("Hello").get()).isEqualTo("Hello");
}

@Test
public void testPeerUidIsRecorded() throws Exception {
assertThat(doCall("Hello").get()).isEqualTo("Hello");
Expand Down
56 changes: 56 additions & 0 deletions binder/src/main/java/io/grpc/binder/BinderChannelBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,62 @@ public BinderChannelBuilder preAuthorizeServers(boolean preAuthorize) {
return this;
}

/**
* Specifies how and when to authorize a server against this Channel's {@link SecurityPolicy}.
*
* <p>This method selects the original "legacy" authorization strategy, which is no longer
* preferred for two reasons. First, the legacy strategy considers the UID of the server *process*
* we connect to. This is problematic for services using the `android:isolatedProcess` attribute,
* which runs them under a different UID and without any of the privileges of the hosting app.
* Second, the legacy authorization strategy performs SecurityPolicy checks later in the
* handshake, which means the calling UID must be rechecked on every subsequent transaction. For
* these reasons, prefer {@link #useV2AuthStrategy()} instead.
*
* <p>The server does not know which authorization strategy a client is using. Both strategies
* work with all versions of the grpc-binder server.
*
* <p>The default authorization strategy is unspecified. Clients that require the legacy strategy
* should configure it explicitly using this method. Eventually support for the legacy strategy
* will be removed.
*
* @return this
*/
public BinderChannelBuilder useLegacyAuthStrategy() {
transportFactoryBuilder.setUseLegacyAuthStrategy(true);
return this;
}

/**
* Specifies how and when to authorize a server against this Channel's {@link SecurityPolicy}.
*
* <p>This method selects the v2 authorization strategy. It improves on {@link
* #useLegacyAuthStrategy()}, by considering the UID of the server *app* we connect to, rather
* than the server *process*. This allows clients to connect to services using the
* `android:isolatedProcess` attribute, which runs them under a different ephemeral UID and
* without any of the privileges of the hosting app.
*
* <p>Furthermore, the v2 authorization strategy performs SecurityPolicy checks earlier the
* handshake, which allows subsequent transactions over the connection to proceed securely without
* further UID checks. For these reasons, clients should prefer the v2 strategy.
*
* <p>The server does not know which authorization strategy a client is using. Both strategies
* work with all versions of the grpc-binder server.
*
* <p>The default authorization strategy is unspecified. Clients that require the v2 strategy
* should configure it explicitly using this method. Eventually support for the legacy strategy
* will be removed.
*
* <p>If moving to the new authorization strategy causes a robolectric test to fail, ensure your
* fake Service component is registered with `ShadowPackageManager` using `addOrUpdateService()`.
*
* @return this
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/12397")
public BinderChannelBuilder useV2AuthStrategy() {
transportFactoryBuilder.setUseLegacyAuthStrategy(false);
return this;
}

@Override
public BinderChannelBuilder idleTimeout(long value, TimeUnit unit) {
checkState(
Expand Down
22 changes: 20 additions & 2 deletions binder/src/main/java/io/grpc/binder/internal/Bindable.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,11 @@ interface Observer {
* before giving them a chance to run. However, note that the identity/existence of the resolved
* Service can change between the time this method returns and the time you actually bind/connect
* to it. For example, suppose the target package gets uninstalled or upgraded right after this
* method returns. In {@link Observer#onBound}, you should verify that the server you resolved is
* the same one you connected to.
* method returns.
*
* <p>Compare with {@link #getConnectedServiceInfo()}, which can only be called after {@link
* Observer#onBound(IBinder)} but can be used to learn about the service you actually connected
* to.
*/
@AnyThread
ServiceInfo resolve() throws StatusException;
Expand All @@ -68,6 +71,21 @@ interface Observer {
@AnyThread
void bind();

/**
* Asks PackageManager for details about the remote Service we *actually* connected to.
*
* <p>Can only be called after {@link Observer#onBound}.
*
* <p>Compare with {@link #resolve()}, which reports which service would be selected as of now but
* *without* connecting.
*
* @throws StatusException UNIMPLEMENTED if the connected service isn't found (an {@link
* Observer#onUnbound} callback has likely already happened or is on its way!)
* @throws IllegalStateException if {@link Observer#onBound} has not "happened-before" this call
*/
@AnyThread
ServiceInfo getConnectedServiceInfo() throws StatusException;

/**
* Unbind from the remote service if connected.
*
Expand Down
Loading