1 /* 2 * Copyright 2020 The gRPC Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package io.grpc.binder.internal; 18 19 import android.os.Parcel; 20 import io.grpc.MethodDescriptor.MethodType; 21 import io.grpc.Status; 22 import javax.annotation.Nullable; 23 24 /** Constants and helpers for managing inbound / outbound transactions. */ 25 final class TransactionUtils { 26 /** Set when the transaction contains rpc prefix data. */ 27 static final int FLAG_PREFIX = 0x1; 28 /** Set when the transaction contains some message data. */ 29 static final int FLAG_MESSAGE_DATA = 0x2; 30 /** Set when the transaction contains rpc suffix data. */ 31 static final int FLAG_SUFFIX = 0x4; 32 /** Set when the transaction is an out-of-band close event. */ 33 static final int FLAG_OUT_OF_BAND_CLOSE = 0x8; 34 35 /** 36 * When a transaction contains client prefix data, this will be set if the rpc being made is 37 * expected to return a single message. (I.e the method type is either {@link MethodType#UNARY}, 38 * or {@link MethodType#CLIENT_STREAMING}). 39 */ 40 static final int FLAG_EXPECT_SINGLE_MESSAGE = 0x10; 41 42 /** Set when the included status data includes a description string. */ 43 static final int FLAG_STATUS_DESCRIPTION = 0x20; 44 45 /** When a transaction contains message data, this will be set if the message is a parcelable. */ 46 static final int FLAG_MESSAGE_DATA_IS_PARCELABLE = 0x40; 47 48 /** 49 * When a transaction contains message data, this will be set if the message is only partial, and 50 * further transactions are required. 51 */ 52 static final int FLAG_MESSAGE_DATA_IS_PARTIAL = 0x80; 53 54 static final int STATUS_CODE_SHIFT = 16; 55 static final int STATUS_CODE_MASK = 0xff0000; 56 57 /** The maximum string length for a status description. */ 58 private static final int MAX_STATUS_DESCRIPTION_LENGTH = 1000; 59 TransactionUtils()60 private TransactionUtils() {} 61 hasFlag(int flags, int flag)62 static boolean hasFlag(int flags, int flag) { 63 return (flags & flag) != 0; 64 } 65 66 @Nullable getTruncatedDescription(Status status)67 private static String getTruncatedDescription(Status status) { 68 String desc = status.getDescription(); 69 if (desc != null && desc.length() > MAX_STATUS_DESCRIPTION_LENGTH) { 70 desc = desc.substring(0, MAX_STATUS_DESCRIPTION_LENGTH); 71 } 72 return desc; 73 } 74 readStatus(int flags, Parcel parcel)75 static Status readStatus(int flags, Parcel parcel) { 76 Status status = Status.fromCodeValue((flags & STATUS_CODE_MASK) >> STATUS_CODE_SHIFT); 77 if ((flags & FLAG_STATUS_DESCRIPTION) != 0) { 78 status = status.withDescription(parcel.readString()); 79 } 80 return status; 81 } 82 writeStatus(Parcel parcel, Status status)83 static int writeStatus(Parcel parcel, Status status) { 84 int flags = status.getCode().value() << STATUS_CODE_SHIFT; 85 String desc = getTruncatedDescription(status); 86 if (desc != null) { 87 flags |= FLAG_STATUS_DESCRIPTION; 88 parcel.writeString(desc); 89 } 90 return flags; 91 } 92 fillInFlags(Parcel parcel, int flags)93 static void fillInFlags(Parcel parcel, int flags) { 94 int pos = parcel.dataPosition(); 95 parcel.setDataPosition(0); 96 parcel.writeInt(flags); 97 parcel.setDataPosition(pos); 98 } 99 } 100