Home | History | Annotate | Download | only in base
      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 #define LOG_TAG "HidlStatus"
     18 #include <android-base/logging.h>
     19 
     20 #include <hidl/Status.h>
     21 
     22 #include <unordered_map>
     23 
     24 namespace android {
     25 namespace hardware {
     26 
     27 static std::string statusToString(status_t s) {
     28     const std::unordered_map<status_t, std::string> statusStrings{{
     29         #define STATUS_TO_STRING_PAIR(STATUS) {STATUS, #STATUS}
     30         STATUS_TO_STRING_PAIR(OK),
     31         STATUS_TO_STRING_PAIR(UNKNOWN_ERROR),
     32         STATUS_TO_STRING_PAIR(NO_MEMORY),
     33         STATUS_TO_STRING_PAIR(INVALID_OPERATION),
     34         STATUS_TO_STRING_PAIR(BAD_VALUE),
     35         STATUS_TO_STRING_PAIR(BAD_TYPE),
     36         STATUS_TO_STRING_PAIR(NAME_NOT_FOUND),
     37         STATUS_TO_STRING_PAIR(PERMISSION_DENIED),
     38         STATUS_TO_STRING_PAIR(NO_INIT),
     39         STATUS_TO_STRING_PAIR(ALREADY_EXISTS),
     40         STATUS_TO_STRING_PAIR(DEAD_OBJECT),
     41         STATUS_TO_STRING_PAIR(FAILED_TRANSACTION),
     42         STATUS_TO_STRING_PAIR(BAD_INDEX),
     43         STATUS_TO_STRING_PAIR(NOT_ENOUGH_DATA),
     44         STATUS_TO_STRING_PAIR(WOULD_BLOCK),
     45         STATUS_TO_STRING_PAIR(TIMED_OUT),
     46         STATUS_TO_STRING_PAIR(UNKNOWN_TRANSACTION),
     47         STATUS_TO_STRING_PAIR(FDS_NOT_ALLOWED),
     48         STATUS_TO_STRING_PAIR(UNEXPECTED_NULL)
     49     }};
     50     auto it = statusStrings.find(s);
     51     if (it != statusStrings.end()) {
     52         return it->second;
     53     }
     54     std::string str = std::to_string(s);
     55     char *err = strerror(-s);
     56     if (err != NULL) {
     57         str.append(1, ' ').append(err);
     58     }
     59     return str;
     60 }
     61 
     62 static std::string exceptionToString(int32_t ex) {
     63     const std::unordered_map<int32_t, std::string> exceptionStrings{{
     64         #define EXCEPTION_TO_STRING_PAIR(EXCEPTION) {Status::Exception::EXCEPTION, #EXCEPTION}
     65         EXCEPTION_TO_STRING_PAIR(EX_NONE),
     66         EXCEPTION_TO_STRING_PAIR(EX_SECURITY),
     67         EXCEPTION_TO_STRING_PAIR(EX_BAD_PARCELABLE),
     68         EXCEPTION_TO_STRING_PAIR(EX_ILLEGAL_ARGUMENT),
     69         EXCEPTION_TO_STRING_PAIR(EX_NULL_POINTER),
     70         EXCEPTION_TO_STRING_PAIR(EX_ILLEGAL_STATE),
     71         EXCEPTION_TO_STRING_PAIR(EX_NETWORK_MAIN_THREAD),
     72         EXCEPTION_TO_STRING_PAIR(EX_UNSUPPORTED_OPERATION),
     73         EXCEPTION_TO_STRING_PAIR(EX_HAS_REPLY_HEADER),
     74         EXCEPTION_TO_STRING_PAIR(EX_TRANSACTION_FAILED)
     75     }};
     76     auto it = exceptionStrings.find(ex);
     77     return it == exceptionStrings.end() ? std::to_string(ex) : it->second;
     78 }
     79 
     80 Status Status::ok() {
     81     return Status();
     82 }
     83 
     84 Status Status::fromExceptionCode(int32_t exceptionCode) {
     85     return Status(exceptionCode, OK);
     86 }
     87 
     88 Status Status::fromExceptionCode(int32_t exceptionCode,
     89                                  const char *message) {
     90     return Status(exceptionCode, OK, message);
     91 }
     92 
     93 Status Status::fromStatusT(status_t status) {
     94     Status ret;
     95     ret.setFromStatusT(status);
     96     return ret;
     97 }
     98 
     99 Status::Status(int32_t exceptionCode, int32_t errorCode)
    100     : mException(exceptionCode),
    101       mErrorCode(errorCode) {}
    102 
    103 Status::Status(int32_t exceptionCode, int32_t errorCode, const char *message)
    104     : mException(exceptionCode),
    105       mErrorCode(errorCode),
    106       mMessage(message) {}
    107 
    108 void Status::setException(int32_t ex, const char *message) {
    109     mException = ex;
    110     mErrorCode = NO_ERROR;  // an exception, not a transaction failure.
    111     mMessage = message;
    112 }
    113 
    114 void Status::setFromStatusT(status_t status) {
    115     mException = (status == NO_ERROR) ? EX_NONE : EX_TRANSACTION_FAILED;
    116     mErrorCode = status;
    117     mMessage.clear();
    118 }
    119 
    120 std::string Status::description() const {
    121     std::ostringstream oss;
    122     oss << (*this);
    123     return oss.str();
    124 }
    125 
    126 std::ostream& operator<< (std::ostream& stream, const Status& s) {
    127     if (s.exceptionCode() == Status::EX_NONE) {
    128         stream << "No error";
    129     } else {
    130         stream << "Status(" << exceptionToString(s.exceptionCode()) << "): '";
    131         if (s.exceptionCode() == Status::EX_TRANSACTION_FAILED) {
    132             stream << statusToString(s.transactionError()) << ": ";
    133         }
    134         stream << s.exceptionMessage() << "'";
    135     }
    136     return stream;
    137 }
    138 
    139 namespace details {
    140     void return_status::assertOk() const {
    141         if (!isOk()) {
    142             LOG(FATAL) << "Attempted to retrieve value from failed HIDL call: " << description();
    143         }
    144     }
    145 
    146     return_status::~return_status() {
    147         // mCheckedStatus must be checked before isOk since isOk modifies mCheckedStatus
    148         if (!mCheckedStatus && !isOk()) {
    149             LOG(FATAL) << "Failed HIDL return status not checked: " << description();
    150         }
    151     }
    152 
    153     return_status &return_status::operator=(return_status &&other) {
    154         if (!mCheckedStatus && !isOk()) {
    155             LOG(FATAL) << "Failed HIDL return status not checked: " << description();
    156         }
    157         std::swap(mStatus, other.mStatus);
    158         std::swap(mCheckedStatus, other.mCheckedStatus);
    159         return *this;
    160     }
    161 
    162 }  // namespace details
    163 
    164 }  // namespace hardware
    165 }  // namespace android
    166