xref: /aosp_15_r20/system/libhidl/base/Status.cpp (revision 8222fbe171c3d6fadfe95119c180cf3010c392a8)
1*8222fbe1SAndroid Build Coastguard Worker /*
2*8222fbe1SAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*8222fbe1SAndroid Build Coastguard Worker  *
4*8222fbe1SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8222fbe1SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8222fbe1SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8222fbe1SAndroid Build Coastguard Worker  *
8*8222fbe1SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*8222fbe1SAndroid Build Coastguard Worker  *
10*8222fbe1SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8222fbe1SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8222fbe1SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8222fbe1SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8222fbe1SAndroid Build Coastguard Worker  * limitations under the License.
15*8222fbe1SAndroid Build Coastguard Worker  */
16*8222fbe1SAndroid Build Coastguard Worker 
17*8222fbe1SAndroid Build Coastguard Worker #define LOG_TAG "HidlStatus"
18*8222fbe1SAndroid Build Coastguard Worker #include <android-base/logging.h>
19*8222fbe1SAndroid Build Coastguard Worker 
20*8222fbe1SAndroid Build Coastguard Worker #include <hidl/Status.h>
21*8222fbe1SAndroid Build Coastguard Worker #include <utils/CallStack.h>
22*8222fbe1SAndroid Build Coastguard Worker 
23*8222fbe1SAndroid Build Coastguard Worker #include <unordered_map>
24*8222fbe1SAndroid Build Coastguard Worker 
25*8222fbe1SAndroid Build Coastguard Worker namespace android {
26*8222fbe1SAndroid Build Coastguard Worker namespace hardware {
27*8222fbe1SAndroid Build Coastguard Worker 
28*8222fbe1SAndroid Build Coastguard Worker 
exceptionToString(int32_t ex)29*8222fbe1SAndroid Build Coastguard Worker static std::string exceptionToString(int32_t ex) {
30*8222fbe1SAndroid Build Coastguard Worker #define EXCEPTION_CASE(EXCEPTION)      \
31*8222fbe1SAndroid Build Coastguard Worker     case Status::Exception::EXCEPTION: \
32*8222fbe1SAndroid Build Coastguard Worker         return #EXCEPTION
33*8222fbe1SAndroid Build Coastguard Worker 
34*8222fbe1SAndroid Build Coastguard Worker     switch (ex) {
35*8222fbe1SAndroid Build Coastguard Worker         EXCEPTION_CASE(EX_NONE);
36*8222fbe1SAndroid Build Coastguard Worker         EXCEPTION_CASE(EX_SECURITY);
37*8222fbe1SAndroid Build Coastguard Worker         EXCEPTION_CASE(EX_BAD_PARCELABLE);
38*8222fbe1SAndroid Build Coastguard Worker         EXCEPTION_CASE(EX_ILLEGAL_ARGUMENT);
39*8222fbe1SAndroid Build Coastguard Worker         EXCEPTION_CASE(EX_NULL_POINTER);
40*8222fbe1SAndroid Build Coastguard Worker         EXCEPTION_CASE(EX_ILLEGAL_STATE);
41*8222fbe1SAndroid Build Coastguard Worker         EXCEPTION_CASE(EX_NETWORK_MAIN_THREAD);
42*8222fbe1SAndroid Build Coastguard Worker         EXCEPTION_CASE(EX_UNSUPPORTED_OPERATION);
43*8222fbe1SAndroid Build Coastguard Worker         EXCEPTION_CASE(EX_HAS_REPLY_HEADER);
44*8222fbe1SAndroid Build Coastguard Worker         EXCEPTION_CASE(EX_TRANSACTION_FAILED);
45*8222fbe1SAndroid Build Coastguard Worker #undef EXCEPTION_CASE
46*8222fbe1SAndroid Build Coastguard Worker     }
47*8222fbe1SAndroid Build Coastguard Worker     return std::to_string(ex);
48*8222fbe1SAndroid Build Coastguard Worker }
49*8222fbe1SAndroid Build Coastguard Worker 
ok()50*8222fbe1SAndroid Build Coastguard Worker Status Status::ok() {
51*8222fbe1SAndroid Build Coastguard Worker     return Status();
52*8222fbe1SAndroid Build Coastguard Worker }
53*8222fbe1SAndroid Build Coastguard Worker 
fromExceptionCode(int32_t exceptionCode)54*8222fbe1SAndroid Build Coastguard Worker Status Status::fromExceptionCode(int32_t exceptionCode) {
55*8222fbe1SAndroid Build Coastguard Worker     if (exceptionCode == EX_TRANSACTION_FAILED) {
56*8222fbe1SAndroid Build Coastguard Worker         return Status(exceptionCode, FAILED_TRANSACTION);
57*8222fbe1SAndroid Build Coastguard Worker     }
58*8222fbe1SAndroid Build Coastguard Worker     return Status(exceptionCode, OK);
59*8222fbe1SAndroid Build Coastguard Worker }
60*8222fbe1SAndroid Build Coastguard Worker 
fromExceptionCode(int32_t exceptionCode,const char * message)61*8222fbe1SAndroid Build Coastguard Worker Status Status::fromExceptionCode(int32_t exceptionCode,
62*8222fbe1SAndroid Build Coastguard Worker                                  const char *message) {
63*8222fbe1SAndroid Build Coastguard Worker     if (exceptionCode == EX_TRANSACTION_FAILED) {
64*8222fbe1SAndroid Build Coastguard Worker         return Status(exceptionCode, FAILED_TRANSACTION, message);
65*8222fbe1SAndroid Build Coastguard Worker     }
66*8222fbe1SAndroid Build Coastguard Worker     return Status(exceptionCode, OK, message);
67*8222fbe1SAndroid Build Coastguard Worker }
68*8222fbe1SAndroid Build Coastguard Worker 
fromStatusT(status_t status)69*8222fbe1SAndroid Build Coastguard Worker Status Status::fromStatusT(status_t status) {
70*8222fbe1SAndroid Build Coastguard Worker     Status ret;
71*8222fbe1SAndroid Build Coastguard Worker     ret.setFromStatusT(status);
72*8222fbe1SAndroid Build Coastguard Worker     return ret;
73*8222fbe1SAndroid Build Coastguard Worker }
74*8222fbe1SAndroid Build Coastguard Worker 
Status(int32_t exceptionCode,int32_t errorCode)75*8222fbe1SAndroid Build Coastguard Worker Status::Status(int32_t exceptionCode, int32_t errorCode)
76*8222fbe1SAndroid Build Coastguard Worker     : mException(exceptionCode),
77*8222fbe1SAndroid Build Coastguard Worker       mErrorCode(errorCode) {}
78*8222fbe1SAndroid Build Coastguard Worker 
Status(int32_t exceptionCode,int32_t errorCode,const char * message)79*8222fbe1SAndroid Build Coastguard Worker Status::Status(int32_t exceptionCode, int32_t errorCode, const char *message)
80*8222fbe1SAndroid Build Coastguard Worker     : mException(exceptionCode),
81*8222fbe1SAndroid Build Coastguard Worker       mErrorCode(errorCode),
82*8222fbe1SAndroid Build Coastguard Worker       mMessage(message) {}
83*8222fbe1SAndroid Build Coastguard Worker 
setException(int32_t ex,const char * message)84*8222fbe1SAndroid Build Coastguard Worker void Status::setException(int32_t ex, const char *message) {
85*8222fbe1SAndroid Build Coastguard Worker     mException = ex;
86*8222fbe1SAndroid Build Coastguard Worker     mErrorCode = ex == EX_TRANSACTION_FAILED ? FAILED_TRANSACTION : NO_ERROR;
87*8222fbe1SAndroid Build Coastguard Worker     mMessage = message;
88*8222fbe1SAndroid Build Coastguard Worker }
89*8222fbe1SAndroid Build Coastguard Worker 
setFromStatusT(status_t status)90*8222fbe1SAndroid Build Coastguard Worker void Status::setFromStatusT(status_t status) {
91*8222fbe1SAndroid Build Coastguard Worker     mException = (status == NO_ERROR) ? EX_NONE : EX_TRANSACTION_FAILED;
92*8222fbe1SAndroid Build Coastguard Worker     mErrorCode = status;
93*8222fbe1SAndroid Build Coastguard Worker     mMessage.clear();
94*8222fbe1SAndroid Build Coastguard Worker }
95*8222fbe1SAndroid Build Coastguard Worker 
description() const96*8222fbe1SAndroid Build Coastguard Worker std::string Status::description() const {
97*8222fbe1SAndroid Build Coastguard Worker     std::ostringstream oss;
98*8222fbe1SAndroid Build Coastguard Worker     oss << (*this);
99*8222fbe1SAndroid Build Coastguard Worker     return oss.str();
100*8222fbe1SAndroid Build Coastguard Worker }
101*8222fbe1SAndroid Build Coastguard Worker 
operator <<(std::ostream & stream,const Status & s)102*8222fbe1SAndroid Build Coastguard Worker std::ostream& operator<< (std::ostream& stream, const Status& s) {
103*8222fbe1SAndroid Build Coastguard Worker     if (s.exceptionCode() == Status::EX_NONE) {
104*8222fbe1SAndroid Build Coastguard Worker         stream << "No error";
105*8222fbe1SAndroid Build Coastguard Worker     } else {
106*8222fbe1SAndroid Build Coastguard Worker         stream << "Status(" << exceptionToString(s.exceptionCode()) << "): '";
107*8222fbe1SAndroid Build Coastguard Worker         if (s.exceptionCode() == Status::EX_TRANSACTION_FAILED) {
108*8222fbe1SAndroid Build Coastguard Worker             stream << statusToString(s.transactionError()) << ": ";
109*8222fbe1SAndroid Build Coastguard Worker         }
110*8222fbe1SAndroid Build Coastguard Worker         stream << s.exceptionMessage() << "'";
111*8222fbe1SAndroid Build Coastguard Worker     }
112*8222fbe1SAndroid Build Coastguard Worker     return stream;
113*8222fbe1SAndroid Build Coastguard Worker }
114*8222fbe1SAndroid Build Coastguard Worker 
115*8222fbe1SAndroid Build Coastguard Worker static HidlReturnRestriction gReturnRestriction = HidlReturnRestriction::NONE;
setProcessHidlReturnRestriction(HidlReturnRestriction restriction)116*8222fbe1SAndroid Build Coastguard Worker void setProcessHidlReturnRestriction(HidlReturnRestriction restriction) {
117*8222fbe1SAndroid Build Coastguard Worker     gReturnRestriction = restriction;
118*8222fbe1SAndroid Build Coastguard Worker }
119*8222fbe1SAndroid Build Coastguard Worker 
120*8222fbe1SAndroid Build Coastguard Worker namespace details {
onValueRetrieval() const121*8222fbe1SAndroid Build Coastguard Worker     void return_status::onValueRetrieval() const {
122*8222fbe1SAndroid Build Coastguard Worker         if (!isOk()) {
123*8222fbe1SAndroid Build Coastguard Worker             LOG(FATAL) << "Attempted to retrieve value from failed HIDL call: " << description();
124*8222fbe1SAndroid Build Coastguard Worker         }
125*8222fbe1SAndroid Build Coastguard Worker     }
126*8222fbe1SAndroid Build Coastguard Worker 
onIgnored() const127*8222fbe1SAndroid Build Coastguard Worker     void return_status::onIgnored() const {
128*8222fbe1SAndroid Build Coastguard Worker         if (gReturnRestriction == HidlReturnRestriction::NONE) {
129*8222fbe1SAndroid Build Coastguard Worker             return;
130*8222fbe1SAndroid Build Coastguard Worker         }
131*8222fbe1SAndroid Build Coastguard Worker 
132*8222fbe1SAndroid Build Coastguard Worker         if (gReturnRestriction == HidlReturnRestriction::ERROR_IF_UNCHECKED) {
133*8222fbe1SAndroid Build Coastguard Worker             LOG(ERROR) << "Failed to check status of HIDL Return.";
134*8222fbe1SAndroid Build Coastguard Worker             CallStack::logStack("unchecked HIDL return", CallStack::getCurrent(10).get(),
135*8222fbe1SAndroid Build Coastguard Worker                                 ANDROID_LOG_ERROR);
136*8222fbe1SAndroid Build Coastguard Worker         } else {
137*8222fbe1SAndroid Build Coastguard Worker             LOG(FATAL) << "Failed to check status of HIDL Return.";
138*8222fbe1SAndroid Build Coastguard Worker         }
139*8222fbe1SAndroid Build Coastguard Worker     }
140*8222fbe1SAndroid Build Coastguard Worker 
assertOk() const141*8222fbe1SAndroid Build Coastguard Worker     void return_status::assertOk() const {
142*8222fbe1SAndroid Build Coastguard Worker         if (!isOk()) {
143*8222fbe1SAndroid Build Coastguard Worker             LOG(FATAL) << "Failed HIDL return status not checked. Usually this happens because of "
144*8222fbe1SAndroid Build Coastguard Worker                           "a transport error (error parceling, binder driver, or from unparceling)"
145*8222fbe1SAndroid Build Coastguard Worker                           ". If you see this in code calling into \"Bn\" classes in for a HAL "
146*8222fbe1SAndroid Build Coastguard Worker                           "server process, then it is likely that the code there is returning "
147*8222fbe1SAndroid Build Coastguard Worker                           "transport errors there (as opposed to errors defined within its "
148*8222fbe1SAndroid Build Coastguard Worker                           "protocol). Error is: " << description();
149*8222fbe1SAndroid Build Coastguard Worker         }
150*8222fbe1SAndroid Build Coastguard Worker     }
151*8222fbe1SAndroid Build Coastguard Worker 
~return_status()152*8222fbe1SAndroid Build Coastguard Worker     return_status::~return_status() {
153*8222fbe1SAndroid Build Coastguard Worker         // mCheckedStatus must be checked before isOk since isOk modifies mCheckedStatus
154*8222fbe1SAndroid Build Coastguard Worker         if (mCheckedStatus) return;
155*8222fbe1SAndroid Build Coastguard Worker 
156*8222fbe1SAndroid Build Coastguard Worker         assertOk();
157*8222fbe1SAndroid Build Coastguard Worker         onIgnored();
158*8222fbe1SAndroid Build Coastguard Worker     }
159*8222fbe1SAndroid Build Coastguard Worker 
operator =(return_status && other)160*8222fbe1SAndroid Build Coastguard Worker     return_status& return_status::operator=(return_status&& other) noexcept {
161*8222fbe1SAndroid Build Coastguard Worker         if (!mCheckedStatus) {
162*8222fbe1SAndroid Build Coastguard Worker             assertOk();
163*8222fbe1SAndroid Build Coastguard Worker             onIgnored();
164*8222fbe1SAndroid Build Coastguard Worker         }
165*8222fbe1SAndroid Build Coastguard Worker 
166*8222fbe1SAndroid Build Coastguard Worker         std::swap(mStatus, other.mStatus);
167*8222fbe1SAndroid Build Coastguard Worker         std::swap(mCheckedStatus, other.mCheckedStatus);
168*8222fbe1SAndroid Build Coastguard Worker         return *this;
169*8222fbe1SAndroid Build Coastguard Worker     }
170*8222fbe1SAndroid Build Coastguard Worker 
171*8222fbe1SAndroid Build Coastguard Worker }  // namespace details
172*8222fbe1SAndroid Build Coastguard Worker 
173*8222fbe1SAndroid Build Coastguard Worker }  // namespace hardware
174*8222fbe1SAndroid Build Coastguard Worker }  // namespace android
175