mirror of https://github.com/grpc/grpc-java.git
binder: Rationalize @ThreadSafe-ty of BinderTransport. (#12130)
- Use @BinderThread to document restrictions on methods and certain fields. - Make TransactionHandler non-public since only Android should call it. - Replace an unnecessary AtomicLong with a plain old long.
This commit is contained in:
parent
4cd7881086
commit
c206428749
|
@ -29,6 +29,7 @@ import android.os.Parcel;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.TransactionTooLargeException;
|
import android.os.TransactionTooLargeException;
|
||||||
|
import androidx.annotation.BinderThread;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Ticker;
|
import com.google.common.base.Ticker;
|
||||||
import com.google.common.base.Verify;
|
import com.google.common.base.Verify;
|
||||||
|
@ -105,8 +106,7 @@ import javax.annotation.concurrent.ThreadSafe;
|
||||||
* 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
|
||||||
public abstract class BinderTransport
|
public abstract class BinderTransport implements IBinder.DeathRecipient {
|
||||||
implements LeakSafeOneWayBinder.TransactionHandler, IBinder.DeathRecipient {
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(BinderTransport.class.getName());
|
private static final Logger logger = Logger.getLogger(BinderTransport.class.getName());
|
||||||
|
|
||||||
|
@ -210,9 +210,11 @@ public abstract class BinderTransport
|
||||||
private final FlowController flowController;
|
private final FlowController flowController;
|
||||||
|
|
||||||
/** The number of incoming bytes we've received. */
|
/** The number of incoming bytes we've received. */
|
||||||
private final AtomicLong numIncomingBytes;
|
// Only read/written on @BinderThread.
|
||||||
|
private long numIncomingBytes;
|
||||||
|
|
||||||
/** The number of incoming bytes we've told our peer we've received. */
|
/** The number of incoming bytes we've told our peer we've received. */
|
||||||
|
// Only read/written on @BinderThread.
|
||||||
private long acknowledgedIncomingBytes;
|
private long acknowledgedIncomingBytes;
|
||||||
|
|
||||||
private BinderTransport(
|
private BinderTransport(
|
||||||
|
@ -225,10 +227,9 @@ public abstract class BinderTransport
|
||||||
this.attributes = attributes;
|
this.attributes = attributes;
|
||||||
this.logId = logId;
|
this.logId = logId;
|
||||||
scheduledExecutorService = executorServicePool.getObject();
|
scheduledExecutorService = executorServicePool.getObject();
|
||||||
incomingBinder = new LeakSafeOneWayBinder(this);
|
incomingBinder = new LeakSafeOneWayBinder(this::handleTransaction);
|
||||||
ongoingCalls = new ConcurrentHashMap<>();
|
ongoingCalls = new ConcurrentHashMap<>();
|
||||||
flowController = new FlowController(TRANSACTION_BYTES_WINDOW);
|
flowController = new FlowController(TRANSACTION_BYTES_WINDOW);
|
||||||
numIncomingBytes = new AtomicLong();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override in child class.
|
// Override in child class.
|
||||||
|
@ -423,8 +424,9 @@ public abstract class BinderTransport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@BinderThread
|
||||||
public final boolean handleTransaction(int code, Parcel parcel) {
|
@VisibleForTesting
|
||||||
|
final boolean handleTransaction(int code, Parcel parcel) {
|
||||||
try {
|
try {
|
||||||
return handleTransactionInternal(code, parcel);
|
return handleTransactionInternal(code, parcel);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
|
@ -440,6 +442,7 @@ public abstract class BinderTransport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BinderThread
|
||||||
private boolean handleTransactionInternal(int code, Parcel parcel) {
|
private boolean handleTransactionInternal(int code, Parcel parcel) {
|
||||||
if (code < FIRST_CALL_ID) {
|
if (code < FIRST_CALL_ID) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
|
@ -483,11 +486,12 @@ public abstract class BinderTransport
|
||||||
if (inbound != null) {
|
if (inbound != null) {
|
||||||
inbound.handleTransaction(parcel);
|
inbound.handleTransaction(parcel);
|
||||||
}
|
}
|
||||||
long nib = numIncomingBytes.addAndGet(size);
|
numIncomingBytes += size;
|
||||||
if ((nib - acknowledgedIncomingBytes) > TRANSACTION_BYTES_WINDOW_FORCE_ACK) {
|
if ((numIncomingBytes - acknowledgedIncomingBytes) > TRANSACTION_BYTES_WINDOW_FORCE_ACK) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
sendAcknowledgeBytes(checkNotNull(outgoingBinder));
|
sendAcknowledgeBytes(checkNotNull(outgoingBinder), numIncomingBytes);
|
||||||
}
|
}
|
||||||
|
acknowledgedIncomingBytes = numIncomingBytes;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -519,10 +523,8 @@ public abstract class BinderTransport
|
||||||
protected void handlePingResponse(Parcel parcel) {}
|
protected void handlePingResponse(Parcel parcel) {}
|
||||||
|
|
||||||
@GuardedBy("this")
|
@GuardedBy("this")
|
||||||
private void sendAcknowledgeBytes(OneWayBinderProxy iBinder) {
|
private void sendAcknowledgeBytes(OneWayBinderProxy iBinder, long n) {
|
||||||
// Send a transaction to acknowledge reception of incoming data.
|
// Send a transaction to acknowledge reception of incoming data.
|
||||||
long n = numIncomingBytes.get();
|
|
||||||
acknowledgedIncomingBytes = n;
|
|
||||||
try (ParcelHolder parcel = ParcelHolder.obtain()) {
|
try (ParcelHolder parcel = ParcelHolder.obtain()) {
|
||||||
parcel.get().writeLong(n);
|
parcel.get().writeLong(n);
|
||||||
iBinder.transact(ACKNOWLEDGE_BYTES, parcel);
|
iBinder.transact(ACKNOWLEDGE_BYTES, parcel);
|
||||||
|
|
|
@ -19,6 +19,7 @@ package io.grpc.binder.internal;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
|
import androidx.annotation.BinderThread;
|
||||||
import io.grpc.Internal;
|
import io.grpc.Internal;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
@ -58,6 +59,7 @@ public final class LeakSafeOneWayBinder extends Binder {
|
||||||
* @return the value to return from {@link Binder#onTransact}. NB: "oneway" semantics mean this
|
* @return the value to return from {@link Binder#onTransact}. NB: "oneway" semantics mean this
|
||||||
* result will not delivered to the caller of {@link IBinder#transact}
|
* result will not delivered to the caller of {@link IBinder#transact}
|
||||||
*/
|
*/
|
||||||
|
@BinderThread
|
||||||
boolean handleTransaction(int code, Parcel data);
|
boolean handleTransaction(int code, Parcel data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue