1616
1717package io .grpc .binder .internal ;
1818
19+ import static com .google .common .truth .Truth .assertThat ;
20+ import static java .util .concurrent .TimeUnit .MILLISECONDS ;
21+ import static org .mockito .Mockito .never ;
22+ import static org .mockito .Mockito .timeout ;
23+ import static org .mockito .Mockito .verify ;
1924import static org .robolectric .Shadows .shadowOf ;
2025
2126import android .app .Application ;
2227import android .content .Intent ;
28+ import android .content .pm .ApplicationInfo ;
29+ import android .content .pm .PackageInfo ;
30+ import android .content .pm .ServiceInfo ;
2331import androidx .test .core .app .ApplicationProvider ;
32+ import androidx .test .core .content .pm .ApplicationInfoBuilder ;
33+ import androidx .test .core .content .pm .PackageInfoBuilder ;
2434import com .google .common .collect .ImmutableList ;
35+ import io .grpc .Attributes ;
2536import io .grpc .ServerStreamTracer ;
37+ import io .grpc .Status ;
2638import io .grpc .binder .AndroidComponentAddress ;
39+ import io .grpc .binder .ApiConstants ;
40+ import io .grpc .binder .AsyncSecurityPolicy ;
41+ import io .grpc .binder .internal .SettableAsyncSecurityPolicy .AuthRequest ;
2742import io .grpc .internal .AbstractTransportTest ;
2843import io .grpc .internal .ClientTransportFactory .ClientTransportOptions ;
2944import io .grpc .internal .GrpcUtil ;
3045import io .grpc .internal .InternalServer ;
3146import io .grpc .internal .ManagedClientTransport ;
3247import io .grpc .internal .ObjectPool ;
3348import io .grpc .internal .SharedResourcePool ;
49+ import java .util .Collections ;
3450import java .util .List ;
3551import java .util .concurrent .Executor ;
3652import java .util .concurrent .ScheduledExecutorService ;
3753import org .junit .Before ;
3854import org .junit .Ignore ;
55+ import org .junit .Rule ;
3956import org .junit .Test ;
4057import org .junit .runner .RunWith ;
58+ import org .mockito .Mock ;
59+ import org .mockito .junit .MockitoJUnit ;
60+ import org .mockito .junit .MockitoRule ;
4161import org .robolectric .ParameterizedRobolectricTestRunner ;
4262import org .robolectric .ParameterizedRobolectricTestRunner .Parameter ;
4363import org .robolectric .ParameterizedRobolectricTestRunner .Parameters ;
4464import org .robolectric .annotation .LooperMode ;
4565import org .robolectric .annotation .LooperMode .Mode ;
66+ import org .robolectric .shadows .ShadowBinder ;
4667
4768/**
4869 * All of the AbstractTransportTest cases applied to {@link BinderTransport} running in a
@@ -68,15 +89,44 @@ public final class RobolectricBinderTransportTest extends AbstractTransportTest
6889 private final ObjectPool <Executor > serverExecutorPool =
6990 SharedResourcePool .forResource (GrpcUtil .SHARED_CHANNEL_EXECUTOR );
7091
92+ @ Rule public MockitoRule mocks = MockitoJUnit .rule ();
93+
94+ @ Mock AsyncSecurityPolicy mockClientSecurityPolicy ;
95+
96+ ApplicationInfo serverAppInfo ;
97+ PackageInfo serverPkgInfo ;
98+ ServiceInfo serviceInfo ;
99+
71100 private int nextServerAddress ;
72101
73- @ Parameter public boolean preAuthorizeServers ;
102+ @ Parameter public boolean preAuthServersParam ;
74103
75- @ Parameters (name = "preAuthorizeServers ={0}" )
104+ @ Parameters (name = "preAuthServersParam ={0}" )
76105 public static ImmutableList <Boolean > data () {
77106 return ImmutableList .of (true , false );
78107 }
79108
109+ @ Override
110+ public void setUp () {
111+ serverAppInfo =
112+ ApplicationInfoBuilder .newBuilder ().setPackageName ("the.server.package" ).build ();
113+ serverAppInfo .uid = android .os .Process .myUid ();
114+ serverPkgInfo =
115+ PackageInfoBuilder .newBuilder ()
116+ .setPackageName (serverAppInfo .packageName )
117+ .setApplicationInfo (serverAppInfo )
118+ .build ();
119+ shadowOf (application .getPackageManager ()).installPackage (serverPkgInfo );
120+
121+ serviceInfo = new ServiceInfo ();
122+ serviceInfo .name = "SomeService" ;
123+ serviceInfo .packageName = serverAppInfo .packageName ;
124+ serviceInfo .applicationInfo = serverAppInfo ;
125+ shadowOf (application .getPackageManager ()).addOrUpdateService (serviceInfo );
126+
127+ super .setUp ();
128+ }
129+
80130 @ Before
81131 public void requestRealisticBindServiceBehavior () {
82132 shadowOf (application ).setBindServiceCallsOnServiceConnectedDirectly (false );
@@ -85,10 +135,11 @@ public void requestRealisticBindServiceBehavior() {
85135
86136 @ Override
87137 protected InternalServer newServer (List <ServerStreamTracer .Factory > streamTracerFactories ) {
88- AndroidComponentAddress listenAddr = AndroidComponentAddress .forBindIntent (
89- new Intent ()
90- .setClassName (application .getPackageName (), "HostService" )
91- .setAction ("io.grpc.action.BIND." + nextServerAddress ++));
138+ AndroidComponentAddress listenAddr =
139+ AndroidComponentAddress .forBindIntent (
140+ new Intent ()
141+ .setClassName (serviceInfo .packageName , serviceInfo .name )
142+ .setAction ("io.grpc.action.BIND." + nextServerAddress ++));
92143
93144 BinderServer binderServer =
94145 new BinderServer .Builder ()
@@ -115,30 +166,101 @@ protected InternalServer newServer(
115166 return newServer (streamTracerFactories );
116167 }
117168
169+ BinderClientTransportFactory .Builder newClientTransportFactoryBuilder () {
170+ return new BinderClientTransportFactory .Builder ()
171+ .setPreAuthorizeServers (preAuthServersParam )
172+ .setSourceContext (application )
173+ .setScheduledExecutorPool (executorServicePool )
174+ .setOffloadExecutorPool (offloadExecutorPool );
175+ }
176+
177+ BinderClientTransportBuilder newClientTransportBuilder () {
178+ return new BinderClientTransportBuilder ()
179+ .setClientTransportFactory (newClientTransportFactoryBuilder ().buildClientTransportFactory ())
180+ .setServerAddress (server .getListenSocketAddress ());
181+ }
182+
118183 @ Override
119184 protected ManagedClientTransport newClientTransport (InternalServer server ) {
120- BinderClientTransportFactory .Builder builder =
121- new BinderClientTransportFactory .Builder ()
122- .setPreAuthorizeServers (preAuthorizeServers )
123- .setSourceContext (application )
124- .setScheduledExecutorPool (executorServicePool )
125- .setOffloadExecutorPool (offloadExecutorPool );
126-
127185 ClientTransportOptions options = new ClientTransportOptions ();
128186 options .setEagAttributes (eagAttrs ());
129187 options .setChannelLogger (transportLogger ());
130188
131- return new BinderTransport . BinderClientTransport (
132- builder . buildClientTransportFactory (),
133- ( AndroidComponentAddress ) server . getListenSocketAddress (),
134- options );
189+ return newClientTransportBuilder ()
190+ . setServerAddress ( server . getListenSocketAddress ())
191+ . setClientTransportOptions ( options )
192+ . build ( );
135193 }
136194
137195 @ Override
138196 protected String testAuthority (InternalServer server ) {
139197 return ((AndroidComponentAddress ) server .getListenSocketAddress ()).getAuthority ();
140198 }
141199
200+ @ Test
201+ public void clientAuthorizesServerUidsInOrder () throws Exception {
202+ serverAppInfo .uid = 11111 ;
203+ shadowOf (application .getPackageManager ()).installPackage (serverPkgInfo );
204+ shadowOf (application .getPackageManager ()).addOrUpdateService (serviceInfo );
205+ server = newServer (Collections .emptyList ());
206+ server .start (serverListener );
207+
208+ SettableAsyncSecurityPolicy securityPolicy = new SettableAsyncSecurityPolicy ();
209+ client =
210+ newClientTransportBuilder ()
211+ .setClientTransportFactory (
212+ newClientTransportFactoryBuilder ()
213+ .setSecurityPolicy (securityPolicy )
214+ .buildClientTransportFactory ())
215+ .build ();
216+
217+ // TODO(jdcormie): In real Android, Binder#getCallingUid is thread-local but Robolectric only
218+ // lets us fake value this *globally*. So the ShadowBinder#setCallingUid() here unrealistically
219+ // affects the server's view of the client's uid too. For now this doesn't matter because this
220+ // test never exercises server SecurityPolicy.
221+ ShadowBinder .setCallingUid (22222 ); // UID of the server *process* which != serverAppInfo.uid.
222+ runIfNotNull (client .start (mockClientTransportListener ));
223+
224+ if (preAuthServersParam ) {
225+ AuthRequest preAuthRequest = securityPolicy .takeNextAuthRequest (TIMEOUT_MS , MILLISECONDS );
226+ assertThat (preAuthRequest .uid ).isEqualTo (serverAppInfo .uid );
227+ verify (mockClientTransportListener , never ()).transportReady ();
228+ preAuthRequest .setResult (Status .OK );
229+ }
230+
231+ AuthRequest authRequest = securityPolicy .takeNextAuthRequest (TIMEOUT_MS , MILLISECONDS );
232+ assertThat (authRequest .uid ).isEqualTo (22222 );
233+ verify (mockClientTransportListener , never ()).transportReady ();
234+ authRequest .setResult (Status .OK );
235+
236+ verify (mockClientTransportListener , timeout (TIMEOUT_MS )).transportReady ();
237+ }
238+
239+ @ Test
240+ public void eagAttributeCanOverrideChannelPreAuthServerSetting () throws Exception {
241+ server .start (serverListener );
242+ SettableAsyncSecurityPolicy securityPolicy = new SettableAsyncSecurityPolicy ();
243+ ClientTransportOptions options = new ClientTransportOptions ();
244+ options .setEagAttributes (
245+ Attributes .newBuilder ().set (ApiConstants .PRE_AUTH_SERVER_OVERRIDE , true ).build ());
246+ client =
247+ newClientTransportFactoryBuilder ()
248+ .setSecurityPolicy (securityPolicy )
249+ .buildClientTransportFactory ()
250+ .newClientTransport (server .getListenSocketAddress (), options , null );
251+ runIfNotNull (client .start (mockClientTransportListener ));
252+
253+ AuthRequest preAuthRequest = securityPolicy .takeNextAuthRequest (TIMEOUT_MS , MILLISECONDS );
254+ verify (mockClientTransportListener , never ()).transportReady ();
255+ preAuthRequest .setResult (Status .OK );
256+
257+ AuthRequest authRequest = securityPolicy .takeNextAuthRequest (TIMEOUT_MS , MILLISECONDS );
258+ verify (mockClientTransportListener , never ()).transportReady ();
259+ authRequest .setResult (Status .OK );
260+
261+ verify (mockClientTransportListener , timeout (TIMEOUT_MS )).transportReady ();
262+ }
263+
142264 @ Test
143265 @ Ignore ("See BinderTransportTest#socketStats." )
144266 @ Override
0 commit comments