Skip to content
Open
Changes from all commits
Commits
Show all changes
31 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
80eee58
Pre-factor out the guts of the BinderClientTransport handshake
jdcormie Aug 20, 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
ddf4f2f
Merge branch 'master' of https://github.com/grpc/grpc-java into isola…
jdcormie Aug 29, 2025
c208ab3
factor out the decorate() and wrap() calls common to all handshakes
jdcormie Aug 29, 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
01f46c7
address review comments
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 @@ -25,6 +25,8 @@
import android.os.IBinder;
import android.os.Parcel;
import android.os.Process;
import androidx.annotation.BinderThread;
import androidx.annotation.MainThread;
import com.google.common.base.Ticker;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
Expand Down Expand Up @@ -72,6 +74,9 @@ public final class BinderClientTransport extends BinderTransport
private final SecurityPolicy securityPolicy;
private final Bindable serviceBinding;

@GuardedBy("this")
private final ClientHandshake handshake;

/** Number of ongoing calls which keep this transport "in-use". */
private final AtomicInteger numInUseStreams;

Expand Down Expand Up @@ -122,6 +127,7 @@ public BinderClientTransport(
Boolean preAuthServerOverride = options.getEagAttributes().get(PRE_AUTH_SERVER_OVERRIDE);
this.preAuthorizeServer =
preAuthServerOverride != null ? preAuthServerOverride : factory.preAuthorizeServers;
this.handshake = new LegacyClientHandshake();
numInUseStreams = new AtomicInteger();
pingTracker = new PingTracker(Ticker.systemTicker(), (id) -> sendPing(id));

Expand All @@ -146,7 +152,9 @@ void releaseExecutors() {

@Override
public synchronized void onBound(IBinder binder) {
sendSetupTransaction(binderDecorator.decorate(OneWayBinderProxy.wrap(binder, offloadExecutor)));
OneWayBinderProxy binderProxy = OneWayBinderProxy.wrap(binder, offloadExecutor);
binderProxy = binderDecorator.decorate(binderProxy);
handshake.onBound(binderProxy);
}

@Override
Expand Down Expand Up @@ -329,7 +337,6 @@ void notifyTerminated() {
@Override
@GuardedBy("this")
protected void handleSetupTransport(Parcel parcel) {
int remoteUid = Binder.getCallingUid();
if (inState(TransportState.SETUP)) {
int version = parcel.readInt();
IBinder binder = parcel.readStrongBinder();
Expand All @@ -339,23 +346,8 @@ protected void handleSetupTransport(Parcel parcel) {
shutdownInternal(
Status.UNAVAILABLE.withDescription("Malformed SETUP_TRANSPORT data"), true);
} else {
restrictIncomingBinderToCallsFrom(remoteUid);
attributes = setSecurityAttrs(attributes, remoteUid);
authResultFuture = checkServerAuthorizationAsync(remoteUid);
Futures.addCallback(
authResultFuture,
new FutureCallback<Status>() {
@Override
public void onSuccess(Status result) {
handleAuthResult(binder, result);
}

@Override
public void onFailure(Throwable t) {
handleAuthResult(t);
}
},
offloadExecutor);
OneWayBinderProxy binderProxy = OneWayBinderProxy.wrap(binder, offloadExecutor);
handshake.handleSetupTransport(binderProxy);
}
}
}
Expand All @@ -366,29 +358,70 @@ private ListenableFuture<Status> checkServerAuthorizationAsync(int remoteUid) {
: Futures.submit(() -> securityPolicy.checkAuthorization(remoteUid), offloadExecutor);
}

private synchronized void handleAuthResult(IBinder binder, Status authorization) {
if (inState(TransportState.SETUP)) {
if (!authorization.isOk()) {
shutdownInternal(authorization, true);
} else if (!setOutgoingBinder(OneWayBinderProxy.wrap(binder, offloadExecutor))) {
shutdownInternal(
Status.UNAVAILABLE.withDescription("Failed to observe outgoing binder"), true);
} else {
// Check state again, since a failure inside setOutgoingBinder (or a callback it
// triggers), could have shut us down.
if (!isShutdown()) {
setState(TransportState.READY);
attributes = clientTransportListener.filterTransport(attributes);
clientTransportListener.transportReady();
if (readyTimeoutFuture != null) {
readyTimeoutFuture.cancel(false);
readyTimeoutFuture = null;
private final class LegacyClientHandshake implements ClientHandshake {
@Override
@MainThread
@GuardedBy("BinderClientTransport.this") // By way of @GuardedBy("this") `handshake` member.
public void onBound(OneWayBinderProxy binder) {
sendSetupTransaction(binder);
}

@Override
@BinderThread
@GuardedBy("BinderClientTransport.this") // By way of @GuardedBy("this") `handshake` member.
public void handleSetupTransport(OneWayBinderProxy binder) {
int remoteUid = Binder.getCallingUid();
restrictIncomingBinderToCallsFrom(remoteUid);
attributes = setSecurityAttrs(attributes, remoteUid);
authResultFuture = checkServerAuthorizationAsync(remoteUid);
Futures.addCallback(
authResultFuture,
new FutureCallback<Status>() {
@Override
public void onSuccess(Status result) {
synchronized (BinderClientTransport.this) {
handleAuthResult(binder, result);
}
}

@Override
public void onFailure(Throwable t) {
BinderClientTransport.this.handleAuthResult(t);
}
},
offloadExecutor);
}

@GuardedBy("BinderClientTransport.this")
private void handleAuthResult(OneWayBinderProxy binder, Status authorization) {
if (inState(TransportState.SETUP)) {
if (!authorization.isOk()) {
shutdownInternal(authorization, true);
} else if (!setOutgoingBinder(binder)) {
shutdownInternal(
Status.UNAVAILABLE.withDescription("Failed to observe outgoing binder"), true);
} else {
// Check state again, since a failure inside setOutgoingBinder (or a callback it
// triggers), could have shut us down.
if (!isShutdown()) {
onHandshakeComplete();
}
}
}
}
}

@GuardedBy("this")
private void onHandshakeComplete() {
setState(TransportState.READY);
attributes = clientTransportListener.filterTransport(attributes);
clientTransportListener.transportReady();
if (readyTimeoutFuture != null) {
readyTimeoutFuture.cancel(false);
readyTimeoutFuture = null;
}
}

private synchronized void handleAuthResult(Throwable t) {
shutdownInternal(
Status.INTERNAL.withDescription("Could not evaluate SecurityPolicy").withCause(t), true);
Expand All @@ -400,6 +433,27 @@ protected void handlePingResponse(Parcel parcel) {
pingTracker.onPingResponse(parcel.readInt());
}

/**
* A base for all implementations of the client handshake.
*
* <p>Supports a clean migration away from the legacy approach, one client at a time.
*/
private interface ClientHandshake {
/**
* Notifies the implementation that the binding has succeeded and we are now connected to the
* server's "endpoint" which can be reached at 'endpointBinder'.
*/
@MainThread
void onBound(OneWayBinderProxy endpointBinder);

/**
* Notifies the implementation that we've received a valid SETUP_TRANSPORT transaction from a
* server that can be reached at 'serverBinder'.
*/
@BinderThread
void handleSetupTransport(OneWayBinderProxy serverBinder);
}

private static ClientStream newFailingClientStream(
Status failure, Attributes attributes, Metadata headers, ClientStreamTracer[] tracers) {
StatsTraceContext statsTraceContext =
Expand Down