1 /*
2 * Copyright (C) 2023 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 /** Binder utilities. Consumers of this library must link to "libbinder_ndk". */
18
19 #ifndef ART_LIBARTTOOLS_INCLUDE_BINDER_UTILS_TOOLS_BINDER_UTILS_H_
20 #define ART_LIBARTTOOLS_INCLUDE_BINDER_UTILS_TOOLS_BINDER_UTILS_H_
21
22 #include <string>
23
24 #include "android-base/result.h"
25 #include "android-base/strings.h"
26 #include "android/binder_auto_utils.h"
27
28 namespace art {
29 namespace tools {
30
EscapeErrorMessage(const std::string & message)31 static std::string EscapeErrorMessage(const std::string& message) {
32 return android::base::StringReplace(message, std::string("\0", /*n=*/1), "\\0", /*all=*/true);
33 }
34
35 // Indicates an error that should never happen (e.g., illegal arguments passed by service-art
36 // internally). System server should crash if this kind of error happens.
Fatal(const std::string & message)37 [[maybe_unused]] static ndk::ScopedAStatus Fatal(const std::string& message) {
38 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE,
39 EscapeErrorMessage(message).c_str());
40 }
41
42 // Indicates an error that service-art should handle (e.g., I/O errors, sub-process crashes).
43 // The scope of the error depends on the function that throws it, so service-art should catch the
44 // error at every call site and take different actions.
45 // Ideally, this should be a checked exception or an additional return value that forces service-art
46 // to handle it, but `ServiceSpecificException` (a separate runtime exception type) is the best
47 // approximate we have given the limitation of Java and Binder.
NonFatal(const std::string & message)48 [[maybe_unused]] static ndk::ScopedAStatus NonFatal(const std::string& message) {
49 constexpr int32_t kServiceArtNonFatalErrorCode = 1;
50 return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
51 kServiceArtNonFatalErrorCode, EscapeErrorMessage(message).c_str());
52 }
53
54 } // namespace tools
55 } // namespace art
56
57 #define OR_RETURN_ERROR(func, expr) \
58 ({ \
59 decltype(expr)&& __or_return_error_tmp = (expr); \
60 if (!__or_return_error_tmp.ok()) { \
61 return (func)(__or_return_error_tmp.error().message()); \
62 } \
63 std::move(__or_return_error_tmp).value(); \
64 })
65
66 #define OR_RETURN_FATAL(expr) OR_RETURN_ERROR(Fatal, expr)
67 #define OR_RETURN_NON_FATAL(expr) OR_RETURN_ERROR(NonFatal, expr)
68 #define OR_LOG_AND_RETURN_OK(expr) \
69 OR_RETURN_ERROR( \
70 [](const std::string& message) { \
71 LOG(ERROR) << message; \
72 return ScopedAStatus::ok(); \
73 }, \
74 expr)
75
76 #define ASSERT_STATUS_OK(expr) \
77 ({ \
78 ndk::ScopedAStatus __assert_status_ok_status = (expr); \
79 ASSERT_TRUE(__assert_status_ok_status.isOk()) << __assert_status_ok_status.getMessage(); \
80 })
81
82 #endif // ART_LIBARTTOOLS_INCLUDE_BINDER_UTILS_TOOLS_BINDER_UTILS_H_
83