Skip to content

Commit 701f2dc

Browse files
committed
Pre-factor out the guts of the BinderClientTransport handshake.
Moves the existing handshake logic behind an interface using the strategy pattern. No functional change.
1 parent 9662f0f commit 701f2dc

File tree

1 file changed

+90
-37
lines changed

1 file changed

+90
-37
lines changed

binder/src/main/java/io/grpc/binder/internal/BinderClientTransport.java

Lines changed: 90 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import android.os.IBinder;
2626
import android.os.Parcel;
2727
import android.os.Process;
28+
import androidx.annotation.BinderThread;
29+
import androidx.annotation.MainThread;
2830
import com.google.common.base.Ticker;
2931
import com.google.common.util.concurrent.FutureCallback;
3032
import com.google.common.util.concurrent.Futures;
@@ -72,6 +74,9 @@ public final class BinderClientTransport extends BinderTransport
7274
private final SecurityPolicy securityPolicy;
7375
private final Bindable serviceBinding;
7476

77+
@GuardedBy("this")
78+
private final ClientHandshake handshake;
79+
7580
/** Number of ongoing calls which keep this transport "in-use". */
7681
private final AtomicInteger numInUseStreams;
7782

@@ -115,6 +120,7 @@ public BinderClientTransport(
115120
Boolean preAuthServerOverride = options.getEagAttributes().get(PRE_AUTH_SERVER_OVERRIDE);
116121
this.preAuthorizeServer =
117122
preAuthServerOverride != null ? preAuthServerOverride : factory.preAuthorizeServers;
123+
this.handshake = new LegacyClientHandshake();
118124
numInUseStreams = new AtomicInteger();
119125
pingTracker = new PingTracker(Ticker.systemTicker(), (id) -> sendPing(id));
120126

@@ -137,7 +143,9 @@ void releaseExecutors() {
137143

138144
@Override
139145
public synchronized void onBound(IBinder binder) {
140-
sendSetupTransaction(binderDecorator.decorate(OneWayBinderProxy.wrap(binder, offloadExecutor)));
146+
OneWayBinderProxy binderProxy = OneWayBinderProxy.wrap(binder, offloadExecutor);
147+
binderProxy = binderDecorator.decorate(binderProxy);
148+
handshake.onBound(binderProxy);
141149
}
142150

143151
@Override
@@ -315,7 +323,6 @@ void notifyTerminated() {
315323
@Override
316324
@GuardedBy("this")
317325
protected void handleSetupTransport(Parcel parcel) {
318-
int remoteUid = Binder.getCallingUid();
319326
if (inState(TransportState.SETUP)) {
320327
int version = parcel.readInt();
321328
IBinder binder = parcel.readStrongBinder();
@@ -325,24 +332,8 @@ protected void handleSetupTransport(Parcel parcel) {
325332
shutdownInternal(
326333
Status.UNAVAILABLE.withDescription("Malformed SETUP_TRANSPORT data"), true);
327334
} else {
328-
restrictIncomingBinderToCallsFrom(remoteUid);
329-
attributes = setSecurityAttrs(attributes, remoteUid);
330-
ListenableFuture<Status> authResultFuture =
331-
register(checkServerAuthorizationAsync(remoteUid));
332-
Futures.addCallback(
333-
authResultFuture,
334-
new FutureCallback<Status>() {
335-
@Override
336-
public void onSuccess(Status result) {
337-
handleAuthResult(binder, result);
338-
}
339-
340-
@Override
341-
public void onFailure(Throwable t) {
342-
handleAuthResult(t);
343-
}
344-
},
345-
offloadExecutor);
335+
OneWayBinderProxy binderProxy = OneWayBinderProxy.wrap(binder, offloadExecutor);
336+
handshake.handleSetupTransport(binderProxy);
346337
}
347338
}
348339
}
@@ -353,29 +344,71 @@ private ListenableFuture<Status> checkServerAuthorizationAsync(int remoteUid) {
353344
: Futures.submit(() -> securityPolicy.checkAuthorization(remoteUid), offloadExecutor);
354345
}
355346

356-
private synchronized void handleAuthResult(IBinder binder, Status authorization) {
357-
if (inState(TransportState.SETUP)) {
358-
if (!authorization.isOk()) {
359-
shutdownInternal(authorization, true);
360-
} else if (!setOutgoingBinder(OneWayBinderProxy.wrap(binder, offloadExecutor))) {
361-
shutdownInternal(
362-
Status.UNAVAILABLE.withDescription("Failed to observe outgoing binder"), true);
363-
} else {
364-
// Check state again, since a failure inside setOutgoingBinder (or a callback it
365-
// triggers), could have shut us down.
366-
if (!isShutdown()) {
367-
setState(TransportState.READY);
368-
attributes = clientTransportListener.filterTransport(attributes);
369-
clientTransportListener.transportReady();
370-
if (readyTimeoutFuture != null) {
371-
readyTimeoutFuture.cancel(false);
372-
readyTimeoutFuture = null;
347+
private final class LegacyClientHandshake implements ClientHandshake {
348+
@Override
349+
@MainThread
350+
@GuardedBy("BinderClientTransport.this") // By way of @GuardedBy("this") `handshake` member.
351+
public void onBound(OneWayBinderProxy binder) {
352+
sendSetupTransaction(binder);
353+
}
354+
355+
@Override
356+
@BinderThread
357+
@GuardedBy("BinderClientTransport.this") // By way of @GuardedBy("this") `handshake` member.
358+
public void handleSetupTransport(OneWayBinderProxy binder) {
359+
int remoteUid = Binder.getCallingUid();
360+
restrictIncomingBinderToCallsFrom(remoteUid);
361+
attributes = setSecurityAttrs(attributes, remoteUid);
362+
ListenableFuture<Status> authResultFuture =
363+
register(checkServerAuthorizationAsync(remoteUid));
364+
Futures.addCallback(
365+
authResultFuture,
366+
new FutureCallback<Status>() {
367+
@Override
368+
public void onSuccess(Status result) {
369+
synchronized (BinderClientTransport.this) {
370+
handleAuthResult(binder, result);
371+
}
372+
}
373+
374+
@Override
375+
public void onFailure(Throwable t) {
376+
BinderClientTransport.this.handleAuthResult(t);
377+
}
378+
},
379+
offloadExecutor);
380+
}
381+
382+
@GuardedBy("BinderClientTransport.this")
383+
private void handleAuthResult(OneWayBinderProxy binder, Status authorization) {
384+
if (inState(TransportState.SETUP)) {
385+
if (!authorization.isOk()) {
386+
shutdownInternal(authorization, true);
387+
} else if (!setOutgoingBinder(binder)) {
388+
shutdownInternal(
389+
Status.UNAVAILABLE.withDescription("Failed to observe outgoing binder"), true);
390+
} else {
391+
// Check state again, since a failure inside setOutgoingBinder (or a callback it
392+
// triggers), could have shut us down.
393+
if (!isShutdown()) {
394+
onHandshakeComplete();
373395
}
374396
}
375397
}
376398
}
377399
}
378400

401+
@GuardedBy("this")
402+
private void onHandshakeComplete() {
403+
setState(TransportState.READY);
404+
attributes = clientTransportListener.filterTransport(attributes);
405+
clientTransportListener.transportReady();
406+
if (readyTimeoutFuture != null) {
407+
readyTimeoutFuture.cancel(false);
408+
readyTimeoutFuture = null;
409+
}
410+
}
411+
379412
private synchronized void handleAuthResult(Throwable t) {
380413
shutdownInternal(
381414
Status.INTERNAL.withDescription("Could not evaluate SecurityPolicy").withCause(t), true);
@@ -387,6 +420,26 @@ protected void handlePingResponse(Parcel parcel) {
387420
pingTracker.onPingResponse(parcel.readInt());
388421
}
389422

423+
/**
424+
* A base for all implementations of the client handshake.
425+
*
426+
* <p>Supports a clean migration away from the legacy approach, one client at a time.
427+
*/
428+
private interface ClientHandshake {
429+
/**
430+
* Notifies the implementation that the binding has succeeded and we are now connected to the
431+
* server's "endpoint" which can be reached at 'endpointBinder'.
432+
*/
433+
@MainThread
434+
void onBound(OneWayBinderProxy endpointBinder);
435+
436+
/**
437+
* Notifies the implementation that we've received a valid SETUP_TRANSPORT transaction from a
438+
* server that can be reached at 'serverBinder'.
439+
*/
440+
@BinderThread
441+
void handleSetupTransport(OneWayBinderProxy serverBinder);
442+
}
390443

391444
private static ClientStream newFailingClientStream(
392445
Status failure, Attributes attributes, Metadata headers, ClientStreamTracer[] tracers) {

0 commit comments

Comments
 (0)