2525import android .os .IBinder ;
2626import android .os .Parcel ;
2727import android .os .Process ;
28+ import androidx .annotation .BinderThread ;
29+ import androidx .annotation .MainThread ;
2830import com .google .common .base .Ticker ;
2931import com .google .common .util .concurrent .FutureCallback ;
3032import 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
@@ -114,6 +119,7 @@ public BinderClientTransport(
114119 Boolean preAuthServerOverride = options .getEagAttributes ().get (PRE_AUTH_SERVER_OVERRIDE );
115120 this .preAuthorizeServer =
116121 preAuthServerOverride != null ? preAuthServerOverride : factory .preAuthorizeServers ;
122+ this .handshake = new LegacyClientHandshake ();
117123 numInUseStreams = new AtomicInteger ();
118124 pingTracker = new PingTracker (Ticker .systemTicker (), (id ) -> sendPing (id ));
119125
@@ -136,7 +142,9 @@ void releaseExecutors() {
136142
137143 @ Override
138144 public synchronized void onBound (IBinder binder ) {
139- sendSetupTransaction (binderDecorator .decorate (OneWayBinderProxy .wrap (binder , offloadExecutor )));
145+ OneWayBinderProxy binderProxy = OneWayBinderProxy .wrap (binder , offloadExecutor );
146+ binderProxy = binderDecorator .decorate (binderProxy );
147+ handshake .onBound (binderProxy );
140148 }
141149
142150 @ Override
@@ -340,10 +348,11 @@ protected void handleSetupTransport(Parcel parcel) {
340348 Status .UNAVAILABLE .withDescription ("Failed to observe outgoing binder" ), true );
341349 return ;
342350 }
351+ handshake .handleSetupTransport ();
352+ }
343353
344- int remoteUid = Binder .getCallingUid ();
345- restrictIncomingBinderToCallsFrom (remoteUid );
346- attributes = setSecurityAttrs (attributes , remoteUid );
354+ @ GuardedBy ("this" )
355+ private void checkServerAuthorization (int remoteUid ) {
347356 ListenableFuture <Status > authResultFuture = register (checkServerAuthorizationAsync (remoteUid ));
348357 Futures .addCallback (
349358 authResultFuture ,
@@ -376,7 +385,11 @@ private synchronized void handleAuthResult(Status authorization) {
376385 shutdownInternal (authorization , true );
377386 return ;
378387 }
388+ handshake .onServerAuthorizationOk ();
389+ }
379390
391+ @ GuardedBy ("this" )
392+ private void onHandshakeComplete () {
380393 setState (TransportState .READY );
381394 attributes = clientTransportListener .filterTransport (attributes );
382395 clientTransportListener .transportReady ();
@@ -397,6 +410,52 @@ protected void handlePingResponse(Parcel parcel) {
397410 pingTracker .onPingResponse (parcel .readInt ());
398411 }
399412
413+ /**
414+ * An abstract implementation of the client's connection handshake.
415+ *
416+ * <p>Supports a clean migration away from the legacy approach, one client at a time.
417+ */
418+ private interface ClientHandshake {
419+ /**
420+ * Notifies the implementation that the binding has succeeded and we are now connected to the
421+ * server's "endpoint" which can be reached at 'endpointBinder'.
422+ */
423+ @ MainThread
424+ void onBound (OneWayBinderProxy endpointBinder );
425+
426+ /** Notifies the implementation that we've received a valid SETUP_TRANSPORT transaction. */
427+ @ BinderThread
428+ void handleSetupTransport ();
429+
430+ /** Notifies the implementation that the SecurityPolicy check of the server succeeded. */
431+ void onServerAuthorizationOk ();
432+ }
433+
434+ private final class LegacyClientHandshake implements ClientHandshake {
435+ @ Override
436+ @ MainThread
437+ @ GuardedBy ("BinderClientTransport.this" ) // By way of @GuardedBy("this") `handshake` member.
438+ public void onBound (OneWayBinderProxy binder ) {
439+ sendSetupTransaction (binder );
440+ }
441+
442+ @ Override
443+ @ BinderThread
444+ @ GuardedBy ("BinderClientTransport.this" ) // By way of @GuardedBy("this") `handshake` member.
445+ public void handleSetupTransport () {
446+ int remoteUid = Binder .getCallingUid ();
447+ restrictIncomingBinderToCallsFrom (remoteUid );
448+ attributes = setSecurityAttrs (attributes , remoteUid );
449+ checkServerAuthorization (remoteUid );
450+ }
451+
452+ @ Override
453+ @ GuardedBy ("BinderClientTransport.this" ) // By way of @GuardedBy("this") `handshake` member.
454+ public void onServerAuthorizationOk () {
455+ onHandshakeComplete ();
456+ }
457+ }
458+
400459 private static ClientStream newFailingClientStream (
401460 Status failure , Attributes attributes , Metadata headers , ClientStreamTracer [] tracers ) {
402461 StatsTraceContext statsTraceContext =
0 commit comments