Home | History | Annotate | Download | only in binder
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      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 #include <binder/Status.h>
     18 
     19 namespace android {
     20 namespace binder {
     21 
     22 Status Status::ok() {
     23     return Status();
     24 }
     25 
     26 Status Status::fromExceptionCode(int32_t exceptionCode) {
     27     return Status(exceptionCode, OK);
     28 }
     29 
     30 Status Status::fromExceptionCode(int32_t exceptionCode,
     31                                  const String8& message) {
     32     return Status(exceptionCode, OK, message);
     33 }
     34 
     35 Status Status::fromExceptionCode(int32_t exceptionCode,
     36                                  const char* message) {
     37     return fromExceptionCode(exceptionCode, String8(message));
     38 }
     39 
     40 Status Status::fromServiceSpecificError(int32_t serviceSpecificErrorCode) {
     41     return Status(EX_SERVICE_SPECIFIC, serviceSpecificErrorCode);
     42 }
     43 
     44 Status Status::fromServiceSpecificError(int32_t serviceSpecificErrorCode,
     45                                         const String8& message) {
     46     return Status(EX_SERVICE_SPECIFIC, serviceSpecificErrorCode, message);
     47 }
     48 
     49 Status Status::fromServiceSpecificError(int32_t serviceSpecificErrorCode,
     50                                         const char* message) {
     51     return fromServiceSpecificError(serviceSpecificErrorCode, String8(message));
     52 }
     53 
     54 Status Status::fromStatusT(status_t status) {
     55     Status ret;
     56     ret.setFromStatusT(status);
     57     return ret;
     58 }
     59 
     60 Status::Status(int32_t exceptionCode, int32_t errorCode)
     61     : mException(exceptionCode),
     62       mErrorCode(errorCode) {}
     63 
     64 Status::Status(int32_t exceptionCode, int32_t errorCode, const String8& message)
     65     : mException(exceptionCode),
     66       mErrorCode(errorCode),
     67       mMessage(message) {}
     68 
     69 status_t Status::readFromParcel(const Parcel& parcel) {
     70     status_t status = parcel.readInt32(&mException);
     71     if (status != OK) {
     72         setFromStatusT(status);
     73         return status;
     74     }
     75 
     76     // Skip over fat response headers.  Not used (or propagated) in native code.
     77     if (mException == EX_HAS_REPLY_HEADER) {
     78         // Note that the header size includes the 4 byte size field.
     79         const int32_t header_start = parcel.dataPosition();
     80         int32_t header_size;
     81         status = parcel.readInt32(&header_size);
     82         if (status != OK) {
     83             setFromStatusT(status);
     84             return status;
     85         }
     86         parcel.setDataPosition(header_start + header_size);
     87         // And fat response headers are currently only used when there are no
     88         // exceptions, so act like there was no error.
     89         mException = EX_NONE;
     90     }
     91 
     92     if (mException == EX_NONE) {
     93         return status;
     94     }
     95 
     96     // The remote threw an exception.  Get the message back.
     97     String16 message;
     98     status = parcel.readString16(&message);
     99     if (status != OK) {
    100         setFromStatusT(status);
    101         return status;
    102     }
    103     mMessage = String8(message);
    104 
    105     if (mException == EX_SERVICE_SPECIFIC) {
    106         status = parcel.readInt32(&mErrorCode);
    107     } else if (mException == EX_PARCELABLE) {
    108         // Skip over the blob of Parcelable data
    109         const int32_t header_start = parcel.dataPosition();
    110         int32_t header_size;
    111         status = parcel.readInt32(&header_size);
    112         if (status != OK) {
    113             setFromStatusT(status);
    114             return status;
    115         }
    116         parcel.setDataPosition(header_start + header_size);
    117     }
    118     if (status != OK) {
    119         setFromStatusT(status);
    120         return status;
    121     }
    122 
    123     return status;
    124 }
    125 
    126 status_t Status::writeToParcel(Parcel* parcel) const {
    127     // Something really bad has happened, and we're not going to even
    128     // try returning rich error data.
    129     if (mException == EX_TRANSACTION_FAILED) {
    130         return mErrorCode;
    131     }
    132 
    133     status_t status = parcel->writeInt32(mException);
    134     if (status != OK) { return status; }
    135     if (mException == EX_NONE) {
    136         // We have no more information to write.
    137         return status;
    138     }
    139     status = parcel->writeString16(String16(mMessage));
    140     if (mException == EX_SERVICE_SPECIFIC) {
    141         status = parcel->writeInt32(mErrorCode);
    142     } else if (mException == EX_PARCELABLE) {
    143         // Sending Parcelable blobs currently not supported
    144         status = parcel->writeInt32(0);
    145     }
    146     return status;
    147 }
    148 
    149 void Status::setException(int32_t ex, const String8& message) {
    150     mException = ex;
    151     mErrorCode = NO_ERROR;  // an exception, not a transaction failure.
    152     mMessage.setTo(message);
    153 }
    154 
    155 void Status::setServiceSpecificError(int32_t errorCode, const String8& message) {
    156     setException(EX_SERVICE_SPECIFIC, message);
    157     mErrorCode = errorCode;
    158 }
    159 
    160 void Status::setFromStatusT(status_t status) {
    161     mException = (status == NO_ERROR) ? EX_NONE : EX_TRANSACTION_FAILED;
    162     mErrorCode = status;
    163     mMessage.clear();
    164 }
    165 
    166 String8 Status::toString8() const {
    167     String8 ret;
    168     if (mException == EX_NONE) {
    169         ret.append("No error");
    170     } else {
    171         ret.appendFormat("Status(%d): '", mException);
    172         if (mException == EX_SERVICE_SPECIFIC ||
    173             mException == EX_TRANSACTION_FAILED) {
    174             ret.appendFormat("%d: ", mErrorCode);
    175         }
    176         ret.append(String8(mMessage));
    177         ret.append("'");
    178     }
    179     return ret;
    180 }
    181 
    182 std::stringstream& operator<< (std::stringstream& stream, const Status& s) {
    183     stream << s.toString8().string();
    184     return stream;
    185 }
    186 
    187 }  // namespace binder
    188 }  // namespace android
    189