google-java-format binder/src/*/*.java (#11297)

https://github.com/grpc/grpc-java/blob/master/CONTRIBUTING.md#code-style

We've been talking about an incremental approach in https://github.com/grpc/grpc-java/issues/1664 but https://github.com/google/google-java-format/issues/1114 causes a bunch of manual formatting toil every time I run ~/google-java-format-diff.py because we have a LOT of lines >100 characters. Establishing a gjf-clean baseline will make things a lot easier for me.
This commit is contained in:
John Cormie 2024-06-24 09:42:31 -07:00 committed by GitHub
parent 46e54aeb4b
commit 5770114d08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
46 changed files with 522 additions and 592 deletions

View File

@ -78,8 +78,8 @@ public final class BinderChannelSmokeTest {
private static final int SLIGHTLY_MORE_THAN_ONE_BLOCK = 16 * 1024 + 100; private static final int SLIGHTLY_MORE_THAN_ONE_BLOCK = 16 * 1024 + 100;
private static final String MSG = "Some text which will be repeated many many times"; private static final String MSG = "Some text which will be repeated many many times";
private static final String SERVER_TARGET_URI = "fake://server"; private static final String SERVER_TARGET_URI = "fake://server";
private static final Metadata.Key<PoisonParcelable> POISON_KEY = ParcelableUtils.metadataKey( private static final Metadata.Key<PoisonParcelable> POISON_KEY =
"poison-bin", PoisonParcelable.CREATOR); ParcelableUtils.metadataKey("poison-bin", PoisonParcelable.CREATOR);
final MethodDescriptor<String, String> method = final MethodDescriptor<String, String> method =
MethodDescriptor.newBuilder(StringMarshaller.INSTANCE, StringMarshaller.INSTANCE) MethodDescriptor.newBuilder(StringMarshaller.INSTANCE, StringMarshaller.INSTANCE)
@ -140,22 +140,27 @@ public final class BinderChannelSmokeTest {
AndroidComponentAddress serverAddress = HostServices.allocateService(appContext); AndroidComponentAddress serverAddress = HostServices.allocateService(appContext);
fakeNameResolverProvider = new FakeNameResolverProvider(SERVER_TARGET_URI, serverAddress); fakeNameResolverProvider = new FakeNameResolverProvider(SERVER_TARGET_URI, serverAddress);
NameResolverRegistry.getDefaultRegistry().register(fakeNameResolverProvider); NameResolverRegistry.getDefaultRegistry().register(fakeNameResolverProvider);
HostServices.configureService(serverAddress, HostServices.configureService(
serverAddress,
HostServices.serviceParamsBuilder() HostServices.serviceParamsBuilder()
.setServerFactory((service, receiver) -> .setServerFactory(
BinderServerBuilder.forAddress(serverAddress, receiver) (service, receiver) ->
.inboundParcelablePolicy(InboundParcelablePolicy.newBuilder() BinderServerBuilder.forAddress(serverAddress, receiver)
.setAcceptParcelableMetadataValues(true) .inboundParcelablePolicy(
InboundParcelablePolicy.newBuilder()
.setAcceptParcelableMetadataValues(true)
.build())
.addService(serviceDef)
.build()) .build())
.addService(serviceDef)
.build())
.build()); .build());
channel = BinderChannelBuilder.forAddress(serverAddress, appContext) channel =
.inboundParcelablePolicy(InboundParcelablePolicy.newBuilder() BinderChannelBuilder.forAddress(serverAddress, appContext)
.setAcceptParcelableMetadataValues(true) .inboundParcelablePolicy(
.build()) InboundParcelablePolicy.newBuilder()
.build(); .setAcceptParcelableMetadataValues(true)
.build())
.build();
} }
@After @After
@ -253,8 +258,8 @@ public final class BinderChannelSmokeTest {
Metadata extraHeadersToSend = new Metadata(); Metadata extraHeadersToSend = new Metadata();
extraHeadersToSend.put(POISON_KEY, bad); extraHeadersToSend.put(POISON_KEY, bad);
Channel interceptedChannel = Channel interceptedChannel =
ClientInterceptors.intercept(channel, ClientInterceptors.intercept(
MetadataUtils.newAttachHeadersInterceptor(extraHeadersToSend)); channel, MetadataUtils.newAttachHeadersInterceptor(extraHeadersToSend));
CallOptions callOptions = CallOptions.DEFAULT.withDeadlineAfter(5, SECONDS); CallOptions callOptions = CallOptions.DEFAULT.withDeadlineAfter(5, SECONDS);
try { try {
ClientCalls.blockingUnaryCall(interceptedChannel, method, callOptions, "hello"); ClientCalls.blockingUnaryCall(interceptedChannel, method, callOptions, "hello");
@ -361,33 +366,36 @@ public final class BinderChannelSmokeTest {
class AddParcelableServerInterceptor implements ServerInterceptor { class AddParcelableServerInterceptor implements ServerInterceptor {
@Override @Override
public <ReqT, RespT> Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, public <ReqT, RespT> Listener<ReqT> interceptCall(
Metadata headers, ServerCallHandler<ReqT, RespT> next) { ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
return next.startCall(new SimpleForwardingServerCall<ReqT, RespT>(call) { return next.startCall(
@Override new SimpleForwardingServerCall<ReqT, RespT>(call) {
public void sendHeaders(Metadata headers) { @Override
if (parcelableForResponseHeaders != null) { public void sendHeaders(Metadata headers) {
headers.put(POISON_KEY, parcelableForResponseHeaders); if (parcelableForResponseHeaders != null) {
} headers.put(POISON_KEY, parcelableForResponseHeaders);
super.sendHeaders(headers); }
} super.sendHeaders(headers);
}, headers); }
},
headers);
} }
} }
static class PoisonParcelable implements Parcelable { static class PoisonParcelable implements Parcelable {
public static final Creator<PoisonParcelable> CREATOR = new Parcelable.Creator<PoisonParcelable>() { public static final Creator<PoisonParcelable> CREATOR =
@Override new Parcelable.Creator<PoisonParcelable>() {
public PoisonParcelable createFromParcel(Parcel parcel) { @Override
throw new RuntimeException("ouch"); public PoisonParcelable createFromParcel(Parcel parcel) {
} throw new RuntimeException("ouch");
}
@Override @Override
public PoisonParcelable[] newArray(int n) { public PoisonParcelable[] newArray(int n) {
return new PoisonParcelable[n]; return new PoisonParcelable[n];
} }
}; };
@Override @Override
public int describeContents() { public int describeContents() {
@ -395,7 +403,6 @@ public final class BinderChannelSmokeTest {
} }
@Override @Override
public void writeToParcel(Parcel parcel, int flags) { public void writeToParcel(Parcel parcel, int flags) {}
}
} }
} }

View File

@ -47,7 +47,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@ -111,15 +110,14 @@ public final class BinderSecurityTest {
private void createChannel(ServerSecurityPolicy serverPolicy, SecurityPolicy channelPolicy) private void createChannel(ServerSecurityPolicy serverPolicy, SecurityPolicy channelPolicy)
throws Exception { throws Exception {
AndroidComponentAddress addr = HostServices.allocateService(appContext); AndroidComponentAddress addr = HostServices.allocateService(appContext);
HostServices.configureService(addr, HostServices.configureService(
addr,
HostServices.serviceParamsBuilder() HostServices.serviceParamsBuilder()
.setServerFactory((service, receiver) -> buildServer(addr, receiver, serverPolicy)) .setServerFactory((service, receiver) -> buildServer(addr, receiver, serverPolicy))
.build()); .build());
channel = channel =
BinderChannelBuilder.forAddress(addr, appContext) BinderChannelBuilder.forAddress(addr, appContext).securityPolicy(channelPolicy).build();
.securityPolicy(channelPolicy)
.build();
} }
private Server buildServer( private Server buildServer(
@ -149,7 +147,7 @@ public final class BinderSecurityTest {
try { try {
ClientCalls.blockingUnaryCall(channel, method, CallOptions.DEFAULT, null); ClientCalls.blockingUnaryCall(channel, method, CallOptions.DEFAULT, null);
fail("Expected call to " + method.getFullMethodName() + " to fail but it succeeded."); fail("Expected call to " + method.getFullMethodName() + " to fail but it succeeded.");
throw new AssertionError(); // impossible throw new AssertionError(); // impossible
} catch (StatusRuntimeException sre) { } catch (StatusRuntimeException sre) {
assertThat(sre.getStatus().getCode()).isEqualTo(status.getCode()); assertThat(sre.getStatus().getCode()).isEqualTo(status.getCode());
return sre; return sre;
@ -186,12 +184,14 @@ public final class BinderSecurityTest {
IllegalStateException originalException = new IllegalStateException(errorMessage); IllegalStateException originalException = new IllegalStateException(errorMessage);
createChannel( createChannel(
ServerSecurityPolicy.newBuilder() ServerSecurityPolicy.newBuilder()
.servicePolicy("foo", new AsyncSecurityPolicy() { .servicePolicy(
@Override "foo",
public ListenableFuture<Status> checkAuthorizationAsync(int uid) { new AsyncSecurityPolicy() {
return Futures.immediateFailedFuture(originalException); @Override
} public ListenableFuture<Status> checkAuthorizationAsync(int uid) {
}) return Futures.immediateFailedFuture(originalException);
}
})
.build(), .build(),
SecurityPolicies.internalOnly()); SecurityPolicies.internalOnly());
MethodDescriptor<Empty, Empty> method = methods.get("foo/method0"); MethodDescriptor<Empty, Empty> method = methods.get("foo/method0");
@ -205,15 +205,17 @@ public final class BinderSecurityTest {
AtomicReference<Boolean> firstAttempt = new AtomicReference<>(true); AtomicReference<Boolean> firstAttempt = new AtomicReference<>(true);
createChannel( createChannel(
ServerSecurityPolicy.newBuilder() ServerSecurityPolicy.newBuilder()
.servicePolicy("foo", new AsyncSecurityPolicy() { .servicePolicy(
@Override "foo",
public ListenableFuture<Status> checkAuthorizationAsync(int uid) { new AsyncSecurityPolicy() {
if (firstAttempt.getAndSet(false)) { @Override
return Futures.immediateFailedFuture(new IllegalStateException()); public ListenableFuture<Status> checkAuthorizationAsync(int uid) {
} if (firstAttempt.getAndSet(false)) {
return Futures.immediateFuture(Status.OK); return Futures.immediateFailedFuture(new IllegalStateException());
} }
}) return Futures.immediateFuture(Status.OK);
}
})
.build(), .build(),
SecurityPolicies.internalOnly()); SecurityPolicies.internalOnly());
MethodDescriptor<Empty, Empty> method = methods.get("foo/method0"); MethodDescriptor<Empty, Empty> method = methods.get("foo/method0");
@ -227,15 +229,17 @@ public final class BinderSecurityTest {
AtomicReference<Boolean> firstAttempt = new AtomicReference<>(true); AtomicReference<Boolean> firstAttempt = new AtomicReference<>(true);
createChannel( createChannel(
ServerSecurityPolicy.newBuilder() ServerSecurityPolicy.newBuilder()
.servicePolicy("foo", new AsyncSecurityPolicy() { .servicePolicy(
@Override "foo",
public ListenableFuture<Status> checkAuthorizationAsync(int uid) { new AsyncSecurityPolicy() {
if (firstAttempt.getAndSet(false)) { @Override
return Futures.immediateCancelledFuture(); public ListenableFuture<Status> checkAuthorizationAsync(int uid) {
} if (firstAttempt.getAndSet(false)) {
return Futures.immediateFuture(Status.OK); return Futures.immediateCancelledFuture();
} }
}) return Futures.immediateFuture(Status.OK);
}
})
.build(), .build(),
SecurityPolicies.internalOnly()); SecurityPolicies.internalOnly());
MethodDescriptor<Empty, Empty> method = methods.get("foo/method0"); MethodDescriptor<Empty, Empty> method = methods.get("foo/method0");
@ -275,11 +279,11 @@ public final class BinderSecurityTest {
@Test @Test
public void testPerServicePolicyAsync() throws Exception { public void testPerServicePolicyAsync() throws Exception {
createChannel( createChannel(
ServerSecurityPolicy.newBuilder() ServerSecurityPolicy.newBuilder()
.servicePolicy("foo", asyncPolicy((uid) -> Futures.immediateFuture(true))) .servicePolicy("foo", asyncPolicy((uid) -> Futures.immediateFuture(true)))
.servicePolicy("bar", asyncPolicy((uid) -> Futures.immediateFuture(false))) .servicePolicy("bar", asyncPolicy((uid) -> Futures.immediateFuture(false)))
.build(), .build(),
SecurityPolicies.internalOnly()); SecurityPolicies.internalOnly());
assertThat(methods).isNotEmpty(); assertThat(methods).isNotEmpty();
for (MethodDescriptor<Empty, Empty> method : methods.values()) { for (MethodDescriptor<Empty, Empty> method : methods.values()) {
@ -326,11 +330,10 @@ public final class BinderSecurityTest {
return new AsyncSecurityPolicy() { return new AsyncSecurityPolicy() {
@Override @Override
public ListenableFuture<Status> checkAuthorizationAsync(int uid) { public ListenableFuture<Status> checkAuthorizationAsync(int uid) {
return Futures return Futures.transform(
.transform( func.apply(uid),
func.apply(uid), allowed -> allowed ? Status.OK : Status.PERMISSION_DENIED,
allowed -> allowed ? Status.OK : Status.PERMISSION_DENIED, MoreExecutors.directExecutor());
MoreExecutors.directExecutor());
} }
}; };
} }
@ -340,9 +343,7 @@ public final class BinderSecurityTest {
@Override @Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall( public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
ServerCall<ReqT, RespT> call, ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
Metadata headers,
ServerCallHandler<ReqT, RespT> next) {
numInterceptedCalls += 1; numInterceptedCalls += 1;
return next.startCall(call, headers); return next.startCall(call, headers);
} }

View File

@ -16,7 +16,6 @@
package io.grpc.binder; package io.grpc.binder;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.concurrent.TimeUnit.SECONDS;
@ -30,20 +29,12 @@ import android.os.RemoteException;
import androidx.lifecycle.LifecycleService; import androidx.lifecycle.LifecycleService;
import com.google.auto.value.AutoValue; import com.google.auto.value.AutoValue;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import io.grpc.NameResolver;
import io.grpc.Server; import io.grpc.Server;
import io.grpc.ServerServiceDefinition;
import io.grpc.ServerStreamTracer;
import io.grpc.binder.AndroidComponentAddress;
import io.grpc.internal.InternalServer;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -64,7 +55,6 @@ public final class HostServices {
HostService1.class, HostService2.class, HostService1.class, HostService2.class,
}; };
public interface ServerFactory { public interface ServerFactory {
Server createServer(Service service, IBinderReceiver receiver); Server createServer(Service service, IBinderReceiver receiver);
} }

View File

@ -80,9 +80,8 @@ import org.junit.runner.RunWith;
public final class BinderClientTransportTest { public final class BinderClientTransportTest {
private static final long TIMEOUT_SECONDS = 5; private static final long TIMEOUT_SECONDS = 5;
private static final ClientStreamTracer[] tracers = new ClientStreamTracer[] { private static final ClientStreamTracer[] tracers =
new ClientStreamTracer() {} new ClientStreamTracer[] {new ClientStreamTracer() {}};
};
private final Context appContext = ApplicationProvider.getApplicationContext(); private final Context appContext = ApplicationProvider.getApplicationContext();
@ -149,10 +148,11 @@ public final class BinderClientTransportTest {
} }
private class BinderClientTransportBuilder { private class BinderClientTransportBuilder {
final BinderClientTransportFactory.Builder factoryBuilder = new BinderClientTransportFactory.Builder() final BinderClientTransportFactory.Builder factoryBuilder =
.setSourceContext(appContext) new BinderClientTransportFactory.Builder()
.setScheduledExecutorPool(executorServicePool) .setSourceContext(appContext)
.setOffloadExecutorPool(offloadServicePool); .setScheduledExecutorPool(executorServicePool)
.setOffloadExecutorPool(offloadServicePool);
public BinderClientTransportBuilder setSecurityPolicy(SecurityPolicy securityPolicy) { public BinderClientTransportBuilder setSecurityPolicy(SecurityPolicy securityPolicy) {
factoryBuilder.setSecurityPolicy(securityPolicy); factoryBuilder.setSecurityPolicy(securityPolicy);
@ -171,7 +171,8 @@ public final class BinderClientTransportTest {
} }
public BinderTransport.BinderClientTransport build() { public BinderTransport.BinderClientTransport build() {
return factoryBuilder.buildClientTransportFactory() return factoryBuilder
.buildClientTransportFactory()
.newClientTransport(serverAddress, new ClientTransportOptions(), null); .newClientTransport(serverAddress, new ClientTransportOptions(), null);
} }
} }
@ -197,8 +198,8 @@ public final class BinderClientTransportTest {
public void testShutdownBeforeStreamStart_b153326034() throws Exception { public void testShutdownBeforeStreamStart_b153326034() throws Exception {
transport = new BinderClientTransportBuilder().build(); transport = new BinderClientTransportBuilder().build();
startAndAwaitReady(transport, transportListener); startAndAwaitReady(transport, transportListener);
ClientStream stream = transport.newStream( ClientStream stream =
methodDesc, new Metadata(), CallOptions.DEFAULT, tracers); transport.newStream(methodDesc, new Metadata(), CallOptions.DEFAULT, tracers);
transport.shutdownNow(Status.UNKNOWN.withDescription("reasons")); transport.shutdownNow(Status.UNKNOWN.withDescription("reasons"));
// This shouldn't throw an exception. // This shouldn't throw an exception.
@ -284,7 +285,8 @@ public final class BinderClientTransportTest {
@Test @Test
public void testNewStreamBeforeTransportReadyFails() throws Exception { public void testNewStreamBeforeTransportReadyFails() throws Exception {
// Use a special SecurityPolicy that lets us act before the transport is setup/ready. // Use a special SecurityPolicy that lets us act before the transport is setup/ready.
transport = new BinderClientTransportBuilder().setSecurityPolicy(blockingSecurityPolicy).build(); transport =
new BinderClientTransportBuilder().setSecurityPolicy(blockingSecurityPolicy).build();
transport.start(transportListener).run(); transport.start(transportListener).run();
ClientStream stream = ClientStream stream =
transport.newStream(streamingMethodDesc, new Metadata(), CallOptions.DEFAULT, tracers); transport.newStream(streamingMethodDesc, new Metadata(), CallOptions.DEFAULT, tracers);
@ -299,12 +301,10 @@ public final class BinderClientTransportTest {
@Test @Test
public void testTxnFailureDuringSetup() throws Exception { public void testTxnFailureDuringSetup() throws Exception {
BlockingBinderDecorator<ThrowingOneWayBinderProxy> decorator = new BlockingBinderDecorator<>(); BlockingBinderDecorator<ThrowingOneWayBinderProxy> decorator = new BlockingBinderDecorator<>();
transport = new BinderClientTransportBuilder() transport = new BinderClientTransportBuilder().setBinderDecorator(decorator).build();
.setBinderDecorator(decorator)
.build();
transport.start(transportListener).run(); transport.start(transportListener).run();
ThrowingOneWayBinderProxy endpointBinder = new ThrowingOneWayBinderProxy( ThrowingOneWayBinderProxy endpointBinder =
decorator.takeNextRequest()); new ThrowingOneWayBinderProxy(decorator.takeNextRequest());
DeadObjectException doe = new DeadObjectException("ouch"); DeadObjectException doe = new DeadObjectException("ouch");
endpointBinder.setRemoteException(doe); endpointBinder.setRemoteException(doe);
decorator.putNextResult(endpointBinder); decorator.putNextResult(endpointBinder);
@ -326,15 +326,13 @@ public final class BinderClientTransportTest {
@Test @Test
public void testTxnFailurePostSetup() throws Exception { public void testTxnFailurePostSetup() throws Exception {
BlockingBinderDecorator<ThrowingOneWayBinderProxy> decorator = new BlockingBinderDecorator<>(); BlockingBinderDecorator<ThrowingOneWayBinderProxy> decorator = new BlockingBinderDecorator<>();
transport = new BinderClientTransportBuilder() transport = new BinderClientTransportBuilder().setBinderDecorator(decorator).build();
.setBinderDecorator(decorator)
.build();
transport.start(transportListener).run(); transport.start(transportListener).run();
ThrowingOneWayBinderProxy endpointBinder = new ThrowingOneWayBinderProxy( ThrowingOneWayBinderProxy endpointBinder =
decorator.takeNextRequest()); new ThrowingOneWayBinderProxy(decorator.takeNextRequest());
decorator.putNextResult(endpointBinder); decorator.putNextResult(endpointBinder);
ThrowingOneWayBinderProxy serverBinder = new ThrowingOneWayBinderProxy( ThrowingOneWayBinderProxy serverBinder =
decorator.takeNextRequest()); new ThrowingOneWayBinderProxy(decorator.takeNextRequest());
DeadObjectException doe = new DeadObjectException("ouch"); DeadObjectException doe = new DeadObjectException("ouch");
serverBinder.setRemoteException(doe); serverBinder.setRemoteException(doe);
decorator.putNextResult(serverBinder); decorator.putNextResult(serverBinder);
@ -355,13 +353,14 @@ public final class BinderClientTransportTest {
@Test @Test
public void testBlackHoleEndpointConnectTimeout() throws Exception { public void testBlackHoleEndpointConnectTimeout() throws Exception {
BlockingBinderDecorator<BlackHoleOneWayBinderProxy> decorator = new BlockingBinderDecorator<>(); BlockingBinderDecorator<BlackHoleOneWayBinderProxy> decorator = new BlockingBinderDecorator<>();
transport = new BinderClientTransportBuilder() transport =
.setBinderDecorator(decorator) new BinderClientTransportBuilder()
.setReadyTimeoutMillis(1_234) .setBinderDecorator(decorator)
.build(); .setReadyTimeoutMillis(1_234)
.build();
transport.start(transportListener).run(); transport.start(transportListener).run();
BlackHoleOneWayBinderProxy endpointBinder = new BlackHoleOneWayBinderProxy( BlackHoleOneWayBinderProxy endpointBinder =
decorator.takeNextRequest()); new BlackHoleOneWayBinderProxy(decorator.takeNextRequest());
endpointBinder.dropAllTransactions(true); endpointBinder.dropAllTransactions(true);
decorator.putNextResult(endpointBinder); decorator.putNextResult(endpointBinder);
Status transportStatus = transportListener.awaitShutdown(); Status transportStatus = transportListener.awaitShutdown();
@ -372,10 +371,11 @@ public final class BinderClientTransportTest {
@Test @Test
public void testBlackHoleSecurityPolicyConnectTimeout() throws Exception { public void testBlackHoleSecurityPolicyConnectTimeout() throws Exception {
transport = new BinderClientTransportBuilder() transport =
.setSecurityPolicy(blockingSecurityPolicy) new BinderClientTransportBuilder()
.setReadyTimeoutMillis(1_234) .setSecurityPolicy(blockingSecurityPolicy)
.build(); .setReadyTimeoutMillis(1_234)
.build();
transport.start(transportListener).run(); transport.start(transportListener).run();
Status transportStatus = transportListener.awaitShutdown(); Status transportStatus = transportListener.awaitShutdown();
assertThat(transportStatus.getCode()).isEqualTo(Code.DEADLINE_EXCEEDED); assertThat(transportStatus.getCode()).isEqualTo(Code.DEADLINE_EXCEEDED);
@ -387,9 +387,7 @@ public final class BinderClientTransportTest {
@Test @Test
public void testAsyncSecurityPolicyFailure() throws Exception { public void testAsyncSecurityPolicyFailure() throws Exception {
SettableAsyncSecurityPolicy securityPolicy = new SettableAsyncSecurityPolicy(); SettableAsyncSecurityPolicy securityPolicy = new SettableAsyncSecurityPolicy();
transport = new BinderClientTransportBuilder() transport = new BinderClientTransportBuilder().setSecurityPolicy(securityPolicy).build();
.setSecurityPolicy(securityPolicy)
.build();
RuntimeException exception = new NullPointerException(); RuntimeException exception = new NullPointerException();
securityPolicy.setAuthorizationException(exception); securityPolicy.setAuthorizationException(exception);
transport.start(transportListener).run(); transport.start(transportListener).run();
@ -402,9 +400,7 @@ public final class BinderClientTransportTest {
@Test @Test
public void testAsyncSecurityPolicySuccess() throws Exception { public void testAsyncSecurityPolicySuccess() throws Exception {
SettableAsyncSecurityPolicy securityPolicy = new SettableAsyncSecurityPolicy(); SettableAsyncSecurityPolicy securityPolicy = new SettableAsyncSecurityPolicy();
transport = new BinderClientTransportBuilder() transport = new BinderClientTransportBuilder().setSecurityPolicy(securityPolicy).build();
.setSecurityPolicy(securityPolicy)
.build();
securityPolicy.setAuthorizationResult(Status.PERMISSION_DENIED); securityPolicy.setAuthorizationResult(Status.PERMISSION_DENIED);
transport.start(transportListener).run(); transport.start(transportListener).run();
Status transportStatus = transportListener.awaitShutdown(); Status transportStatus = transportListener.awaitShutdown();
@ -572,9 +568,7 @@ public final class BinderClientTransportTest {
} }
} }
/** /** An AsyncSecurityPolicy that lets a test specify the outcome of checkAuthorizationAsync(). */
* An AsyncSecurityPolicy that lets a test specify the outcome of checkAuthorizationAsync().
*/
static class SettableAsyncSecurityPolicy extends AsyncSecurityPolicy { static class SettableAsyncSecurityPolicy extends AsyncSecurityPolicy {
private SettableFuture<Status> result = SettableFuture.create(); private SettableFuture<Status> result = SettableFuture.create();

View File

@ -73,7 +73,8 @@ public final class BinderTransportTest extends AbstractTransportTest {
.setStreamTracerFactories(streamTracerFactories) .setStreamTracerFactories(streamTracerFactories)
.build(); .build();
HostServices.configureService(addr, HostServices.configureService(
addr,
HostServices.serviceParamsBuilder() HostServices.serviceParamsBuilder()
.setRawBinderSupplier(() -> binderServer.getHostBinder()) .setRawBinderSupplier(() -> binderServer.getHostBinder())
.build()); .build());
@ -95,19 +96,18 @@ public final class BinderTransportTest extends AbstractTransportTest {
@Override @Override
protected ManagedClientTransport newClientTransport(InternalServer server) { protected ManagedClientTransport newClientTransport(InternalServer server) {
AndroidComponentAddress addr = (AndroidComponentAddress) server.getListenSocketAddress(); AndroidComponentAddress addr = (AndroidComponentAddress) server.getListenSocketAddress();
BinderClientTransportFactory.Builder builder = new BinderClientTransportFactory.Builder() BinderClientTransportFactory.Builder builder =
.setSourceContext(appContext) new BinderClientTransportFactory.Builder()
.setScheduledExecutorPool(executorServicePool) .setSourceContext(appContext)
.setOffloadExecutorPool(offloadExecutorPool); .setScheduledExecutorPool(executorServicePool)
.setOffloadExecutorPool(offloadExecutorPool);
ClientTransportOptions options = new ClientTransportOptions(); ClientTransportOptions options = new ClientTransportOptions();
options.setEagAttributes(eagAttrs()); options.setEagAttributes(eagAttrs());
options.setChannelLogger(transportLogger()); options.setChannelLogger(transportLogger());
return new BinderTransport.BinderClientTransport( return new BinderTransport.BinderClientTransport(
builder.buildClientTransportFactory(), builder.buildClientTransportFactory(), addr, options);
addr,
options);
} }
@Test @Test

View File

@ -20,16 +20,14 @@ import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import javax.annotation.Nullable; import javax.annotation.Nullable;
/** /** A collection of {@link OneWayBinderProxy}-related test helpers. */
* A collection of {@link OneWayBinderProxy}-related test helpers.
*/
public final class OneWayBinderProxies { public final class OneWayBinderProxies {
/** /**
* A {@link OneWayBinderProxy.Decorator} that blocks calling threads while an (external) test * A {@link OneWayBinderProxy.Decorator} that blocks calling threads while an (external) test
* provides the actual decoration. * provides the actual decoration.
*/ */
public static final class BlockingBinderDecorator<T extends OneWayBinderProxy> implements public static final class BlockingBinderDecorator<T extends OneWayBinderProxy>
OneWayBinderProxy.Decorator { implements OneWayBinderProxy.Decorator {
private final BlockingQueue<OneWayBinderProxy> requests = new LinkedBlockingQueue<>(); private final BlockingQueue<OneWayBinderProxy> requests = new LinkedBlockingQueue<>();
private final BlockingQueue<T> results = new LinkedBlockingQueue<>(); private final BlockingQueue<T> results = new LinkedBlockingQueue<>();
@ -37,16 +35,14 @@ public final class OneWayBinderProxies {
* Returns the next {@link OneWayBinderProxy} that needs decorating, blocking if it hasn't yet * Returns the next {@link OneWayBinderProxy} that needs decorating, blocking if it hasn't yet
* been provided to {@link #decorate}. * been provided to {@link #decorate}.
* *
* <p>Follow this with a call to {@link #putNextResult(OneWayBinderProxy)} to provide * <p>Follow this with a call to {@link #putNextResult(OneWayBinderProxy)} to provide the result
* the result of {@link #decorate} and unblock the waiting caller. * of {@link #decorate} and unblock the waiting caller.
*/ */
public OneWayBinderProxy takeNextRequest() throws InterruptedException { public OneWayBinderProxy takeNextRequest() throws InterruptedException {
return requests.take(); return requests.take();
} }
/** /** Provides the next value to return from {@link #decorate}. */
* Provides the next value to return from {@link #decorate}.
*/
public void putNextResult(T next) throws InterruptedException { public void putNextResult(T next) throws InterruptedException {
results.put(next); results.put(next);
} }
@ -63,13 +59,10 @@ public final class OneWayBinderProxies {
} }
} }
/** /** A {@link OneWayBinderProxy} decorator whose transact method can artificially throw. */
* A {@link OneWayBinderProxy} decorator whose transact method can artificially throw.
*/
public static final class ThrowingOneWayBinderProxy extends OneWayBinderProxy { public static final class ThrowingOneWayBinderProxy extends OneWayBinderProxy {
private final OneWayBinderProxy wrapped; private final OneWayBinderProxy wrapped;
@Nullable @Nullable private RemoteException remoteException;
private RemoteException remoteException;
ThrowingOneWayBinderProxy(OneWayBinderProxy wrapped) { ThrowingOneWayBinderProxy(OneWayBinderProxy wrapped) {
super(wrapped.getDelegate()); super(wrapped.getDelegate());
@ -127,5 +120,6 @@ public final class OneWayBinderProxies {
} }
// Cannot be instantiated. // Cannot be instantiated.
private OneWayBinderProxies() {}; private OneWayBinderProxies() {}
;
} }

View File

@ -72,8 +72,8 @@ public final class AndroidComponentAddress extends SocketAddress {
} }
/** /**
* Creates an address referencing a {@link android.app.Service} in another * Creates an address referencing a {@link android.app.Service} in another application and using
* application and using the default binding {@link Intent}. * the default binding {@link Intent}.
* *
* @param applicationPackage The package name of the application containing the server. * @param applicationPackage The package name of the application containing the server.
* @param serviceClassName The full class name of the Android Service to bind to. * @param serviceClassName The full class name of the Android Service to bind to.

View File

@ -19,7 +19,6 @@ package io.grpc.binder;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import io.grpc.ExperimentalApi; import io.grpc.ExperimentalApi;
import io.grpc.Status; import io.grpc.Status;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import javax.annotation.CheckReturnValue; import javax.annotation.CheckReturnValue;
@ -37,24 +36,24 @@ import javax.annotation.CheckReturnValue;
@CheckReturnValue @CheckReturnValue
public abstract class AsyncSecurityPolicy extends SecurityPolicy { public abstract class AsyncSecurityPolicy extends SecurityPolicy {
/** /**
* @deprecated Prefer {@link #checkAuthorizationAsync(int)} for async or slow calls or subclass * @deprecated Prefer {@link #checkAuthorizationAsync(int)} for async or slow calls or subclass
* {@link SecurityPolicy} directly for quick, synchronous implementations. * {@link SecurityPolicy} directly for quick, synchronous implementations.
*/ */
@Override @Override
@Deprecated @Deprecated
public final Status checkAuthorization(int uid) { public final Status checkAuthorization(int uid) {
try { try {
return checkAuthorizationAsync(uid).get(); return checkAuthorizationAsync(uid).get();
} catch (ExecutionException e) { } catch (ExecutionException e) {
return Status.fromThrowable(e); return Status.fromThrowable(e);
} catch (CancellationException e) { } catch (CancellationException e) {
return Status.CANCELLED.withCause(e); return Status.CANCELLED.withCause(e);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); // re-set the current thread's interruption state Thread.currentThread().interrupt(); // re-set the current thread's interruption state
return Status.CANCELLED.withCause(e); return Status.CANCELLED.withCause(e);
}
} }
}
/** /**
* Decides whether the given Android UID is authorized. (Validity is implementation dependent). * Decides whether the given Android UID is authorized. (Validity is implementation dependent).

View File

@ -42,8 +42,7 @@ import javax.annotation.Nullable;
* Services</a> * Services</a>
*/ */
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022") @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public final class BinderChannelBuilder public final class BinderChannelBuilder extends ForwardingChannelBuilder<BinderChannelBuilder> {
extends ForwardingChannelBuilder<BinderChannelBuilder> {
/** /**
* Creates a channel builder that will bind to a remote Android service. * Creates a channel builder that will bind to a remote Android service.
@ -97,8 +96,8 @@ public final class BinderChannelBuilder
} }
/** /**
* Creates a channel builder that will bind to a remote Android service, via a string * Creates a channel builder that will bind to a remote Android service, via a string target name
* target name which will be resolved. * which will be resolved.
* *
* <p>The underlying Android binding will be torn down when the channel becomes idle. This happens * <p>The underlying Android binding will be torn down when the channel becomes idle. This happens
* after 30 minutes without use by default but can be configured via {@link * after 30 minutes without use by default but can be configured via {@link
@ -109,16 +108,13 @@ public final class BinderChannelBuilder
* resulting builder. They will not be shut down automatically. * resulting builder. They will not be shut down automatically.
* *
* @param target A target uri which should resolve into an {@link AndroidComponentAddress} * @param target A target uri which should resolve into an {@link AndroidComponentAddress}
* referencing the service to bind to. * referencing the service to bind to.
* @param sourceContext the context to bind from (e.g. The current Activity or Application). * @param sourceContext the context to bind from (e.g. The current Activity or Application).
* @return a new builder * @return a new builder
*/ */
public static BinderChannelBuilder forTarget(String target, Context sourceContext) { public static BinderChannelBuilder forTarget(String target, Context sourceContext) {
return new BinderChannelBuilder( return new BinderChannelBuilder(
null, null, checkNotNull(target, "target"), sourceContext, BinderChannelCredentials.forDefault());
checkNotNull(target, "target"),
sourceContext,
BinderChannelCredentials.forDefault());
} }
/** /**
@ -147,18 +143,14 @@ public final class BinderChannelBuilder
null, checkNotNull(target, "target"), sourceContext, channelCredentials); null, checkNotNull(target, "target"), sourceContext, channelCredentials);
} }
/** /** Always fails. Call {@link #forAddress(AndroidComponentAddress, Context)} instead. */
* Always fails. Call {@link #forAddress(AndroidComponentAddress, Context)} instead.
*/
@DoNotCall("Unsupported. Use forAddress(AndroidComponentAddress, Context) instead") @DoNotCall("Unsupported. Use forAddress(AndroidComponentAddress, Context) instead")
public static BinderChannelBuilder forAddress(String name, int port) { public static BinderChannelBuilder forAddress(String name, int port) {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
"call forAddress(AndroidComponentAddress, Context) instead"); "call forAddress(AndroidComponentAddress, Context) instead");
} }
/** /** Always fails. Call {@link #forAddress(AndroidComponentAddress, Context)} instead. */
* Always fails. Call {@link #forAddress(AndroidComponentAddress, Context)} instead.
*/
@DoNotCall("Unsupported. Use forTarget(String, Context) instead") @DoNotCall("Unsupported. Use forTarget(String, Context) instead")
public static BinderChannelBuilder forTarget(String target) { public static BinderChannelBuilder forTarget(String target) {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
@ -175,23 +167,18 @@ public final class BinderChannelBuilder
@Nullable String target, @Nullable String target,
Context sourceContext, Context sourceContext,
BinderChannelCredentials channelCredentials) { BinderChannelCredentials channelCredentials) {
transportFactoryBuilder = new BinderClientTransportFactory.Builder() transportFactoryBuilder =
.setSourceContext(sourceContext) new BinderClientTransportFactory.Builder()
.setChannelCredentials(channelCredentials); .setSourceContext(sourceContext)
.setChannelCredentials(channelCredentials);
if (directAddress != null) { if (directAddress != null) {
managedChannelImplBuilder = managedChannelImplBuilder =
new ManagedChannelImplBuilder( new ManagedChannelImplBuilder(
directAddress, directAddress, directAddress.getAuthority(), transportFactoryBuilder, null);
directAddress.getAuthority(),
transportFactoryBuilder,
null);
} else { } else {
managedChannelImplBuilder = managedChannelImplBuilder =
new ManagedChannelImplBuilder( new ManagedChannelImplBuilder(target, transportFactoryBuilder, null);
target,
transportFactoryBuilder,
null);
} }
idleTimeout(60, TimeUnit.SECONDS); idleTimeout(60, TimeUnit.SECONDS);
} }
@ -218,7 +205,7 @@ public final class BinderChannelBuilder
*/ */
public BinderChannelBuilder scheduledExecutorService( public BinderChannelBuilder scheduledExecutorService(
ScheduledExecutorService scheduledExecutorService) { ScheduledExecutorService scheduledExecutorService) {
transportFactoryBuilder.setScheduledExecutorPool( transportFactoryBuilder.setScheduledExecutorPool(
new FixedObjectPool<>(checkNotNull(scheduledExecutorService, "scheduledExecutorService"))); new FixedObjectPool<>(checkNotNull(scheduledExecutorService, "scheduledExecutorService")));
return this; return this;
} }
@ -248,7 +235,7 @@ public final class BinderChannelBuilder
return this; return this;
} }
/** /**
* Provides the target {@UserHandle} of the remote Android service. * Provides the target {@UserHandle} of the remote Android service.
* *
* <p>When targetUserHandle is set, Context.bindServiceAsUser will used and additional Android * <p>When targetUserHandle is set, Context.bindServiceAsUser will used and additional Android
@ -274,10 +261,9 @@ public final class BinderChannelBuilder
} }
/** /**
* Disables the channel idle timeout and prevents it from being enabled. This * Disables the channel idle timeout and prevents it from being enabled. This allows a centralized
* allows a centralized application method to configure the channel builder * application method to configure the channel builder and return it, without worrying about
* and return it, without worrying about another part of the application * another part of the application accidentally enabling the idle timeout.
* accidentally enabling the idle timeout.
*/ */
public BinderChannelBuilder strictLifecycleManagement() { public BinderChannelBuilder strictLifecycleManagement() {
strictLifecycleManagement = true; strictLifecycleManagement = true;
@ -287,7 +273,9 @@ public final class BinderChannelBuilder
@Override @Override
public BinderChannelBuilder idleTimeout(long value, TimeUnit unit) { public BinderChannelBuilder idleTimeout(long value, TimeUnit unit) {
checkState(!strictLifecycleManagement, "Idle timeouts are not supported when strict lifecycle management is enabled"); checkState(
!strictLifecycleManagement,
"Idle timeouts are not supported when strict lifecycle management is enabled");
super.idleTimeout(value, unit); super.idleTimeout(value, unit);
return this; return this;
} }

View File

@ -20,26 +20,22 @@ import android.os.IBinder;
import io.grpc.Internal; import io.grpc.Internal;
import io.grpc.binder.internal.BinderTransportSecurity; import io.grpc.binder.internal.BinderTransportSecurity;
/** /** Helper class to expose IBinderReceiver methods for legacy internal builders. */
* Helper class to expose IBinderReceiver methods for legacy internal builders.
*/
@Internal @Internal
public class BinderInternal { public class BinderInternal {
/** /** Sets the receiver's {@link IBinder} using {@link IBinderReceiver#set(IBinder)}. */
* Sets the receiver's {@link IBinder} using {@link IBinderReceiver#set(IBinder)}.
*/
public static void setIBinder(IBinderReceiver receiver, IBinder binder) { public static void setIBinder(IBinderReceiver receiver, IBinder binder) {
receiver.set(binder); receiver.set(binder);
} }
/** /**
* Creates a {@link BinderTransportSecurity.ServerPolicyChecker} from a * Creates a {@link BinderTransportSecurity.ServerPolicyChecker} from a {@link
* {@link ServerSecurityPolicy}. This exposes to callers an interface to check security policies * ServerSecurityPolicy}. This exposes to callers an interface to check security policies without
* without causing hard dependencies on a specific class. * causing hard dependencies on a specific class.
*/ */
public static BinderTransportSecurity.ServerPolicyChecker createPolicyChecker( public static BinderTransportSecurity.ServerPolicyChecker createPolicyChecker(
ServerSecurityPolicy securityPolicy) { ServerSecurityPolicy securityPolicy) {
return securityPolicy::checkAuthorizationForServiceAsync; return securityPolicy::checkAuthorizationForServiceAsync;
} }
} }

View File

@ -30,35 +30,29 @@ import io.grpc.binder.internal.BinderServer;
import io.grpc.binder.internal.BinderTransportSecurity; import io.grpc.binder.internal.BinderTransportSecurity;
import io.grpc.internal.FixedObjectPool; import io.grpc.internal.FixedObjectPool;
import io.grpc.internal.ServerImplBuilder; import io.grpc.internal.ServerImplBuilder;
import java.io.File; import java.io.File;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
/** /** Builder for a server that services requests from an Android Service. */
* Builder for a server that services requests from an Android Service. public final class BinderServerBuilder extends ForwardingServerBuilder<BinderServerBuilder> {
*/
public final class BinderServerBuilder
extends ForwardingServerBuilder<BinderServerBuilder> {
/** /**
* Creates a server builder that will listen for bindings to the specified address. * Creates a server builder that will listen for bindings to the specified address.
* *
* <p>The listening {@link IBinder} associated with new {@link Server}s will be stored * <p>The listening {@link IBinder} associated with new {@link Server}s will be stored in {@code
* in {@code binderReceiver} upon {@link #build()}. Callers should return it from {@link * binderReceiver} upon {@link #build()}. Callers should return it from {@link
* Service#onBind(Intent)} when the binding intent matches {@code listenAddress}. * Service#onBind(Intent)} when the binding intent matches {@code listenAddress}.
* *
* @param listenAddress an Android Service and binding Intent associated with this server. * @param listenAddress an Android Service and binding Intent associated with this server.
* @param receiver an "out param" for the new {@link Server}'s listening {@link IBinder} * @param receiver an "out param" for the new {@link Server}'s listening {@link IBinder}
* @return a new builder * @return a new builder
*/ */
public static BinderServerBuilder forAddress(AndroidComponentAddress listenAddress, public static BinderServerBuilder forAddress(
IBinderReceiver receiver) { AndroidComponentAddress listenAddress, IBinderReceiver receiver) {
return new BinderServerBuilder(listenAddress, receiver); return new BinderServerBuilder(listenAddress, receiver);
} }
/** /** Always fails. Call {@link #forAddress(AndroidComponentAddress, IBinderReceiver)} instead. */
* Always fails. Call {@link #forAddress(AndroidComponentAddress, IBinderReceiver)} instead.
*/
@DoNotCall("Unsupported. Use forAddress() instead") @DoNotCall("Unsupported. Use forAddress() instead")
public static BinderServerBuilder forPort(int port) { public static BinderServerBuilder forPort(int port) {
throw new UnsupportedOperationException("call forAddress() instead"); throw new UnsupportedOperationException("call forAddress() instead");
@ -69,16 +63,17 @@ public final class BinderServerBuilder
private boolean isBuilt; private boolean isBuilt;
private BinderServerBuilder( private BinderServerBuilder(
AndroidComponentAddress listenAddress, AndroidComponentAddress listenAddress, IBinderReceiver binderReceiver) {
IBinderReceiver binderReceiver) {
internalBuilder.setListenAddress(listenAddress); internalBuilder.setListenAddress(listenAddress);
serverImplBuilder = new ServerImplBuilder(streamTracerFactories -> { serverImplBuilder =
internalBuilder.setStreamTracerFactories(streamTracerFactories); new ServerImplBuilder(
BinderServer server = internalBuilder.build(); streamTracerFactories -> {
BinderInternal.setIBinder(binderReceiver, server.getHostBinder()); internalBuilder.setStreamTracerFactories(streamTracerFactories);
return server; BinderServer server = internalBuilder.build();
}); BinderInternal.setIBinder(binderReceiver, server.getHostBinder());
return server;
});
// Disable stats and tracing by default. // Disable stats and tracing by default.
serverImplBuilder.setStatsEnabled(false); serverImplBuilder.setStatsEnabled(false);
@ -114,8 +109,8 @@ public final class BinderServerBuilder
*/ */
public BinderServerBuilder scheduledExecutorService( public BinderServerBuilder scheduledExecutorService(
ScheduledExecutorService scheduledExecutorService) { ScheduledExecutorService scheduledExecutorService) {
internalBuilder.setExecutorServicePool( internalBuilder.setExecutorServicePool(
new FixedObjectPool<>(checkNotNull(scheduledExecutorService, "scheduledExecutorService"))); new FixedObjectPool<>(checkNotNull(scheduledExecutorService, "scheduledExecutorService")));
return this; return this;
} }
@ -140,9 +135,7 @@ public final class BinderServerBuilder
return this; return this;
} }
/** /** Always fails. TLS is not supported in BinderServer. */
* Always fails. TLS is not supported in BinderServer.
*/
@Override @Override
public BinderServerBuilder useTransportSecurity(File certChain, File privateKey) { public BinderServerBuilder useTransportSecurity(File certChain, File privateKey) {
throw new UnsupportedOperationException("TLS not supported in BinderServer"); throw new UnsupportedOperationException("TLS not supported in BinderServer");

View File

@ -50,8 +50,6 @@ public final class ParcelableUtils {
*/ */
public static <P extends Parcelable> Metadata.Key<P> metadataKeyForImmutableType( public static <P extends Parcelable> Metadata.Key<P> metadataKeyForImmutableType(
String name, Parcelable.Creator<P> creator) { String name, Parcelable.Creator<P> creator) {
return Metadata.Key.of( return Metadata.Key.of(name, new MetadataHelper.ParcelableMetadataMarshaller<P>(creator, true));
name, new MetadataHelper.ParcelableMetadataMarshaller<P>(creator, true));
} }
} }

View File

@ -83,8 +83,8 @@ public final class SecurityPolicies {
} }
/** /**
* Creates a {@link SecurityPolicy} which checks if the package signature * Creates a {@link SecurityPolicy} which checks if the package signature matches {@code
* matches {@code requiredSignature}. * requiredSignature}.
* *
* @param packageName the package name of the allowed package. * @param packageName the package name of the allowed package.
* @param requiredSignature the allowed signature of the allowed package. * @param requiredSignature the allowed signature of the allowed package.
@ -93,8 +93,7 @@ public final class SecurityPolicies {
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022") @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public static SecurityPolicy hasSignature( public static SecurityPolicy hasSignature(
PackageManager packageManager, String packageName, Signature requiredSignature) { PackageManager packageManager, String packageName, Signature requiredSignature) {
return oneOfSignatures( return oneOfSignatures(packageManager, packageName, ImmutableList.of(requiredSignature));
packageManager, packageName, ImmutableList.of(requiredSignature));
} }
/** /**
@ -114,8 +113,8 @@ public final class SecurityPolicies {
} }
/** /**
* Creates a {@link SecurityPolicy} which checks if the package signature * Creates a {@link SecurityPolicy} which checks if the package signature matches any of {@code
* matches any of {@code requiredSignatures}. * requiredSignatures}.
* *
* @param packageName the package name of the allowed package. * @param packageName the package name of the allowed package.
* @param requiredSignatures the allowed signatures of the allowed package. * @param requiredSignatures the allowed signatures of the allowed package.
@ -124,14 +123,11 @@ public final class SecurityPolicies {
*/ */
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022") @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public static SecurityPolicy oneOfSignatures( public static SecurityPolicy oneOfSignatures(
PackageManager packageManager, PackageManager packageManager, String packageName, Collection<Signature> requiredSignatures) {
String packageName,
Collection<Signature> requiredSignatures) {
Preconditions.checkNotNull(packageManager, "packageManager"); Preconditions.checkNotNull(packageManager, "packageManager");
Preconditions.checkNotNull(packageName, "packageName"); Preconditions.checkNotNull(packageName, "packageName");
Preconditions.checkNotNull(requiredSignatures, "requiredSignatures"); Preconditions.checkNotNull(requiredSignatures, "requiredSignatures");
Preconditions.checkArgument(!requiredSignatures.isEmpty(), Preconditions.checkArgument(!requiredSignatures.isEmpty(), "requiredSignatures");
"requiredSignatures");
ImmutableList<Signature> requiredSignaturesImmutable = ImmutableList.copyOf(requiredSignatures); ImmutableList<Signature> requiredSignaturesImmutable = ImmutableList.copyOf(requiredSignatures);
for (Signature requiredSignature : requiredSignaturesImmutable) { for (Signature requiredSignature : requiredSignaturesImmutable) {
@ -141,8 +137,7 @@ public final class SecurityPolicies {
return new SecurityPolicy() { return new SecurityPolicy() {
@Override @Override
public Status checkAuthorization(int uid) { public Status checkAuthorization(int uid) {
return checkUidSignature( return checkUidSignature(packageManager, uid, packageName, requiredSignaturesImmutable);
packageManager, uid, packageName, requiredSignaturesImmutable);
} }
}; };
} }
@ -186,22 +181,23 @@ public final class SecurityPolicies {
} }
/** /**
* Creates {@link SecurityPolicy} which checks if the app is a device owner app. See * Creates {@link SecurityPolicy} which checks if the app is a device owner app. See {@link
* {@link DevicePolicyManager}. * DevicePolicyManager}.
*/ */
@RequiresApi(18) @RequiresApi(18)
public static io.grpc.binder.SecurityPolicy isDeviceOwner(Context applicationContext) { public static io.grpc.binder.SecurityPolicy isDeviceOwner(Context applicationContext) {
DevicePolicyManager devicePolicyManager = DevicePolicyManager devicePolicyManager =
(DevicePolicyManager) applicationContext.getSystemService(Context.DEVICE_POLICY_SERVICE); (DevicePolicyManager) applicationContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
return anyPackageWithUidSatisfies( return anyPackageWithUidSatisfies(
applicationContext, pkg -> devicePolicyManager.isDeviceOwnerApp(pkg), applicationContext,
pkg -> devicePolicyManager.isDeviceOwnerApp(pkg),
"Rejected by device owner policy. No packages found for UID.", "Rejected by device owner policy. No packages found for UID.",
"Rejected by device owner policy"); "Rejected by device owner policy");
} }
/** /**
* Creates {@link SecurityPolicy} which checks if the app is a profile owner app. See * Creates {@link SecurityPolicy} which checks if the app is a profile owner app. See {@link
* {@link DevicePolicyManager}. * DevicePolicyManager}.
*/ */
@RequiresApi(21) @RequiresApi(21)
public static SecurityPolicy isProfileOwner(Context applicationContext) { public static SecurityPolicy isProfileOwner(Context applicationContext) {
@ -223,9 +219,10 @@ public final class SecurityPolicies {
(DevicePolicyManager) applicationContext.getSystemService(Context.DEVICE_POLICY_SERVICE); (DevicePolicyManager) applicationContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
return anyPackageWithUidSatisfies( return anyPackageWithUidSatisfies(
applicationContext, applicationContext,
pkg -> VERSION.SDK_INT >= 30 pkg ->
&& devicePolicyManager.isProfileOwnerApp(pkg) VERSION.SDK_INT >= 30
&& devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile(), && devicePolicyManager.isProfileOwnerApp(pkg)
&& devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile(),
"Rejected by profile owner on organization-owned device policy. No packages found for UID.", "Rejected by profile owner on organization-owned device policy. No packages found for UID.",
"Rejected by profile owner on organization-owned device policy"); "Rejected by profile owner on organization-owned device policy");
} }
@ -237,8 +234,7 @@ public final class SecurityPolicies {
ImmutableList<Signature> requiredSignatures) { ImmutableList<Signature> requiredSignatures) {
String[] packages = packageManager.getPackagesForUid(uid); String[] packages = packageManager.getPackagesForUid(uid);
if (packages == null) { if (packages == null) {
return Status.UNAUTHENTICATED.withDescription( return Status.UNAUTHENTICATED.withDescription("Rejected by signature check security policy");
"Rejected by signature check security policy");
} }
boolean packageNameMatched = false; boolean packageNameMatched = false;
for (String pkg : packages) { for (String pkg : packages) {
@ -251,8 +247,7 @@ public final class SecurityPolicies {
} }
} }
return Status.PERMISSION_DENIED.withDescription( return Status.PERMISSION_DENIED.withDescription(
"Rejected by signature check security policy. Package name matched: " "Rejected by signature check security policy. Package name matched: " + packageNameMatched);
+ packageNameMatched);
} }
private static Status checkUidSha256Signature( private static Status checkUidSha256Signature(
@ -289,9 +284,8 @@ public final class SecurityPolicies {
* *
* @param packageName the package to be checked * @param packageName the package to be checked
* @param signatureCheckFunction {@link Predicate} that takes a signature and verifies if it * @param signatureCheckFunction {@link Predicate} that takes a signature and verifies if it
* satisfies any signature constraints * satisfies any signature constraints return {@code true} if {@code packageName} has a
* return {@code true} if {@code packageName} has a signature that satisfies {@code * signature that satisfies {@code signatureCheckFunction}.
* signatureCheckFunction}.
*/ */
@SuppressWarnings("deprecation") // For PackageInfo.signatures @SuppressWarnings("deprecation") // For PackageInfo.signatures
@SuppressLint("PackageManagerGetSignatures") // We only allow 1 signature. @SuppressLint("PackageManagerGetSignatures") // We only allow 1 signature.
@ -426,13 +420,13 @@ public final class SecurityPolicies {
* *
* <p>The gRPC framework assumes that a {@link SecurityPolicy}'s verdict for a given peer UID will * <p>The gRPC framework assumes that a {@link SecurityPolicy}'s verdict for a given peer UID will
* not change over the lifetime of any process with that UID. But Android runtime permissions can * not change over the lifetime of any process with that UID. But Android runtime permissions can
* be granted or revoked by the user at any time and so using the {@link #hasPermissions} * be granted or revoked by the user at any time and so using the {@link #hasPermissions} {@link
* {@link SecurityPolicy} comes with certain special responsibilities. * SecurityPolicy} comes with certain special responsibilities.
* *
* <p>In particular, callers must ensure that the *subjects* of the returned * <p>In particular, callers must ensure that the *subjects* of the returned {@link
* {@link SecurityPolicy} hold all required {@code permissions} *before* making use of it. Android * SecurityPolicy} hold all required {@code permissions} *before* making use of it. Android kills
* kills an app's processes when it loses any permission but the same isn't true when a permission * an app's processes when it loses any permission but the same isn't true when a permission is
* is granted. And so without special care, a {@link #hasPermissions} denial could incorrectly * granted. And so without special care, a {@link #hasPermissions} denial could incorrectly
* persist even if the subject is later granted all required {@code permissions}. * persist even if the subject is later granted all required {@code permissions}.
* *
* <p>A server using {@link #hasPermissions} must, as part of its RPC API contract, require * <p>A server using {@link #hasPermissions} must, as part of its RPC API contract, require

View File

@ -22,10 +22,10 @@ import javax.annotation.CheckReturnValue;
/** /**
* Decides whether a given Android UID is authorized to access some resource. * Decides whether a given Android UID is authorized to access some resource.
* *
* While it's possible to extend this class to define your own policy, it's strongly * <p>While it's possible to extend this class to define your own policy, it's strongly recommended
* recommended that you only use the policies provided by the {@link SecurityPolicies} or * that you only use the policies provided by the {@link SecurityPolicies} or {@link
* {@link UntrustedSecurityPolicies} classes. Implementing your own security policy requires * UntrustedSecurityPolicies} classes. Implementing your own security policy requires significant
* significant care, and an understanding of the details and pitfalls of Android security. * care, and an understanding of the details and pitfalls of Android security.
* *
* <p><b>IMPORTANT</b> For any concrete extensions of this class, it's assumed that the * <p><b>IMPORTANT</b> For any concrete extensions of this class, it's assumed that the
* authorization status of a given UID will <b>not</b> change as long as a process with that UID is * authorization status of a given UID will <b>not</b> change as long as a process with that UID is

View File

@ -27,7 +27,7 @@ import javax.annotation.CheckReturnValue;
/** /**
* A security policy for a gRPC server. * A security policy for a gRPC server.
* *
* Contains a default policy, and optional policies for each server. * <p>Contains a default policy, and optional policies for each server.
*/ */
public final class ServerSecurityPolicy { public final class ServerSecurityPolicy {
@ -61,8 +61,8 @@ public final class ServerSecurityPolicy {
/** /**
* Returns whether the given Android UID is authorized to access a particular service. * Returns whether the given Android UID is authorized to access a particular service.
* *
* <p>This method never throws an exception. If the execution of the security policy check * <p>This method never throws an exception. If the execution of the security policy check fails,
* fails, a failed future with such exception is returned. * a failed future with such exception is returned.
* *
* @param uid The Android UID to authenticate. * @param uid The Android UID to authenticate.
* @param serviceName The name of the gRPC service being called. * @param serviceName The name of the gRPC service being called.

View File

@ -20,9 +20,7 @@ import io.grpc.ExperimentalApi;
import io.grpc.Status; import io.grpc.Status;
import javax.annotation.CheckReturnValue; import javax.annotation.CheckReturnValue;
/** /** Static factory methods for creating untrusted security policies. */
* Static factory methods for creating untrusted security policies.
*/
@CheckReturnValue @CheckReturnValue
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022") @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public final class UntrustedSecurityPolicies { public final class UntrustedSecurityPolicies {
@ -30,11 +28,9 @@ public final class UntrustedSecurityPolicies {
private UntrustedSecurityPolicies() {} private UntrustedSecurityPolicies() {}
/** /**
* Return a security policy which allows any peer on device. * Return a security policy which allows any peer on device. Servers should only use this policy
* Servers should only use this policy if they intend to expose * if they intend to expose a service to all applications on device. Clients should only use this
* a service to all applications on device. * policy if they don't need to trust the application they're connecting to.
* Clients should only use this policy if they don't need to trust the
* application they're connecting to.
*/ */
public static SecurityPolicy untrustedPublic() { public static SecurityPolicy untrustedPublic() {
return new SecurityPolicy() { return new SecurityPolicy() {

View File

@ -41,9 +41,7 @@ import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import javax.annotation.Nullable; import javax.annotation.Nullable;
/** /** Creates new binder transports. */
* Creates new binder transports.
*/
@Internal @Internal
public final class BinderClientTransportFactory implements ClientTransportFactory { public final class BinderClientTransportFactory implements ClientTransportFactory {
final Context sourceContext; final Context sourceContext;
@ -52,8 +50,7 @@ public final class BinderClientTransportFactory implements ClientTransportFactor
final ObjectPool<ScheduledExecutorService> scheduledExecutorPool; final ObjectPool<ScheduledExecutorService> scheduledExecutorPool;
final ObjectPool<? extends Executor> offloadExecutorPool; final ObjectPool<? extends Executor> offloadExecutorPool;
final SecurityPolicy securityPolicy; final SecurityPolicy securityPolicy;
@Nullable @Nullable final UserHandle targetUserHandle;
final UserHandle targetUserHandle;
final BindServiceFlags bindServiceFlags; final BindServiceFlags bindServiceFlags;
final InboundParcelablePolicy inboundParcelablePolicy; final InboundParcelablePolicy inboundParcelablePolicy;
final OneWayBinderProxy.Decorator binderDecorator; final OneWayBinderProxy.Decorator binderDecorator;
@ -66,8 +63,10 @@ public final class BinderClientTransportFactory implements ClientTransportFactor
private BinderClientTransportFactory(Builder builder) { private BinderClientTransportFactory(Builder builder) {
sourceContext = checkNotNull(builder.sourceContext); sourceContext = checkNotNull(builder.sourceContext);
channelCredentials = checkNotNull(builder.channelCredentials); channelCredentials = checkNotNull(builder.channelCredentials);
mainThreadExecutor = builder.mainThreadExecutor != null ? mainThreadExecutor =
builder.mainThreadExecutor : ContextCompat.getMainExecutor(sourceContext); builder.mainThreadExecutor != null
? builder.mainThreadExecutor
: ContextCompat.getMainExecutor(sourceContext);
scheduledExecutorPool = checkNotNull(builder.scheduledExecutorPool); scheduledExecutorPool = checkNotNull(builder.scheduledExecutorPool);
offloadExecutorPool = checkNotNull(builder.offloadExecutorPool); offloadExecutorPool = checkNotNull(builder.offloadExecutorPool);
securityPolicy = checkNotNull(builder.securityPolicy); securityPolicy = checkNotNull(builder.securityPolicy);
@ -112,9 +111,7 @@ public final class BinderClientTransportFactory implements ClientTransportFactor
return Collections.singleton(AndroidComponentAddress.class); return Collections.singleton(AndroidComponentAddress.class);
} }
/** /** Allows fluent construction of ClientTransportFactory. */
* Allows fluent construction of ClientTransportFactory.
*/
public static final class Builder implements ClientTransportFactoryBuilder { public static final class Builder implements ClientTransportFactoryBuilder {
// Required. // Required.
Context sourceContext; Context sourceContext;
@ -122,16 +119,15 @@ public final class BinderClientTransportFactory implements ClientTransportFactor
// Optional. // Optional.
BinderChannelCredentials channelCredentials = BinderChannelCredentials.forDefault(); BinderChannelCredentials channelCredentials = BinderChannelCredentials.forDefault();
Executor mainThreadExecutor; // Default filled-in at build time once sourceContext is decided. Executor mainThreadExecutor; // Default filled-in at build time once sourceContext is decided.
ObjectPool<ScheduledExecutorService> scheduledExecutorPool = ObjectPool<ScheduledExecutorService> scheduledExecutorPool =
SharedResourcePool.forResource(GrpcUtil.TIMER_SERVICE); SharedResourcePool.forResource(GrpcUtil.TIMER_SERVICE);
SecurityPolicy securityPolicy = SecurityPolicies.internalOnly(); SecurityPolicy securityPolicy = SecurityPolicies.internalOnly();
@Nullable @Nullable UserHandle targetUserHandle;
UserHandle targetUserHandle;
BindServiceFlags bindServiceFlags = BindServiceFlags.DEFAULTS; BindServiceFlags bindServiceFlags = BindServiceFlags.DEFAULTS;
InboundParcelablePolicy inboundParcelablePolicy = InboundParcelablePolicy.DEFAULT; InboundParcelablePolicy inboundParcelablePolicy = InboundParcelablePolicy.DEFAULT;
OneWayBinderProxy.Decorator binderDecorator = OneWayBinderProxy.IDENTITY_DECORATOR; OneWayBinderProxy.Decorator binderDecorator = OneWayBinderProxy.IDENTITY_DECORATOR;
long readyTimeoutMillis = -1; // TODO(jdcormie) Set an non-infinite default in a separate PR. long readyTimeoutMillis = -1; // TODO(jdcormie) Set an non-infinite default in a separate PR.
@Override @Override
public BinderClientTransportFactory buildClientTransportFactory() { public BinderClientTransportFactory buildClientTransportFactory() {
@ -143,8 +139,7 @@ public final class BinderClientTransportFactory implements ClientTransportFactor
return this; return this;
} }
public Builder setOffloadExecutorPool( public Builder setOffloadExecutorPool(ObjectPool<? extends Executor> offloadExecutorPool) {
ObjectPool<? extends Executor> offloadExecutorPool) {
this.offloadExecutorPool = checkNotNull(offloadExecutorPool, "offloadExecutorPool"); this.offloadExecutorPool = checkNotNull(offloadExecutorPool, "offloadExecutorPool");
return this; return this;
} }
@ -181,7 +176,8 @@ public final class BinderClientTransportFactory implements ClientTransportFactor
} }
public Builder setInboundParcelablePolicy(InboundParcelablePolicy inboundParcelablePolicy) { public Builder setInboundParcelablePolicy(InboundParcelablePolicy inboundParcelablePolicy) {
this.inboundParcelablePolicy = checkNotNull(inboundParcelablePolicy, "inboundParcelablePolicy"); this.inboundParcelablePolicy =
checkNotNull(inboundParcelablePolicy, "inboundParcelablePolicy");
return this; return this;
} }
@ -199,20 +195,20 @@ public final class BinderClientTransportFactory implements ClientTransportFactor
* Limits how long it can take to for a new transport to become ready after being started. * Limits how long it can take to for a new transport to become ready after being started.
* *
* <p>This process currently includes: * <p>This process currently includes:
*
* <ul> * <ul>
* <li>Creating an Android binding. * <li>Creating an Android binding.
* <li>Waiting for Android to create the server process. * <li>Waiting for Android to create the server process.
* <li>Waiting for the remote Service to be created and handle onBind(). * <li>Waiting for the remote Service to be created and handle onBind().
* <li>Exchanging handshake transactions according to the wire protocol. * <li>Exchanging handshake transactions according to the wire protocol.
* <li>Evaluating a {@link SecurityPolicy} on both sides. * <li>Evaluating a {@link SecurityPolicy} on both sides.
* </ul> * </ul>
* *
* <p>This setting doesn't change the need for deadlines at the call level. It merely ensures * <p>This setting doesn't change the need for deadlines at the call level. It merely ensures
* that gRPC features like * that gRPC features like <a
* <a href="https://github.com/grpc/grpc/blob/master/doc/load-balancing.md">load balancing</a> * href="https://github.com/grpc/grpc/blob/master/doc/load-balancing.md">load balancing</a> and
* and <a href="https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md">fail-fast</a> * <a href="https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md">fail-fast</a> work
* work as expected despite certain edge cases that could otherwise stall the transport * as expected despite certain edge cases that could otherwise stall the transport indefinitely.
* indefinitely.
* *
* <p>Optional. Use a negative value to wait indefinitely. * <p>Optional. Use a negative value to wait indefinitely.
*/ */

View File

@ -56,7 +56,7 @@ import javax.annotation.concurrent.ThreadSafe;
* *
* <p>Multiple incoming connections transports may be active at a time. * <p>Multiple incoming connections transports may be active at a time.
* *
* <b>IMPORTANT</b>: This implementation must comply with this published wire format. * <p><b>IMPORTANT</b>: This implementation must comply with this published wire format.
* https://github.com/grpc/proposal/blob/master/L73-java-binderchannel/wireformat.md * https://github.com/grpc/proposal/blob/master/L73-java-binderchannel/wireformat.md
*/ */
@ThreadSafe @ThreadSafe
@ -180,7 +180,9 @@ public final class BinderServer implements InternalServer, LeakSafeOneWayBinder.
// Create a new transport and let our listener know about it. // Create a new transport and let our listener know about it.
BinderTransport.BinderServerTransport transport = BinderTransport.BinderServerTransport transport =
new BinderTransport.BinderServerTransport( new BinderTransport.BinderServerTransport(
executorServicePool, attrsBuilder.build(), streamTracerFactories, executorServicePool,
attrsBuilder.build(),
streamTracerFactories,
OneWayBinderProxy.IDENTITY_DECORATOR, OneWayBinderProxy.IDENTITY_DECORATOR,
callbackBinder); callbackBinder);
transport.setServerTransportListener(listener.transportCreated(transport)); transport.setServerTransportListener(listener.transportCreated(transport));
@ -246,7 +248,8 @@ public final class BinderServer implements InternalServer, LeakSafeOneWayBinder.
* *
* <p>Required. * <p>Required.
*/ */
public Builder setStreamTracerFactories(List<? extends ServerStreamTracer.Factory> streamTracerFactories) { public Builder setStreamTracerFactories(
List<? extends ServerStreamTracer.Factory> streamTracerFactories) {
this.streamTracerFactories = streamTracerFactories; this.streamTracerFactories = streamTracerFactories;
return this; return this;
} }
@ -275,7 +278,7 @@ public final class BinderServer implements InternalServer, LeakSafeOneWayBinder.
/** /**
* Sets the {@link ServerSecurityPolicy} to be used for built servers. * Sets the {@link ServerSecurityPolicy} to be used for built servers.
* *
* Optional, {@link SecurityPolicies#serverInternalOnly()} is the default. * <p>Optional, {@link SecurityPolicies#serverInternalOnly()} is the default.
*/ */
public Builder setServerSecurityPolicy(ServerSecurityPolicy serverSecurityPolicy) { public Builder setServerSecurityPolicy(ServerSecurityPolicy serverSecurityPolicy) {
this.serverSecurityPolicy = checkNotNull(serverSecurityPolicy, "serverSecurityPolicy"); this.serverSecurityPolicy = checkNotNull(serverSecurityPolicy, "serverSecurityPolicy");
@ -285,10 +288,11 @@ public final class BinderServer implements InternalServer, LeakSafeOneWayBinder.
/** /**
* Sets the {@link InboundParcelablePolicy} to be used for built servers. * Sets the {@link InboundParcelablePolicy} to be used for built servers.
* *
* Optional, {@link InboundParcelablePolicy#DEFAULT} is the default. * <p>Optional, {@link InboundParcelablePolicy#DEFAULT} is the default.
*/ */
public Builder setInboundParcelablePolicy(InboundParcelablePolicy inboundParcelablePolicy) { public Builder setInboundParcelablePolicy(InboundParcelablePolicy inboundParcelablePolicy) {
this.inboundParcelablePolicy = checkNotNull(inboundParcelablePolicy, "inboundParcelablePolicy"); this.inboundParcelablePolicy =
checkNotNull(inboundParcelablePolicy, "inboundParcelablePolicy");
return this; return this;
} }
} }

View File

@ -134,12 +134,10 @@ public abstract class BinderTransport
* <p>Should this change, we should still endeavor to support earlier wire-format versions. If * <p>Should this change, we should still endeavor to support earlier wire-format versions. If
* that's not possible, {@link EARLIEST_SUPPORTED_WIRE_FORMAT_VERSION} should be updated below. * that's not possible, {@link EARLIEST_SUPPORTED_WIRE_FORMAT_VERSION} should be updated below.
*/ */
@Internal @Internal public static final int WIRE_FORMAT_VERSION = 1;
public static final int WIRE_FORMAT_VERSION = 1;
/** The version code of the earliest wire format we support. */ /** The version code of the earliest wire format we support. */
@Internal @Internal public static final int EARLIEST_SUPPORTED_WIRE_FORMAT_VERSION = 1;
public static final int EARLIEST_SUPPORTED_WIRE_FORMAT_VERSION = 1;
/** The max number of "in-flight" bytes before we start buffering transactions. */ /** The max number of "in-flight" bytes before we start buffering transactions. */
private static final int TRANSACTION_BYTES_WINDOW = 128 * 1024; private static final int TRANSACTION_BYTES_WINDOW = 128 * 1024;
@ -152,12 +150,10 @@ public abstract class BinderTransport
* the binder. and from the host s Followed by: int wire_protocol_version IBinder * the binder. and from the host s Followed by: int wire_protocol_version IBinder
* client_transports_callback_binder * client_transports_callback_binder
*/ */
@Internal @Internal public static final int SETUP_TRANSPORT = IBinder.FIRST_CALL_TRANSACTION;
public static final int SETUP_TRANSPORT = IBinder.FIRST_CALL_TRANSACTION;
/** Send to shutdown the transport from either end. */ /** Send to shutdown the transport from either end. */
@Internal @Internal public static final int SHUTDOWN_TRANSPORT = IBinder.FIRST_CALL_TRANSACTION + 1;
public static final int SHUTDOWN_TRANSPORT = IBinder.FIRST_CALL_TRANSACTION + 1;
/** Send to acknowledge receipt of rpc bytes, for flow control. */ /** Send to acknowledge receipt of rpc bytes, for flow control. */
static final int ACKNOWLEDGE_BYTES = IBinder.FIRST_CALL_TRANSACTION + 2; static final int ACKNOWLEDGE_BYTES = IBinder.FIRST_CALL_TRANSACTION + 2;
@ -432,8 +428,8 @@ public abstract class BinderTransport
try { try {
return handleTransactionInternal(code, parcel); return handleTransactionInternal(code, parcel);
} catch (RuntimeException e) { } catch (RuntimeException e) {
logger.log(Level.SEVERE, logger.log(
"Terminating transport for uncaught Exception in transaction " + code, e); Level.SEVERE, "Terminating transport for uncaught Exception in transaction " + code, e);
synchronized (this) { synchronized (this) {
// This unhandled exception may have put us in an inconsistent state. Force terminate the // This unhandled exception may have put us in an inconsistent state. Force terminate the
// whole transport so our peer knows something is wrong and so that clients can retry with // whole transport so our peer knows something is wrong and so that clients can retry with
@ -567,8 +563,10 @@ public abstract class BinderTransport
private final Executor offloadExecutor; private final Executor offloadExecutor;
private final SecurityPolicy securityPolicy; private final SecurityPolicy securityPolicy;
private final Bindable serviceBinding; private final Bindable serviceBinding;
/** Number of ongoing calls which keep this transport "in-use". */ /** Number of ongoing calls which keep this transport "in-use". */
private final AtomicInteger numInUseStreams; private final AtomicInteger numInUseStreams;
private final long readyTimeoutMillis; private final long readyTimeoutMillis;
private final PingTracker pingTracker; private final PingTracker pingTracker;
@ -576,6 +574,7 @@ public abstract class BinderTransport
@GuardedBy("this") @GuardedBy("this")
private int latestCallId = FIRST_CALL_ID; private int latestCallId = FIRST_CALL_ID;
@GuardedBy("this") @GuardedBy("this")
private ScheduledFuture<?> readyTimeoutFuture; // != null iff timeout scheduled. private ScheduledFuture<?> readyTimeoutFuture; // != null iff timeout scheduled.
@ -592,8 +591,11 @@ public abstract class BinderTransport
ClientTransportOptions options) { ClientTransportOptions options) {
super( super(
factory.scheduledExecutorPool, factory.scheduledExecutorPool,
buildClientAttributes(options.getEagAttributes(), buildClientAttributes(
factory.sourceContext, targetAddress, factory.inboundParcelablePolicy), options.getEagAttributes(),
factory.sourceContext,
targetAddress,
factory.inboundParcelablePolicy),
factory.binderDecorator, factory.binderDecorator,
buildLogId(factory.sourceContext, targetAddress)); buildLogId(factory.sourceContext, targetAddress));
this.offloadExecutorPool = factory.offloadExecutorPool; this.offloadExecutorPool = factory.offloadExecutorPool;
@ -622,7 +624,8 @@ public abstract class BinderTransport
@Override @Override
public synchronized void onBound(IBinder binder) { public synchronized void onBound(IBinder binder) {
sendSetupTransaction(binderDecorator.decorate(OneWayBinderProxy.wrap(binder, offloadExecutor))); sendSetupTransaction(
binderDecorator.decorate(OneWayBinderProxy.wrap(binder, offloadExecutor)));
} }
@Override @Override
@ -640,8 +643,12 @@ public abstract class BinderTransport
setState(TransportState.SETUP); setState(TransportState.SETUP);
serviceBinding.bind(); serviceBinding.bind();
if (readyTimeoutMillis >= 0) { if (readyTimeoutMillis >= 0) {
readyTimeoutFuture = getScheduledExecutorService().schedule( readyTimeoutFuture =
BinderClientTransport.this::onReadyTimeout, readyTimeoutMillis, MILLISECONDS); getScheduledExecutorService()
.schedule(
BinderClientTransport.this::onReadyTimeout,
readyTimeoutMillis,
MILLISECONDS);
} }
} }
} }
@ -651,8 +658,9 @@ public abstract class BinderTransport
private synchronized void onReadyTimeout() { private synchronized void onReadyTimeout() {
if (inState(TransportState.SETUP)) { if (inState(TransportState.SETUP)) {
readyTimeoutFuture = null; readyTimeoutFuture = null;
shutdownInternal(Status.DEADLINE_EXCEEDED shutdownInternal(
.withDescription("Connect timeout " + readyTimeoutMillis + "ms lapsed"), Status.DEADLINE_EXCEEDED.withDescription(
"Connect timeout " + readyTimeoutMillis + "ms lapsed"),
true); true);
} }
} }
@ -760,17 +768,23 @@ public abstract class BinderTransport
shutdownInternal( shutdownInternal(
Status.UNAVAILABLE.withDescription("Malformed SETUP_TRANSPORT data"), true); Status.UNAVAILABLE.withDescription("Malformed SETUP_TRANSPORT data"), true);
} else { } else {
ListenableFuture<Status> authFuture = (securityPolicy instanceof AsyncSecurityPolicy) ? ListenableFuture<Status> authFuture =
((AsyncSecurityPolicy) securityPolicy).checkAuthorizationAsync(remoteUid) : (securityPolicy instanceof AsyncSecurityPolicy)
Futures.submit(() -> securityPolicy.checkAuthorization(remoteUid), offloadExecutor); ? ((AsyncSecurityPolicy) securityPolicy).checkAuthorizationAsync(remoteUid)
: Futures.submit(
() -> securityPolicy.checkAuthorization(remoteUid), offloadExecutor);
Futures.addCallback( Futures.addCallback(
authFuture, authFuture,
new FutureCallback<Status>() { new FutureCallback<Status>() {
@Override @Override
public void onSuccess(Status result) { handleAuthResult(binder, result); } public void onSuccess(Status result) {
handleAuthResult(binder, result);
}
@Override @Override
public void onFailure(Throwable t) { handleAuthResult(t); } public void onFailure(Throwable t) {
handleAuthResult(t);
}
}, },
offloadExecutor); offloadExecutor);
} }
@ -802,10 +816,7 @@ public abstract class BinderTransport
private synchronized void handleAuthResult(Throwable t) { private synchronized void handleAuthResult(Throwable t) {
shutdownInternal( shutdownInternal(
Status.INTERNAL Status.INTERNAL.withDescription("Could not evaluate SecurityPolicy").withCause(t), true);
.withDescription("Could not evaluate SecurityPolicy")
.withCause(t),
true);
} }
@GuardedBy("this") @GuardedBy("this")
@ -815,8 +826,7 @@ public abstract class BinderTransport
} }
private static ClientStream newFailingClientStream( private static ClientStream newFailingClientStream(
Status failure, Attributes attributes, Metadata headers, Status failure, Attributes attributes, Metadata headers, ClientStreamTracer[] tracers) {
ClientStreamTracer[] tracers) {
StatsTraceContext statsTraceContext = StatsTraceContext statsTraceContext =
StatsTraceContext.newClientContext(tracers, attributes, headers); StatsTraceContext.newClientContext(tracers, attributes, headers);
statsTraceContext.clientOutboundHeaders(); statsTraceContext.clientOutboundHeaders();
@ -858,7 +868,8 @@ public abstract class BinderTransport
/** Concrete server-side transport implementation. */ /** Concrete server-side transport implementation. */
@Internal @Internal
public static final class BinderServerTransport extends BinderTransport implements ServerTransport { public static final class BinderServerTransport extends BinderTransport
implements ServerTransport {
private final List<ServerStreamTracer.Factory> streamTracerFactories; private final List<ServerStreamTracer.Factory> streamTracerFactories;
@Nullable private ServerTransportListener serverTransportListener; @Nullable private ServerTransportListener serverTransportListener;
@ -880,7 +891,8 @@ public abstract class BinderTransport
setOutgoingBinder(OneWayBinderProxy.wrap(callbackBinder, getScheduledExecutorService())); setOutgoingBinder(OneWayBinderProxy.wrap(callbackBinder, getScheduledExecutorService()));
} }
public synchronized void setServerTransportListener(ServerTransportListener serverTransportListener) { public synchronized void setServerTransportListener(
ServerTransportListener serverTransportListener) {
this.serverTransportListener = serverTransportListener; this.serverTransportListener = serverTransportListener;
if (isShutdown()) { if (isShutdown()) {
setState(TransportState.SHUTDOWN_TERMINATED); setState(TransportState.SHUTDOWN_TERMINATED);
@ -983,4 +995,3 @@ public abstract class BinderTransport
return Status.INTERNAL.withCause(e); return Status.INTERNAL.withCause(e);
} }
} }

View File

@ -41,8 +41,8 @@ import javax.annotation.Nullable;
/** /**
* Manages security for an Android Service hosted gRPC server. * Manages security for an Android Service hosted gRPC server.
* *
* <p>Attaches authorization state to a newly-created transport, and contains a * <p>Attaches authorization state to a newly-created transport, and contains a ServerInterceptor
* ServerInterceptor which ensures calls are authorized before allowing them to proceed. * which ensures calls are authorized before allowing them to proceed.
*/ */
public final class BinderTransportSecurity { public final class BinderTransportSecurity {
@ -205,15 +205,18 @@ public final class BinderTransportSecurity {
serverPolicyChecker.checkAuthorizationForServiceAsync(uid, serviceName); serverPolicyChecker.checkAuthorizationForServiceAsync(uid, serviceName);
if (useCache) { if (useCache) {
serviceAuthorization.putIfAbsent(serviceName, authorization); serviceAuthorization.putIfAbsent(serviceName, authorization);
Futures.addCallback(authorization, new FutureCallback<Status>() { Futures.addCallback(
@Override authorization,
public void onSuccess(Status result) {} new FutureCallback<Status>() {
@Override
public void onSuccess(Status result) {}
@Override @Override
public void onFailure(Throwable t) { public void onFailure(Throwable t) {
serviceAuthorization.remove(serviceName, authorization); serviceAuthorization.remove(serviceName, authorization);
} }
}, MoreExecutors.directExecutor()); },
MoreExecutors.directExecutor());
} }
return authorization; return authorization;
} }
@ -238,7 +241,7 @@ public final class BinderTransportSecurity {
* @param uid The Android UID to authenticate. * @param uid The Android UID to authenticate.
* @param serviceName The name of the gRPC service being called. * @param serviceName The name of the gRPC service being called.
* @return a future with the result of the authorization check. A failed future represents a * @return a future with the result of the authorization check. A failed future represents a
* failure to perform the authorization check, not that the access is denied. * failure to perform the authorization check, not that the access is denied.
*/ */
ListenableFuture<Status> checkAuthorizationForServiceAsync(int uid, String serviceName); ListenableFuture<Status> checkAuthorizationForServiceAsync(int uid, String serviceName);
} }

View File

@ -28,20 +28,17 @@ import javax.annotation.concurrent.NotThreadSafe;
/** /**
* A simple InputStream from a 2-dimensional byte array. * A simple InputStream from a 2-dimensional byte array.
* *
* Used to provide message data from incoming blocks of data. It is assumed that * <p>Used to provide message data from incoming blocks of data. It is assumed that all byte arrays
* all byte arrays passed in the constructor of this this class are owned by the new * passed in the constructor of this this class are owned by the new instance.
* instance.
* *
* This also assumes byte arrays are created by the BlockPool class, and should * <p>This also assumes byte arrays are created by the BlockPool class, and should be returned to it
* be returned to it when this class is closed. * when this class is closed.
*/ */
@NotThreadSafe @NotThreadSafe
final class BlockInputStream extends InputStream implements KnownLength, Drainable { final class BlockInputStream extends InputStream implements KnownLength, Drainable {
@Nullable @Nullable private byte[][] blocks;
private byte[][] blocks; @Nullable private byte[] currentBlock;
@Nullable
private byte[] currentBlock;
private int blockIndex; private int blockIndex;
private int blockOffset; private int blockOffset;
private int available; private int available;
@ -50,8 +47,7 @@ final class BlockInputStream extends InputStream implements KnownLength, Drainab
/** /**
* Creates a new stream with a single block. * Creates a new stream with a single block.
* *
* @param block The single byte array block, ownership of which is * @param block The single byte array block, ownership of which is passed to this instance.
* passed to this instance.
*/ */
BlockInputStream(byte[] block) { BlockInputStream(byte[] block) {
this.blocks = null; this.blocks = null;
@ -62,10 +58,10 @@ final class BlockInputStream extends InputStream implements KnownLength, Drainab
/** /**
* Creates a new stream from a sequence of blocks. * Creates a new stream from a sequence of blocks.
* *
* @param blocks A two dimensional byte array containing the data. Ownership * @param blocks A two dimensional byte array containing the data. Ownership of all blocks is
* of all blocks is passed to this instance. * passed to this instance.
* @param available The number of bytes available in total. This may be * @param available The number of bytes available in total. This may be less than (but never more
* less than (but never more than) the total size of all byte arrays in blocks. * than) the total size of all byte arrays in blocks.
*/ */
BlockInputStream(byte[][] blocks, int available) { BlockInputStream(byte[][] blocks, int available) {
this.blocks = blocks; this.blocks = blocks;

View File

@ -27,9 +27,8 @@ import java.util.concurrent.LinkedBlockingQueue;
* byte array of size N. This means we can't simply read into a large block and be done with it, we * byte array of size N. This means we can't simply read into a large block and be done with it, we
* need to allocate a new buffer specifically. Boo, Android. * need to allocate a new buffer specifically. Boo, Android.
* *
* <p>When writing data though, we can use a fixed-size buffer, so when large messages are * <p>When writing data though, we can use a fixed-size buffer, so when large messages are split
* split into standard-sized blocks, we only need a byte array allocation to read the last * into standard-sized blocks, we only need a byte array allocation to read the last block.
* block.
* *
* <p>This class maintains a pool of blocks of standard size, but also provides smaller blocks when * <p>This class maintains a pool of blocks of standard size, but also provides smaller blocks when
* requested. Currently, blocks of standard size are retained in the pool, when released, but we * requested. Currently, blocks of standard size are retained in the pool, when released, but we
@ -38,8 +37,8 @@ import java.util.concurrent.LinkedBlockingQueue;
final class BlockPool { final class BlockPool {
/** /**
* The size of each standard block. (Currently 16k) * The size of each standard block. (Currently 16k) The block size must be at least as large as
* The block size must be at least as large as the maximum header list size. * the maximum header list size.
*/ */
private static final int BLOCK_SIZE = Math.max(16 * 1024, GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE); private static final int BLOCK_SIZE = Math.max(16 * 1024, GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE);

View File

@ -344,8 +344,7 @@ abstract class Inbound<L extends StreamListener> implements StreamListener.Messa
} }
int index = parcel.readInt(); int index = parcel.readInt();
boolean hasPrefix = TransactionUtils.hasFlag(flags, TransactionUtils.FLAG_PREFIX); boolean hasPrefix = TransactionUtils.hasFlag(flags, TransactionUtils.FLAG_PREFIX);
boolean hasMessageData = boolean hasMessageData = TransactionUtils.hasFlag(flags, TransactionUtils.FLAG_MESSAGE_DATA);
TransactionUtils.hasFlag(flags, TransactionUtils.FLAG_MESSAGE_DATA);
boolean hasSuffix = TransactionUtils.hasFlag(flags, TransactionUtils.FLAG_SUFFIX); boolean hasSuffix = TransactionUtils.hasFlag(flags, TransactionUtils.FLAG_SUFFIX);
if (hasPrefix) { if (hasPrefix) {
handlePrefix(flags, parcel); handlePrefix(flags, parcel);

View File

@ -71,9 +71,7 @@ public final class LeakSafeOneWayBinder extends Binder {
setHandler(null); setHandler(null);
} }
/** /** Replaces the current {@link TransactionHandler} with `handler`. */
* Replaces the current {@link TransactionHandler} with `handler`.
*/
public void setHandler(@Nullable TransactionHandler handler) { public void setHandler(@Nullable TransactionHandler handler) {
this.handler = handler; this.handler = handler;
} }

View File

@ -50,7 +50,7 @@ public final class MetadataHelper {
/** The generic metadata marshaller we use for reading parcelables from the transport. */ /** The generic metadata marshaller we use for reading parcelables from the transport. */
private static final Metadata.BinaryStreamMarshaller<Parcelable> TRANSPORT_INBOUND_MARSHALLER = private static final Metadata.BinaryStreamMarshaller<Parcelable> TRANSPORT_INBOUND_MARSHALLER =
new ParcelableMetadataMarshaller<>(null, true); new ParcelableMetadataMarshaller<>(null, true);
/** Indicates the following value is a parcelable. */ /** Indicates the following value is a parcelable. */
private static final int PARCELABLE_SENTINEL = -1; private static final int PARCELABLE_SENTINEL = -1;
@ -103,7 +103,9 @@ public final class MetadataHelper {
total += read; total += read;
} }
if (total == buffer.length) { if (total == buffer.length) {
throw Status.RESOURCE_EXHAUSTED.withDescription("Metadata value too large").asException(); throw Status.RESOURCE_EXHAUSTED
.withDescription("Metadata value too large")
.asException();
} }
parcel.writeInt(total); parcel.writeInt(total);
if (total > 0) { if (total > 0) {
@ -182,10 +184,8 @@ public final class MetadataHelper {
} }
/** Read a byte array checking that we're not reading too much. */ /** Read a byte array checking that we're not reading too much. */
private static byte[] readBytesChecked( private static byte[] readBytesChecked(Parcel parcel, int numBytes, int bytesRead)
Parcel parcel, throws StatusException {
int numBytes,
int bytesRead) throws StatusException {
if (bytesRead + numBytes > GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE) { if (bytesRead + numBytes > GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE) {
throw Status.RESOURCE_EXHAUSTED.withDescription("Metadata too large").asException(); throw Status.RESOURCE_EXHAUSTED.withDescription("Metadata too large").asException();
} }
@ -203,7 +203,8 @@ public final class MetadataHelper {
@Nullable private final Parcelable.Creator<P> creator; @Nullable private final Parcelable.Creator<P> creator;
private final boolean immutableType; private final boolean immutableType;
public ParcelableMetadataMarshaller(@Nullable Parcelable.Creator<P> creator, boolean immutableType) { public ParcelableMetadataMarshaller(
@Nullable Parcelable.Creator<P> creator, boolean immutableType) {
this.creator = creator; this.creator = creator;
this.immutableType = immutableType; this.immutableType = immutableType;
} }

View File

@ -71,15 +71,13 @@ public abstract class OneWayBinderProxy {
*/ */
public interface Decorator { public interface Decorator {
/** /**
* Returns an instance of {@link OneWayBinderProxy} that decorates {@code input} with some * Returns an instance of {@link OneWayBinderProxy} that decorates {@code input} with some new
* new behavior. * behavior.
*/ */
OneWayBinderProxy decorate(OneWayBinderProxy input); OneWayBinderProxy decorate(OneWayBinderProxy input);
} }
/** /** A {@link Decorator} that does nothing. */
* A {@link Decorator} that does nothing.
*/
public static final Decorator IDENTITY_DECORATOR = (x) -> x; public static final Decorator IDENTITY_DECORATOR = (x) -> x;
/** /**

View File

@ -4,10 +4,8 @@ import io.grpc.Metadata;
import io.grpc.ServerCall; import io.grpc.ServerCall;
import io.grpc.ServerCallHandler; import io.grpc.ServerCallHandler;
import io.grpc.Status; import io.grpc.Status;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nullable; import javax.annotation.Nullable;
/** /**
@ -23,16 +21,14 @@ final class PendingAuthListener<ReqT, RespT> extends ServerCall.Listener<ReqT> {
PendingAuthListener() {} PendingAuthListener() {}
void startCall(ServerCall<ReqT, RespT> call, void startCall(
Metadata headers, ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
ServerCallHandler<ReqT, RespT> next) {
ServerCall.Listener<ReqT> delegate; ServerCall.Listener<ReqT> delegate;
try { try {
delegate = next.startCall(call, headers); delegate = next.startCall(call, headers);
} catch (RuntimeException e) { } catch (RuntimeException e) {
call.close( call.close(
Status Status.INTERNAL
.INTERNAL
.withCause(e) .withCause(e)
.withDescription("Failed to start server call after authorization check"), .withDescription("Failed to start server call after authorization check"),
new Metadata()); new Metadata());

View File

@ -106,8 +106,7 @@ final class PingTracker {
private synchronized void success() { private synchronized void success() {
if (!done) { if (!done) {
done = true; done = true;
executor.execute( executor.execute(() -> callback.onSuccess(ticker.read() - startTimeNanos));
() -> callback.onSuccess(ticker.read() - startTimeNanos));
} }
} }
} }

View File

@ -147,12 +147,7 @@ final class ServiceBinding implements Bindable, ServiceConnection {
state = State.BINDING; state = State.BINDING;
Status bindResult = Status bindResult =
bindInternal( bindInternal(
sourceContext, sourceContext, bindIntent, this, bindFlags, channelCredentials, targetUserHandle);
bindIntent,
this,
bindFlags,
channelCredentials,
targetUserHandle);
if (!bindResult.isOk()) { if (!bindResult.isOk()) {
handleBindServiceFailure(sourceContext, this); handleBindServiceFailure(sourceContext, this);
state = State.UNBOUND; state = State.UNBOUND;
@ -193,17 +188,18 @@ final class ServiceBinding implements Bindable, ServiceConnection {
case DEVICE_POLICY_BIND_SEVICE_ADMIN: case DEVICE_POLICY_BIND_SEVICE_ADMIN:
DevicePolicyManager devicePolicyManager = DevicePolicyManager devicePolicyManager =
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
bindResult = devicePolicyManager.bindDeviceAdminServiceAsUser( bindResult =
channelCredentials.getDevicePolicyAdminComponentName(), devicePolicyManager.bindDeviceAdminServiceAsUser(
bindIntent, channelCredentials.getDevicePolicyAdminComponentName(),
conn, bindIntent,
flags, conn,
targetUserHandle); flags,
targetUserHandle);
break; break;
} }
if (!bindResult) { if (!bindResult) {
return Status.UNIMPLEMENTED.withDescription( return Status.UNIMPLEMENTED.withDescription(
bindMethodType.methodName() + "(" + bindIntent + ") returned false"); bindMethodType.methodName() + "(" + bindIntent + ") returned false");
} }
return Status.OK; return Status.OK;
} catch (SecurityException e) { } catch (SecurityException e) {
@ -211,8 +207,9 @@ final class ServiceBinding implements Bindable, ServiceConnection {
.withCause(e) .withCause(e)
.withDescription("SecurityException from " + bindMethodType.methodName()); .withDescription("SecurityException from " + bindMethodType.methodName());
} catch (RuntimeException e) { } catch (RuntimeException e) {
return Status.INTERNAL.withCause(e).withDescription( return Status.INTERNAL
"RuntimeException from " + bindMethodType.methodName()); .withCause(e)
.withDescription("RuntimeException from " + bindMethodType.methodName());
} }
} }

View File

@ -25,10 +25,13 @@ import javax.annotation.Nullable;
final class TransactionUtils { final class TransactionUtils {
/** Set when the transaction contains rpc prefix data. */ /** Set when the transaction contains rpc prefix data. */
static final int FLAG_PREFIX = 0x1; static final int FLAG_PREFIX = 0x1;
/** Set when the transaction contains some message data. */ /** Set when the transaction contains some message data. */
static final int FLAG_MESSAGE_DATA = 0x2; static final int FLAG_MESSAGE_DATA = 0x2;
/** Set when the transaction contains rpc suffix data. */ /** Set when the transaction contains rpc suffix data. */
static final int FLAG_SUFFIX = 0x4; static final int FLAG_SUFFIX = 0x4;
/** Set when the transaction is an out-of-band close event. */ /** Set when the transaction is an out-of-band close event. */
static final int FLAG_OUT_OF_BAND_CLOSE = 0x8; static final int FLAG_OUT_OF_BAND_CLOSE = 0x8;

View File

@ -32,8 +32,7 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class) @RunWith(JUnit4.class)
public final class PeerUidTestHelperTest { public final class PeerUidTestHelperTest {
@Rule @Rule public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule();
public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule();
private static final int FAKE_UID = 12345; private static final int FAKE_UID = 12345;

View File

@ -21,11 +21,9 @@ import static com.google.common.truth.Truth.assertThat;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import static org.robolectric.Shadows.shadowOf; import static org.robolectric.Shadows.shadowOf;
import io.grpc.binder.internal.MainThreadScheduledExecutorService;
import android.app.Application; import android.app.Application;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Intent; import android.content.Intent;
import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
import androidx.lifecycle.LifecycleService; import androidx.lifecycle.LifecycleService;
@ -44,6 +42,7 @@ import io.grpc.ServerMethodDefinition;
import io.grpc.ServerServiceDefinition; import io.grpc.ServerServiceDefinition;
import io.grpc.Status; import io.grpc.Status;
import io.grpc.StatusRuntimeException; import io.grpc.StatusRuntimeException;
import io.grpc.binder.internal.MainThreadScheduledExecutorService;
import io.grpc.protobuf.lite.ProtoLiteUtils; import io.grpc.protobuf.lite.ProtoLiteUtils;
import io.grpc.stub.ClientCalls; import io.grpc.stub.ClientCalls;
import io.grpc.stub.ServerCalls; import io.grpc.stub.ServerCalls;
@ -249,8 +248,5 @@ public final class RobolectricBinderSecurityTest {
} }
/** A future representing a task submitted to a {@link Handler}. */ /** A future representing a task submitted to a {@link Handler}. */
} }
} }

View File

@ -107,8 +107,7 @@ public final class SecurityPoliciesTest {
} }
@Test @Test
public void testHasSignature_succeedsIfPackageNameAndSignaturesMatch() public void testHasSignature_succeedsIfPackageNameAndSignaturesMatch() throws Exception {
throws Exception {
PackageInfo info = PackageInfo info =
newBuilder().setPackageName(OTHER_UID_PACKAGE_NAME).setSignatures(SIG2).build(); newBuilder().setPackageName(OTHER_UID_PACKAGE_NAME).setSignatures(SIG2).build();
@ -152,8 +151,7 @@ public final class SecurityPoliciesTest {
} }
@Test @Test
public void testOneOfSignatures_succeedsIfPackageNameAndSignaturesMatch() public void testOneOfSignatures_succeedsIfPackageNameAndSignaturesMatch() throws Exception {
throws Exception {
PackageInfo info = PackageInfo info =
newBuilder().setPackageName(OTHER_UID_PACKAGE_NAME).setSignatures(SIG2).build(); newBuilder().setPackageName(OTHER_UID_PACKAGE_NAME).setSignatures(SIG2).build();
@ -189,8 +187,7 @@ public final class SecurityPoliciesTest {
} }
@Test @Test
public void testOneOfSignature_succeedsIfPackageNameAndOneOfSignaturesMatch() public void testOneOfSignature_succeedsIfPackageNameAndOneOfSignaturesMatch() throws Exception {
throws Exception {
PackageInfo info = PackageInfo info =
newBuilder().setPackageName(OTHER_UID_PACKAGE_NAME).setSignatures(SIG2).build(); newBuilder().setPackageName(OTHER_UID_PACKAGE_NAME).setSignatures(SIG2).build();
@ -206,11 +203,7 @@ public final class SecurityPoliciesTest {
@Test @Test
public void testHasSignature_failsIfUidUnknown() throws Exception { public void testHasSignature_failsIfUidUnknown() throws Exception {
policy = policy = SecurityPolicies.hasSignature(packageManager, appContext.getPackageName(), SIG1);
SecurityPolicies.hasSignature(
packageManager,
appContext.getPackageName(),
SIG1);
assertThat(policy.checkAuthorization(OTHER_UID_UNKNOWN).getCode()) assertThat(policy.checkAuthorization(OTHER_UID_UNKNOWN).getCode())
.isEqualTo(Status.UNAUTHENTICATED.getCode()); .isEqualTo(Status.UNAUTHENTICATED.getCode());
@ -335,8 +328,7 @@ public final class SecurityPoliciesTest {
newBuilder().setPackageName(OTHER_UID_PACKAGE_NAME).setSignatures(SIG2).build(); newBuilder().setPackageName(OTHER_UID_PACKAGE_NAME).setSignatures(SIG2).build();
installPackages(OTHER_UID, info); installPackages(OTHER_UID, info);
shadowOf(devicePolicyManager) shadowOf(devicePolicyManager).setDeviceOwner(new ComponentName(OTHER_UID_PACKAGE_NAME, "foo"));
.setDeviceOwner(new ComponentName(OTHER_UID_PACKAGE_NAME, "foo"));
policy = SecurityPolicies.isDeviceOwner(appContext); policy = SecurityPolicies.isDeviceOwner(appContext);
@ -352,17 +344,18 @@ public final class SecurityPoliciesTest {
policy = SecurityPolicies.isDeviceOwner(appContext); policy = SecurityPolicies.isDeviceOwner(appContext);
assertThat(policy.checkAuthorization(OTHER_UID).getCode()).isEqualTo(Status.PERMISSION_DENIED.getCode()); assertThat(policy.checkAuthorization(OTHER_UID).getCode())
.isEqualTo(Status.PERMISSION_DENIED.getCode());
} }
@Test @Test
public void testIsDeviceOwner_failsWhenNoPackagesForUid() throws Exception { public void testIsDeviceOwner_failsWhenNoPackagesForUid() throws Exception {
policy = SecurityPolicies.isDeviceOwner(appContext); policy = SecurityPolicies.isDeviceOwner(appContext);
assertThat(policy.checkAuthorization(OTHER_UID).getCode()).isEqualTo(Status.UNAUTHENTICATED.getCode()); assertThat(policy.checkAuthorization(OTHER_UID).getCode())
.isEqualTo(Status.UNAUTHENTICATED.getCode());
} }
@Test @Test
@Config(sdk = 21) @Config(sdk = 21)
public void testIsProfileOwner_succeedsForProfileOwner() throws Exception { public void testIsProfileOwner_succeedsForProfileOwner() throws Exception {
@ -370,8 +363,7 @@ public final class SecurityPoliciesTest {
newBuilder().setPackageName(OTHER_UID_PACKAGE_NAME).setSignatures(SIG2).build(); newBuilder().setPackageName(OTHER_UID_PACKAGE_NAME).setSignatures(SIG2).build();
installPackages(OTHER_UID, info); installPackages(OTHER_UID, info);
shadowOf(devicePolicyManager) shadowOf(devicePolicyManager).setProfileOwner(new ComponentName(OTHER_UID_PACKAGE_NAME, "foo"));
.setProfileOwner(new ComponentName(OTHER_UID_PACKAGE_NAME, "foo"));
policy = SecurityPolicies.isProfileOwner(appContext); policy = SecurityPolicies.isProfileOwner(appContext);
@ -388,7 +380,8 @@ public final class SecurityPoliciesTest {
policy = SecurityPolicies.isProfileOwner(appContext); policy = SecurityPolicies.isProfileOwner(appContext);
assertThat(policy.checkAuthorization(OTHER_UID).getCode()).isEqualTo(Status.PERMISSION_DENIED.getCode()); assertThat(policy.checkAuthorization(OTHER_UID).getCode())
.isEqualTo(Status.PERMISSION_DENIED.getCode());
} }
@Test @Test
@ -396,7 +389,8 @@ public final class SecurityPoliciesTest {
public void testIsProfileOwner_failsWhenNoPackagesForUid() throws Exception { public void testIsProfileOwner_failsWhenNoPackagesForUid() throws Exception {
policy = SecurityPolicies.isProfileOwner(appContext); policy = SecurityPolicies.isProfileOwner(appContext);
assertThat(policy.checkAuthorization(OTHER_UID).getCode()).isEqualTo(Status.UNAUTHENTICATED.getCode()); assertThat(policy.checkAuthorization(OTHER_UID).getCode())
.isEqualTo(Status.UNAUTHENTICATED.getCode());
} }
@Test @Test
@ -406,14 +400,12 @@ public final class SecurityPoliciesTest {
newBuilder().setPackageName(OTHER_UID_PACKAGE_NAME).setSignatures(SIG2).build(); newBuilder().setPackageName(OTHER_UID_PACKAGE_NAME).setSignatures(SIG2).build();
installPackages(OTHER_UID, info); installPackages(OTHER_UID, info);
shadowOf(devicePolicyManager) shadowOf(devicePolicyManager).setProfileOwner(new ComponentName(OTHER_UID_PACKAGE_NAME, "foo"));
.setProfileOwner(new ComponentName(OTHER_UID_PACKAGE_NAME, "foo"));
shadowOf(devicePolicyManager).setOrganizationOwnedDeviceWithManagedProfile(true); shadowOf(devicePolicyManager).setOrganizationOwnedDeviceWithManagedProfile(true);
policy = SecurityPolicies.isProfileOwnerOnOrganizationOwnedDevice(appContext); policy = SecurityPolicies.isProfileOwnerOnOrganizationOwnedDevice(appContext);
assertThat(policy.checkAuthorization(OTHER_UID).getCode()).isEqualTo(Status.OK.getCode()); assertThat(policy.checkAuthorization(OTHER_UID).getCode()).isEqualTo(Status.OK.getCode());
} }
@Test @Test
@ -423,13 +415,13 @@ public final class SecurityPoliciesTest {
newBuilder().setPackageName(OTHER_UID_PACKAGE_NAME).setSignatures(SIG2).build(); newBuilder().setPackageName(OTHER_UID_PACKAGE_NAME).setSignatures(SIG2).build();
installPackages(OTHER_UID, info); installPackages(OTHER_UID, info);
shadowOf(devicePolicyManager) shadowOf(devicePolicyManager).setProfileOwner(new ComponentName(OTHER_UID_PACKAGE_NAME, "foo"));
.setProfileOwner(new ComponentName(OTHER_UID_PACKAGE_NAME, "foo"));
shadowOf(devicePolicyManager).setOrganizationOwnedDeviceWithManagedProfile(false); shadowOf(devicePolicyManager).setOrganizationOwnedDeviceWithManagedProfile(false);
policy = SecurityPolicies.isProfileOwnerOnOrganizationOwnedDevice(appContext); policy = SecurityPolicies.isProfileOwnerOnOrganizationOwnedDevice(appContext);
assertThat(policy.checkAuthorization(OTHER_UID).getCode()).isEqualTo(Status.PERMISSION_DENIED.getCode()); assertThat(policy.checkAuthorization(OTHER_UID).getCode())
.isEqualTo(Status.PERMISSION_DENIED.getCode());
} }
@Test @Test
@ -442,7 +434,8 @@ public final class SecurityPoliciesTest {
policy = SecurityPolicies.isProfileOwnerOnOrganizationOwnedDevice(appContext); policy = SecurityPolicies.isProfileOwnerOnOrganizationOwnedDevice(appContext);
assertThat(policy.checkAuthorization(OTHER_UID).getCode()).isEqualTo(Status.PERMISSION_DENIED.getCode()); assertThat(policy.checkAuthorization(OTHER_UID).getCode())
.isEqualTo(Status.PERMISSION_DENIED.getCode());
} }
@Test @Test
@ -450,7 +443,8 @@ public final class SecurityPoliciesTest {
public void testIsProfileOwnerOnOrgOwned_failsWhenNoPackagesForUid() throws Exception { public void testIsProfileOwnerOnOrgOwned_failsWhenNoPackagesForUid() throws Exception {
policy = SecurityPolicies.isProfileOwnerOnOrganizationOwnedDevice(appContext); policy = SecurityPolicies.isProfileOwnerOnOrganizationOwnedDevice(appContext);
assertThat(policy.checkAuthorization(OTHER_UID).getCode()).isEqualTo(Status.UNAUTHENTICATED.getCode()); assertThat(policy.checkAuthorization(OTHER_UID).getCode())
.isEqualTo(Status.UNAUTHENTICATED.getCode());
} }
@Test @Test
@ -463,7 +457,8 @@ public final class SecurityPoliciesTest {
policy = SecurityPolicies.isProfileOwner(appContext); policy = SecurityPolicies.isProfileOwner(appContext);
assertThat(policy.checkAuthorization(OTHER_UID).getCode()).isEqualTo(Status.PERMISSION_DENIED.getCode()); assertThat(policy.checkAuthorization(OTHER_UID).getCode())
.isEqualTo(Status.PERMISSION_DENIED.getCode());
} }
private static PackageInfoBuilder newBuilder() { private static PackageInfoBuilder newBuilder() {
@ -490,7 +485,7 @@ public final class SecurityPoliciesTest {
return this; return this;
} }
@SuppressWarnings("deprecation") // 'signatures': We don't yet support signing cert rotation. @SuppressWarnings("deprecation") // 'signatures': We don't yet support signing cert rotation.
public PackageInfo build() { public PackageInfo build() {
checkState(this.packageName != null, "packageName is a mandatory field"); checkState(this.packageName != null, "packageName is a mandatory field");
@ -667,8 +662,8 @@ public final class SecurityPoliciesTest {
@Test @Test
public void public void
testOneOfSignatureSha256Hash_failsIfPackageNameDoNotMatchAndOneOfSignatureHashesMatch() testOneOfSignatureSha256Hash_failsIfPackageNameDoNotMatchAndOneOfSignatureHashesMatch()
throws Exception { throws Exception {
PackageInfo info = PackageInfo info =
newBuilder().setPackageName(OTHER_UID_PACKAGE_NAME).setSignatures(SIG2).build(); newBuilder().setPackageName(OTHER_UID_PACKAGE_NAME).setSignatures(SIG2).build();
installPackages(OTHER_UID, info); installPackages(OTHER_UID, info);

View File

@ -18,8 +18,8 @@ package io.grpc.binder;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertThrows;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import android.os.Process; import android.os.Process;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
@ -27,18 +27,16 @@ import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.Uninterruptibles; import com.google.common.util.concurrent.Uninterruptibles;
import io.grpc.Status; import io.grpc.Status;
import io.grpc.Status.Code;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier; import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public final class ServerSecurityPolicyTest { public final class ServerSecurityPolicyTest {
@ -126,7 +124,6 @@ public final class ServerSecurityPolicyTest {
.isEqualTo(Status.OK.getCode()); .isEqualTo(Status.OK.getCode());
} }
@Test @Test
@Deprecated @Deprecated
public void testPerService_legacyApi() { public void testPerService_legacyApi() {
@ -149,13 +146,16 @@ public final class ServerSecurityPolicyTest {
public void testPerServiceAsync() throws Exception { public void testPerServiceAsync() throws Exception {
policy = policy =
ServerSecurityPolicy.newBuilder() ServerSecurityPolicy.newBuilder()
.servicePolicy(SERVICE2, asyncPolicy(uid -> { .servicePolicy(
// Add some extra future transformation to confirm that a chain SERVICE2,
// of futures gets properly handled. asyncPolicy(
ListenableFuture<Void> dependency = Futures.immediateVoidFuture(); uid -> {
return Futures // Add some extra future transformation to confirm that a chain
.transform(dependency, unused -> Status.OK, MoreExecutors.directExecutor()); // of futures gets properly handled.
})) ListenableFuture<Void> dependency = Futures.immediateVoidFuture();
return Futures.transform(
dependency, unused -> Status.OK, MoreExecutors.directExecutor());
}))
.build(); .build();
assertThat(checkAuthorizationForServiceAsync(policy, MY_UID, SERVICE1)) assertThat(checkAuthorizationForServiceAsync(policy, MY_UID, SERVICE1))
@ -172,11 +172,12 @@ public final class ServerSecurityPolicyTest {
public void testPerService_failedSecurityPolicyFuture_returnsAFailedFuture() { public void testPerService_failedSecurityPolicyFuture_returnsAFailedFuture() {
policy = policy =
ServerSecurityPolicy.newBuilder() ServerSecurityPolicy.newBuilder()
.servicePolicy(SERVICE1, asyncPolicy(uid -> .servicePolicy(
Futures SERVICE1,
.immediateFailedFuture( asyncPolicy(
new IllegalStateException("something went wrong")) uid ->
)) Futures.immediateFailedFuture(
new IllegalStateException("something went wrong"))))
.build(); .build();
ListenableFuture<Status> statusFuture = ListenableFuture<Status> statusFuture =
@ -203,24 +204,31 @@ public final class ServerSecurityPolicyTest {
ListeningExecutorService listeningExecutorService = ListeningExecutorService listeningExecutorService =
MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()); MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
CountDownLatch unsatisfiedLatch = new CountDownLatch(1); CountDownLatch unsatisfiedLatch = new CountDownLatch(1);
ListenableFuture<Status> toBeInterruptedFuture = listeningExecutorService.submit(() -> { ListenableFuture<Status> toBeInterruptedFuture =
unsatisfiedLatch.await(); // waits forever listeningExecutorService.submit(
return null; () -> {
}); unsatisfiedLatch.await(); // waits forever
return null;
});
CyclicBarrier barrier = new CyclicBarrier(2); CyclicBarrier barrier = new CyclicBarrier(2);
Thread testThread = Thread.currentThread(); Thread testThread = Thread.currentThread();
new Thread(() -> { new Thread(
awaitOrFail(barrier); () -> {
testThread.interrupt(); awaitOrFail(barrier);
}).start(); testThread.interrupt();
})
.start();
policy = policy =
ServerSecurityPolicy.newBuilder() ServerSecurityPolicy.newBuilder()
.servicePolicy(SERVICE1, asyncPolicy(unused -> { .servicePolicy(
awaitOrFail(barrier); SERVICE1,
return toBeInterruptedFuture; asyncPolicy(
})) unused -> {
awaitOrFail(barrier);
return toBeInterruptedFuture;
}))
.build(); .build();
ListenableFuture<Status> statusFuture = ListenableFuture<Status> statusFuture =
policy.checkAuthorizationForServiceAsync(MY_UID, SERVICE1); policy.checkAuthorizationForServiceAsync(MY_UID, SERVICE1);
@ -247,13 +255,16 @@ public final class ServerSecurityPolicyTest {
// Uses the specified policy for service2. // Uses the specified policy for service2.
assertThat(checkAuthorizationForServiceAsync(policy, MY_UID, SERVICE2)) assertThat(checkAuthorizationForServiceAsync(policy, MY_UID, SERVICE2))
.isEqualTo(Status.PERMISSION_DENIED.getCode()); .isEqualTo(Status.PERMISSION_DENIED.getCode());
assertThat(checkAuthorizationForServiceAsync(policy, OTHER_UID, SERVICE2)).isEqualTo(Status.OK.getCode()); assertThat(checkAuthorizationForServiceAsync(policy, OTHER_UID, SERVICE2))
.isEqualTo(Status.OK.getCode());
// Falls back to the default. // Falls back to the default.
assertThat(checkAuthorizationForServiceAsync(policy, MY_UID, SERVICE3)).isEqualTo(Status.OK.getCode()); assertThat(checkAuthorizationForServiceAsync(policy, MY_UID, SERVICE3))
.isEqualTo(Status.OK.getCode());
assertThat(checkAuthorizationForServiceAsync(policy, OTHER_UID, SERVICE3)) assertThat(checkAuthorizationForServiceAsync(policy, OTHER_UID, SERVICE3))
.isEqualTo(Status.PERMISSION_DENIED.getCode()); .isEqualTo(Status.PERMISSION_DENIED.getCode());
} }
@Test @Test
@Deprecated @Deprecated
public void testPerServiceNoDefault_legacyApi() { public void testPerServiceNoDefault_legacyApi() {
@ -286,44 +297,40 @@ public final class ServerSecurityPolicyTest {
@Test @Test
public void testPerServiceNoDefaultAsync() throws Exception { public void testPerServiceNoDefaultAsync() throws Exception {
policy = policy =
ServerSecurityPolicy.newBuilder() ServerSecurityPolicy.newBuilder()
.servicePolicy( .servicePolicy(SERVICE1, asyncPolicy((uid) -> Futures.immediateFuture(Status.INTERNAL)))
SERVICE1, .servicePolicy(
asyncPolicy((uid) -> Futures.immediateFuture(Status.INTERNAL))) SERVICE2,
.servicePolicy( asyncPolicy(
SERVICE2, asyncPolicy((uid) -> { (uid) -> {
// Add some extra future transformation to confirm that a chain // Add some extra future transformation to confirm that a chain
// of futures gets properly handled. // of futures gets properly handled.
ListenableFuture<Boolean> anotherUidFuture = ListenableFuture<Boolean> anotherUidFuture =
Futures.immediateFuture(uid == OTHER_UID); Futures.immediateFuture(uid == OTHER_UID);
return Futures return Futures.transform(
.transform( anotherUidFuture,
anotherUidFuture, anotherUid -> anotherUid ? Status.OK : Status.PERMISSION_DENIED,
anotherUid -> MoreExecutors.directExecutor());
anotherUid }))
? Status.OK .build();
: Status.PERMISSION_DENIED,
MoreExecutors.directExecutor());
}))
.build();
// Uses the specified policy for service1. // Uses the specified policy for service1.
assertThat(checkAuthorizationForServiceAsync(policy, MY_UID, SERVICE1)) assertThat(checkAuthorizationForServiceAsync(policy, MY_UID, SERVICE1))
.isEqualTo(Status.INTERNAL.getCode()); .isEqualTo(Status.INTERNAL.getCode());
assertThat(checkAuthorizationForServiceAsync(policy, OTHER_UID, SERVICE1)) assertThat(checkAuthorizationForServiceAsync(policy, OTHER_UID, SERVICE1))
.isEqualTo(Status.INTERNAL.getCode()); .isEqualTo(Status.INTERNAL.getCode());
// Uses the specified policy for service2. // Uses the specified policy for service2.
assertThat(checkAuthorizationForServiceAsync(policy, MY_UID, SERVICE2)) assertThat(checkAuthorizationForServiceAsync(policy, MY_UID, SERVICE2))
.isEqualTo(Status.PERMISSION_DENIED.getCode()); .isEqualTo(Status.PERMISSION_DENIED.getCode());
assertThat(checkAuthorizationForServiceAsync(policy, OTHER_UID, SERVICE2)) assertThat(checkAuthorizationForServiceAsync(policy, OTHER_UID, SERVICE2))
.isEqualTo(Status.OK.getCode()); .isEqualTo(Status.OK.getCode());
// Falls back to the default. // Falls back to the default.
assertThat(checkAuthorizationForServiceAsync(policy, MY_UID, SERVICE3)) assertThat(checkAuthorizationForServiceAsync(policy, MY_UID, SERVICE3))
.isEqualTo(Status.OK.getCode()); .isEqualTo(Status.OK.getCode());
assertThat(checkAuthorizationForServiceAsync(policy, OTHER_UID, SERVICE3)) assertThat(checkAuthorizationForServiceAsync(policy, OTHER_UID, SERVICE3))
.isEqualTo(Status.PERMISSION_DENIED.getCode()); .isEqualTo(Status.PERMISSION_DENIED.getCode());
} }
/** /**
@ -331,9 +338,7 @@ public final class ServerSecurityPolicyTest {
* dealing with concurrency details. Returns a {link @Status.Code} for convenience. * dealing with concurrency details. Returns a {link @Status.Code} for convenience.
*/ */
private static Status.Code checkAuthorizationForServiceAsync( private static Status.Code checkAuthorizationForServiceAsync(
ServerSecurityPolicy policy, ServerSecurityPolicy policy, int callerUid, String service) throws ExecutionException {
int callerUid,
String service) throws ExecutionException {
ListenableFuture<Status> statusFuture = ListenableFuture<Status> statusFuture =
policy.checkAuthorizationForServiceAsync(callerUid, service); policy.checkAuthorizationForServiceAsync(callerUid, service);
return Uninterruptibles.getUninterruptibly(statusFuture).getCode(); return Uninterruptibles.getUninterruptibly(statusFuture).getCode();
@ -359,12 +364,12 @@ public final class ServerSecurityPolicyTest {
private static void awaitOrFail(CyclicBarrier barrier) { private static void awaitOrFail(CyclicBarrier barrier) {
try { try {
barrier.await(); barrier.await();
} catch (BrokenBarrierException e) { } catch (BrokenBarrierException e) {
fail(e.getMessage()); fail(e.getMessage());
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
fail(e.getMessage()); fail(e.getMessage());
} }
} }
} }

View File

@ -32,7 +32,6 @@ import com.google.common.collect.ImmutableList;
import io.grpc.Attributes; import io.grpc.Attributes;
import io.grpc.Metadata; import io.grpc.Metadata;
import io.grpc.Status; import io.grpc.Status;
import io.grpc.binder.internal.MainThreadScheduledExecutorService;
import io.grpc.internal.FixedObjectPool; import io.grpc.internal.FixedObjectPool;
import io.grpc.internal.ServerStream; import io.grpc.internal.ServerStream;
import io.grpc.internal.ServerTransportListener; import io.grpc.internal.ServerTransportListener;

View File

@ -45,8 +45,7 @@ public final class BlockInputStreamTest {
@Test @Test
public void testSingleBlock() throws Exception { public void testSingleBlock() throws Exception {
BlockInputStream bis = BlockInputStream bis = new BlockInputStream(new byte[][] {getBytes(10, 1)}, 10);
new BlockInputStream(new byte[][] {getBytes(10, 1)}, 10);
assertThat(bis.read(buff, 0, 20)).isEqualTo(10); assertThat(bis.read(buff, 0, 20)).isEqualTo(10);
assertBytes(buff, 0, 10, 1); assertBytes(buff, 0, 10, 1);
} }
@ -95,8 +94,7 @@ public final class BlockInputStreamTest {
@Test @Test
public void testMultipleBlocksEmptyFinalBlock() throws Exception { public void testMultipleBlocksEmptyFinalBlock() throws Exception {
BlockInputStream bis = BlockInputStream bis = new BlockInputStream(new byte[][] {getBytes(10, 1), getBytes(0, 0)}, 10);
new BlockInputStream(new byte[][] {getBytes(10, 1), getBytes(0, 0)}, 10);
assertThat(bis.read(buff, 0, 20)).isEqualTo(10); assertThat(bis.read(buff, 0, 20)).isEqualTo(10);
assertBytes(buff, 0, 10, 1); assertBytes(buff, 0, 10, 1);
@ -106,8 +104,7 @@ public final class BlockInputStreamTest {
@Test @Test
public void testMultipleBlocksEmptyFinalBlock_drain() throws Exception { public void testMultipleBlocksEmptyFinalBlock_drain() throws Exception {
BlockInputStream bis = BlockInputStream bis = new BlockInputStream(new byte[][] {getBytes(10, 1), getBytes(0, 0)}, 10);
new BlockInputStream(new byte[][] {getBytes(10, 1), getBytes(0, 0)}, 10);
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
bis.drainTo(baos); bis.drainTo(baos);
byte[] data = baos.toByteArray(); byte[] data = baos.toByteArray();

View File

@ -6,6 +6,10 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import io.grpc.Metadata;
import io.grpc.ServerCall;
import io.grpc.ServerCallHandler;
import io.grpc.Status;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
@ -19,11 +23,6 @@ import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule; import org.mockito.junit.MockitoRule;
import io.grpc.Metadata;
import io.grpc.ServerCall;
import io.grpc.ServerCallHandler;
import io.grpc.Status;
@RunWith(JUnit4.class) @RunWith(JUnit4.class)
public final class PendingAuthListenerTest { public final class PendingAuthListenerTest {

View File

@ -266,8 +266,7 @@ public final class ServiceBindingTest {
@Test @Test
@Config(sdk = 30) @Config(sdk = 30)
public void testBindWithTargetUserHandle() throws Exception { public void testBindWithTargetUserHandle() throws Exception {
binding = binding = newBuilder().setTargetUserHandle(generateUserHandle(/* userId= */ 0)).build();
newBuilder().setTargetUserHandle(generateUserHandle(/* userId= */ 0)).build();
shadowOf(getMainLooper()).idle(); shadowOf(getMainLooper()).idle();
binding.bind(); binding.bind();
@ -290,8 +289,7 @@ public final class ServiceBindingTest {
newBuilder() newBuilder()
.setTargetUserHandle(UserHandle.getUserHandleForUid(/* userId= */ 0)) .setTargetUserHandle(UserHandle.getUserHandleForUid(/* userId= */ 0))
.setTargetUserHandle(generateUserHandle(/* userId= */ 0)) .setTargetUserHandle(generateUserHandle(/* userId= */ 0))
.setChannelCredentials( .setChannelCredentials(BinderChannelCredentials.forDevicePolicyAdmin(adminComponent))
BinderChannelCredentials.forDevicePolicyAdmin(adminComponent))
.build(); .build();
shadowOf(getMainLooper()).idle(); shadowOf(getMainLooper()).idle();
@ -317,16 +315,16 @@ public final class ServiceBindingTest {
} }
} }
private static void allowBindDeviceAdminForUser(Context context, ComponentName admin, int userId) { private static void allowBindDeviceAdminForUser(
Context context, ComponentName admin, int userId) {
ShadowDevicePolicyManager devicePolicyManager = ShadowDevicePolicyManager devicePolicyManager =
shadowOf(context.getSystemService(DevicePolicyManager.class)); shadowOf(context.getSystemService(DevicePolicyManager.class));
devicePolicyManager.setDeviceOwner(admin); devicePolicyManager.setDeviceOwner(admin);
devicePolicyManager.setBindDeviceAdminTargetUsers( devicePolicyManager.setBindDeviceAdminTargetUsers(
Arrays.asList(UserHandle.getUserHandleForUid(userId))); Arrays.asList(UserHandle.getUserHandleForUid(userId)));
shadowOf((DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE)); shadowOf((DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE));
devicePolicyManager.setDeviceOwner(admin); devicePolicyManager.setDeviceOwner(admin);
devicePolicyManager.setBindDeviceAdminTargetUsers( devicePolicyManager.setBindDeviceAdminTargetUsers(Arrays.asList(generateUserHandle(userId)));
Arrays.asList(generateUserHandle(userId)));
} }
/** Generate UserHandles the hard way. */ /** Generate UserHandles the hard way. */

View File

@ -7,14 +7,10 @@ import io.grpc.ServerCall;
import io.grpc.ServerCallHandler; import io.grpc.ServerCallHandler;
import io.grpc.ServerInterceptor; import io.grpc.ServerInterceptor;
/** /** Class which helps set up {@link PeerUids} to be used in tests. */
* Class which helps set up {@link PeerUids} to be used in tests.
*/
public final class PeerUidTestHelper { public final class PeerUidTestHelper {
/** /** The UID of the calling package is set with the value of this key. */
* The UID of the calling package is set with the value of this key.
*/
public static final Metadata.Key<Integer> UID_KEY = public static final Metadata.Key<Integer> UID_KEY =
Metadata.Key.of("binder-remote-uid-for-unit-testing", PeerUidTestMarshaller.INSTANCE); Metadata.Key.of("binder-remote-uid-for-unit-testing", PeerUidTestMarshaller.INSTANCE);
@ -41,8 +37,7 @@ public final class PeerUidTestHelper {
}; };
} }
private PeerUidTestHelper() { private PeerUidTestHelper() {}
}
private static class PeerUidTestMarshaller implements Metadata.AsciiMarshaller<Integer> { private static class PeerUidTestMarshaller implements Metadata.AsciiMarshaller<Integer> {
@ -58,6 +53,5 @@ public final class PeerUidTestHelper {
return Integer.parseInt(serialized); return Integer.parseInt(serialized);
} }
} }
; ;
} }

View File

@ -110,8 +110,7 @@ public class MainThreadScheduledExecutorService extends AbstractExecutorService
} }
@Override @Override
public void shutdown() { public void shutdown() {}
}
@Override @Override
public List<Runnable> shutdownNow() { public List<Runnable> shutdownNow() {
@ -154,8 +153,7 @@ public class MainThreadScheduledExecutorService extends AbstractExecutorService
@Override @Override
public int compareTo(Delayed other) { public int compareTo(Delayed other) {
return Comparator.comparingLong( return Comparator.comparingLong((Delayed delayed) -> delayed.getDelay(TimeUnit.MILLISECONDS))
(Delayed delayed) -> delayed.getDelay(TimeUnit.MILLISECONDS))
.compare(this, other); .compare(this, other);
} }