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