1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright (C) 2024 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker #pragma once
18*38e8c45fSAndroid Build Coastguard Worker
19*38e8c45fSAndroid Build Coastguard Worker #include <android/binder_auto_utils.h>
20*38e8c45fSAndroid Build Coastguard Worker #include <android/binder_status.h>
21*38e8c45fSAndroid Build Coastguard Worker #include <android/hardware/power/1.0/IPower.h>
22*38e8c45fSAndroid Build Coastguard Worker #include <binder/Status.h>
23*38e8c45fSAndroid Build Coastguard Worker #include <hidl/HidlSupport.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <string>
25*38e8c45fSAndroid Build Coastguard Worker
26*38e8c45fSAndroid Build Coastguard Worker namespace android::power {
27*38e8c45fSAndroid Build Coastguard Worker
checkUnsupported(const ndk::ScopedAStatus & ndkStatus)28*38e8c45fSAndroid Build Coastguard Worker static bool checkUnsupported(const ndk::ScopedAStatus& ndkStatus) {
29*38e8c45fSAndroid Build Coastguard Worker return ndkStatus.getExceptionCode() == EX_UNSUPPORTED_OPERATION ||
30*38e8c45fSAndroid Build Coastguard Worker ndkStatus.getStatus() == STATUS_UNKNOWN_TRANSACTION;
31*38e8c45fSAndroid Build Coastguard Worker }
32*38e8c45fSAndroid Build Coastguard Worker
checkUnsupported(const binder::Status & status)33*38e8c45fSAndroid Build Coastguard Worker static bool checkUnsupported(const binder::Status& status) {
34*38e8c45fSAndroid Build Coastguard Worker return status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION ||
35*38e8c45fSAndroid Build Coastguard Worker status.transactionError() == UNKNOWN_TRANSACTION;
36*38e8c45fSAndroid Build Coastguard Worker }
37*38e8c45fSAndroid Build Coastguard Worker
38*38e8c45fSAndroid Build Coastguard Worker // Result of a call to the Power HAL wrapper, holding data if successful.
39*38e8c45fSAndroid Build Coastguard Worker template <typename T>
40*38e8c45fSAndroid Build Coastguard Worker class HalResult {
41*38e8c45fSAndroid Build Coastguard Worker public:
ok(T && value)42*38e8c45fSAndroid Build Coastguard Worker static HalResult<T> ok(T&& value) { return HalResult(std::forward<T>(value)); }
ok(T & value)43*38e8c45fSAndroid Build Coastguard Worker static HalResult<T> ok(T& value) { return HalResult<T>::ok(T{value}); }
failed(std::string msg)44*38e8c45fSAndroid Build Coastguard Worker static HalResult<T> failed(std::string msg) { return HalResult(msg, /* unsupported= */ false); }
unsupported()45*38e8c45fSAndroid Build Coastguard Worker static HalResult<T> unsupported() { return HalResult("", /* unsupported= */ true); }
46*38e8c45fSAndroid Build Coastguard Worker
fromStatus(const binder::Status & status,T && data)47*38e8c45fSAndroid Build Coastguard Worker static HalResult<T> fromStatus(const binder::Status& status, T&& data) {
48*38e8c45fSAndroid Build Coastguard Worker if (checkUnsupported(status)) {
49*38e8c45fSAndroid Build Coastguard Worker return HalResult<T>::unsupported();
50*38e8c45fSAndroid Build Coastguard Worker }
51*38e8c45fSAndroid Build Coastguard Worker if (status.isOk()) {
52*38e8c45fSAndroid Build Coastguard Worker return HalResult<T>::ok(std::forward<T>(data));
53*38e8c45fSAndroid Build Coastguard Worker }
54*38e8c45fSAndroid Build Coastguard Worker return HalResult<T>::failed(std::string(status.toString8().c_str()));
55*38e8c45fSAndroid Build Coastguard Worker }
56*38e8c45fSAndroid Build Coastguard Worker
fromStatus(const binder::Status & status,T & data)57*38e8c45fSAndroid Build Coastguard Worker static HalResult<T> fromStatus(const binder::Status& status, T& data) {
58*38e8c45fSAndroid Build Coastguard Worker return HalResult<T>::fromStatus(status, T{data});
59*38e8c45fSAndroid Build Coastguard Worker }
60*38e8c45fSAndroid Build Coastguard Worker
fromStatus(const ndk::ScopedAStatus & ndkStatus,T && data)61*38e8c45fSAndroid Build Coastguard Worker static HalResult<T> fromStatus(const ndk::ScopedAStatus& ndkStatus, T&& data) {
62*38e8c45fSAndroid Build Coastguard Worker if (checkUnsupported(ndkStatus)) {
63*38e8c45fSAndroid Build Coastguard Worker return HalResult<T>::unsupported();
64*38e8c45fSAndroid Build Coastguard Worker }
65*38e8c45fSAndroid Build Coastguard Worker if (ndkStatus.isOk()) {
66*38e8c45fSAndroid Build Coastguard Worker return HalResult<T>::ok(std::forward<T>(data));
67*38e8c45fSAndroid Build Coastguard Worker }
68*38e8c45fSAndroid Build Coastguard Worker return HalResult<T>::failed(std::string(ndkStatus.getDescription()));
69*38e8c45fSAndroid Build Coastguard Worker }
70*38e8c45fSAndroid Build Coastguard Worker
fromStatus(const ndk::ScopedAStatus & ndkStatus,T & data)71*38e8c45fSAndroid Build Coastguard Worker static HalResult<T> fromStatus(const ndk::ScopedAStatus& ndkStatus, T& data) {
72*38e8c45fSAndroid Build Coastguard Worker return HalResult<T>::fromStatus(ndkStatus, T{data});
73*38e8c45fSAndroid Build Coastguard Worker }
74*38e8c45fSAndroid Build Coastguard Worker
75*38e8c45fSAndroid Build Coastguard Worker template <typename R>
fromReturn(hardware::Return<R> & ret,T && data)76*38e8c45fSAndroid Build Coastguard Worker static HalResult<T> fromReturn(hardware::Return<R>& ret, T&& data) {
77*38e8c45fSAndroid Build Coastguard Worker return ret.isOk() ? HalResult<T>::ok(std::forward<T>(data))
78*38e8c45fSAndroid Build Coastguard Worker : HalResult<T>::failed(ret.description());
79*38e8c45fSAndroid Build Coastguard Worker }
80*38e8c45fSAndroid Build Coastguard Worker
81*38e8c45fSAndroid Build Coastguard Worker template <typename R>
fromReturn(hardware::Return<R> & ret,T & data)82*38e8c45fSAndroid Build Coastguard Worker static HalResult<T> fromReturn(hardware::Return<R>& ret, T& data) {
83*38e8c45fSAndroid Build Coastguard Worker return HalResult<T>::fromReturn(ret, T{data});
84*38e8c45fSAndroid Build Coastguard Worker }
85*38e8c45fSAndroid Build Coastguard Worker
86*38e8c45fSAndroid Build Coastguard Worker template <typename R>
fromReturn(hardware::Return<R> & ret,hardware::power::V1_0::Status status,T && data)87*38e8c45fSAndroid Build Coastguard Worker static HalResult<T> fromReturn(hardware::Return<R>& ret, hardware::power::V1_0::Status status,
88*38e8c45fSAndroid Build Coastguard Worker T&& data) {
89*38e8c45fSAndroid Build Coastguard Worker return ret.isOk() ? HalResult<T>::fromStatus(status, std::forward<T>(data))
90*38e8c45fSAndroid Build Coastguard Worker : HalResult<T>::failed(ret.description());
91*38e8c45fSAndroid Build Coastguard Worker }
92*38e8c45fSAndroid Build Coastguard Worker
93*38e8c45fSAndroid Build Coastguard Worker template <typename R>
fromReturn(hardware::Return<R> & ret,hardware::power::V1_0::Status status,T & data)94*38e8c45fSAndroid Build Coastguard Worker static HalResult<T> fromReturn(hardware::Return<R>& ret, hardware::power::V1_0::Status status,
95*38e8c45fSAndroid Build Coastguard Worker T& data) {
96*38e8c45fSAndroid Build Coastguard Worker return HalResult<T>::fromReturn(ret, status, T{data});
97*38e8c45fSAndroid Build Coastguard Worker }
98*38e8c45fSAndroid Build Coastguard Worker
99*38e8c45fSAndroid Build Coastguard Worker // This will throw std::bad_optional_access if this result is not ok.
value()100*38e8c45fSAndroid Build Coastguard Worker const T& value() const { return mValue.value(); }
isOk()101*38e8c45fSAndroid Build Coastguard Worker bool isOk() const { return !mUnsupported && mValue.has_value(); }
isFailed()102*38e8c45fSAndroid Build Coastguard Worker bool isFailed() const { return !mUnsupported && !mValue.has_value(); }
isUnsupported()103*38e8c45fSAndroid Build Coastguard Worker bool isUnsupported() const { return mUnsupported; }
errorMessage()104*38e8c45fSAndroid Build Coastguard Worker const char* errorMessage() const { return mErrorMessage.c_str(); }
105*38e8c45fSAndroid Build Coastguard Worker
106*38e8c45fSAndroid Build Coastguard Worker private:
107*38e8c45fSAndroid Build Coastguard Worker std::optional<T> mValue;
108*38e8c45fSAndroid Build Coastguard Worker std::string mErrorMessage;
109*38e8c45fSAndroid Build Coastguard Worker bool mUnsupported;
110*38e8c45fSAndroid Build Coastguard Worker
HalResult(T && value)111*38e8c45fSAndroid Build Coastguard Worker explicit HalResult(T&& value)
112*38e8c45fSAndroid Build Coastguard Worker : mValue{std::move(value)}, mErrorMessage(), mUnsupported(false) {}
HalResult(std::string errorMessage,bool unsupported)113*38e8c45fSAndroid Build Coastguard Worker explicit HalResult(std::string errorMessage, bool unsupported)
114*38e8c45fSAndroid Build Coastguard Worker : mValue(), mErrorMessage(std::move(errorMessage)), mUnsupported(unsupported) {}
115*38e8c45fSAndroid Build Coastguard Worker };
116*38e8c45fSAndroid Build Coastguard Worker
117*38e8c45fSAndroid Build Coastguard Worker // Empty result
118*38e8c45fSAndroid Build Coastguard Worker template <>
119*38e8c45fSAndroid Build Coastguard Worker class HalResult<void> {
120*38e8c45fSAndroid Build Coastguard Worker public:
ok()121*38e8c45fSAndroid Build Coastguard Worker static HalResult<void> ok() { return HalResult(); }
failed(std::string msg)122*38e8c45fSAndroid Build Coastguard Worker static HalResult<void> failed(std::string msg) { return HalResult(std::move(msg)); }
unsupported()123*38e8c45fSAndroid Build Coastguard Worker static HalResult<void> unsupported() { return HalResult(/* unsupported= */ true); }
124*38e8c45fSAndroid Build Coastguard Worker
fromStatus(const binder::Status & status)125*38e8c45fSAndroid Build Coastguard Worker static HalResult<void> fromStatus(const binder::Status& status) {
126*38e8c45fSAndroid Build Coastguard Worker if (checkUnsupported(status)) {
127*38e8c45fSAndroid Build Coastguard Worker return HalResult<void>::unsupported();
128*38e8c45fSAndroid Build Coastguard Worker }
129*38e8c45fSAndroid Build Coastguard Worker if (status.isOk()) {
130*38e8c45fSAndroid Build Coastguard Worker return HalResult<void>::ok();
131*38e8c45fSAndroid Build Coastguard Worker }
132*38e8c45fSAndroid Build Coastguard Worker return HalResult<void>::failed(std::string(status.toString8().c_str()));
133*38e8c45fSAndroid Build Coastguard Worker }
134*38e8c45fSAndroid Build Coastguard Worker
fromStatus(const ndk::ScopedAStatus & ndkStatus)135*38e8c45fSAndroid Build Coastguard Worker static HalResult<void> fromStatus(const ndk::ScopedAStatus& ndkStatus) {
136*38e8c45fSAndroid Build Coastguard Worker if (ndkStatus.isOk()) {
137*38e8c45fSAndroid Build Coastguard Worker return HalResult<void>::ok();
138*38e8c45fSAndroid Build Coastguard Worker }
139*38e8c45fSAndroid Build Coastguard Worker if (checkUnsupported(ndkStatus)) {
140*38e8c45fSAndroid Build Coastguard Worker return HalResult<void>::unsupported();
141*38e8c45fSAndroid Build Coastguard Worker }
142*38e8c45fSAndroid Build Coastguard Worker return HalResult<void>::failed(ndkStatus.getDescription());
143*38e8c45fSAndroid Build Coastguard Worker }
144*38e8c45fSAndroid Build Coastguard Worker
145*38e8c45fSAndroid Build Coastguard Worker template <typename R>
fromReturn(hardware::Return<R> & ret)146*38e8c45fSAndroid Build Coastguard Worker static HalResult<void> fromReturn(hardware::Return<R>& ret) {
147*38e8c45fSAndroid Build Coastguard Worker return ret.isOk() ? HalResult<void>::ok() : HalResult<void>::failed(ret.description());
148*38e8c45fSAndroid Build Coastguard Worker }
149*38e8c45fSAndroid Build Coastguard Worker
isOk()150*38e8c45fSAndroid Build Coastguard Worker bool isOk() const { return !mUnsupported && !mFailed; }
isFailed()151*38e8c45fSAndroid Build Coastguard Worker bool isFailed() const { return !mUnsupported && mFailed; }
isUnsupported()152*38e8c45fSAndroid Build Coastguard Worker bool isUnsupported() const { return mUnsupported; }
errorMessage()153*38e8c45fSAndroid Build Coastguard Worker const char* errorMessage() const { return mErrorMessage.c_str(); }
154*38e8c45fSAndroid Build Coastguard Worker
155*38e8c45fSAndroid Build Coastguard Worker private:
156*38e8c45fSAndroid Build Coastguard Worker std::string mErrorMessage;
157*38e8c45fSAndroid Build Coastguard Worker bool mFailed;
158*38e8c45fSAndroid Build Coastguard Worker bool mUnsupported;
159*38e8c45fSAndroid Build Coastguard Worker
160*38e8c45fSAndroid Build Coastguard Worker explicit HalResult(bool unsupported = false)
mErrorMessage()161*38e8c45fSAndroid Build Coastguard Worker : mErrorMessage(), mFailed(false), mUnsupported(unsupported) {}
HalResult(std::string errorMessage)162*38e8c45fSAndroid Build Coastguard Worker explicit HalResult(std::string errorMessage)
163*38e8c45fSAndroid Build Coastguard Worker : mErrorMessage(std::move(errorMessage)), mFailed(true), mUnsupported(false) {}
164*38e8c45fSAndroid Build Coastguard Worker };
165*38e8c45fSAndroid Build Coastguard Worker } // namespace android::power
166