• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 #pragma once
18 
19 #include <binder/Status.h>
20 
21 // Extracted from frameworks/av/media/libaudioclient/include/media/AidlConversionUtil.h
22 namespace android::gui::aidl_utils {
23 
24 /**
25  * Return the equivalent Android status_t from a binder exception code.
26  *
27  * Generally one should use statusTFromBinderStatus() instead.
28  *
29  * Exception codes can be generated from a remote Java service exception, translate
30  * them for use on the Native side.
31  *
32  * Note: for EX_TRANSACTION_FAILED and EX_SERVICE_SPECIFIC a more detailed error code
33  * can be found from transactionError() or serviceSpecificErrorCode().
34  */
statusTFromExceptionCode(int32_t exceptionCode)35 static inline status_t statusTFromExceptionCode(int32_t exceptionCode) {
36     using namespace ::android::binder;
37     switch (exceptionCode) {
38         case Status::EX_NONE:
39             return OK;
40         case Status::EX_SECURITY: // Java SecurityException, rethrows locally in Java
41             return PERMISSION_DENIED;
42         case Status::EX_BAD_PARCELABLE:   // Java BadParcelableException, rethrows in Java
43         case Status::EX_ILLEGAL_ARGUMENT: // Java IllegalArgumentException, rethrows in Java
44         case Status::EX_NULL_POINTER:     // Java NullPointerException, rethrows in Java
45             return BAD_VALUE;
46         case Status::EX_ILLEGAL_STATE:         // Java IllegalStateException, rethrows in Java
47         case Status::EX_UNSUPPORTED_OPERATION: // Java UnsupportedOperationException, rethrows
48             return INVALID_OPERATION;
49         case Status::EX_HAS_REPLY_HEADER: // Native strictmode violation
50         case Status::EX_PARCELABLE: // Java bootclass loader (not standard exception), rethrows
51         case Status::EX_NETWORK_MAIN_THREAD: // Java NetworkOnMainThreadException, rethrows
52         case Status::EX_TRANSACTION_FAILED:  // Native - see error code
53         case Status::EX_SERVICE_SPECIFIC:    // Java ServiceSpecificException,
54                                              // rethrows in Java with integer error code
55             return UNKNOWN_ERROR;
56     }
57     return UNKNOWN_ERROR;
58 }
59 
60 /**
61  * Return the equivalent Android status_t from a binder status.
62  *
63  * Used to handle errors from a AIDL method declaration
64  *
65  * [oneway] void method(type0 param0, ...)
66  *
67  * or the following (where return_type is not a status_t)
68  *
69  * return_type method(type0 param0, ...)
70  */
statusTFromBinderStatus(const::android::binder::Status & status)71 static inline status_t statusTFromBinderStatus(const ::android::binder::Status &status) {
72     return status.isOk() ? OK // check OK,
73         : status.serviceSpecificErrorCode() // service-side error, not standard Java exception
74                                             // (fromServiceSpecificError)
75         ?: status.transactionError() // a native binder transaction error (fromStatusT)
76         ?: statusTFromExceptionCode(status.exceptionCode()); // a service-side error with a
77                                                     // standard Java exception (fromExceptionCode)
78 }
79 
80 /**
81  * Return a binder::Status from native service status.
82  *
83  * This is used for methods not returning an explicit status_t,
84  * where Java callers expect an exception, not an integer return value.
85  */
86 static inline ::android::binder::Status binderStatusFromStatusT(
87         status_t status, const char *optionalMessage = nullptr) {
88     const char *const emptyIfNull = optionalMessage == nullptr ? "" : optionalMessage;
89     // From binder::Status instructions:
90     //  Prefer a generic exception code when possible, then a service specific
91     //  code, and finally a status_t for low level failures or legacy support.
92     //  Exception codes and service specific errors map to nicer exceptions for
93     //  Java clients.
94 
95     using namespace ::android::binder;
96     switch (status) {
97         case OK:
98             return Status::ok();
99         case PERMISSION_DENIED: // throw SecurityException on Java side
100             return Status::fromExceptionCode(Status::EX_SECURITY, emptyIfNull);
101         case BAD_VALUE: // throw IllegalArgumentException on Java side
102             return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, emptyIfNull);
103         case INVALID_OPERATION: // throw IllegalStateException on Java side
104             return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, emptyIfNull);
105     }
106 
107     // A service specific error will not show on status.transactionError() so
108     // be sure to use statusTFromBinderStatus() for reliable error handling.
109 
110     // throw a ServiceSpecificException.
111     return Status::fromServiceSpecificError(status, emptyIfNull);
112 }
113 
114 } // namespace android::gui::aidl_utils
115