/* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include namespace android::power { static bool checkUnsupported(const ndk::ScopedAStatus& ndkStatus) { return ndkStatus.getExceptionCode() == EX_UNSUPPORTED_OPERATION || ndkStatus.getStatus() == STATUS_UNKNOWN_TRANSACTION; } static bool checkUnsupported(const binder::Status& status) { return status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION || status.transactionError() == UNKNOWN_TRANSACTION; } // Result of a call to the Power HAL wrapper, holding data if successful. template class HalResult { public: static HalResult ok(T&& value) { return HalResult(std::forward(value)); } static HalResult ok(T& value) { return HalResult::ok(T{value}); } static HalResult failed(std::string msg) { return HalResult(msg, /* unsupported= */ false); } static HalResult unsupported() { return HalResult("", /* unsupported= */ true); } static HalResult fromStatus(const binder::Status& status, T&& data) { if (checkUnsupported(status)) { return HalResult::unsupported(); } if (status.isOk()) { return HalResult::ok(std::forward(data)); } return HalResult::failed(std::string(status.toString8().c_str())); } static HalResult fromStatus(const binder::Status& status, T& data) { return HalResult::fromStatus(status, T{data}); } static HalResult fromStatus(const ndk::ScopedAStatus& ndkStatus, T&& data) { if (checkUnsupported(ndkStatus)) { return HalResult::unsupported(); } if (ndkStatus.isOk()) { return HalResult::ok(std::forward(data)); } return HalResult::failed(std::string(ndkStatus.getDescription())); } static HalResult fromStatus(const ndk::ScopedAStatus& ndkStatus, T& data) { return HalResult::fromStatus(ndkStatus, T{data}); } template static HalResult fromReturn(hardware::Return& ret, T&& data) { return ret.isOk() ? HalResult::ok(std::forward(data)) : HalResult::failed(ret.description()); } template static HalResult fromReturn(hardware::Return& ret, T& data) { return HalResult::fromReturn(ret, T{data}); } template static HalResult fromReturn(hardware::Return& ret, hardware::power::V1_0::Status status, T&& data) { return ret.isOk() ? HalResult::fromStatus(status, std::forward(data)) : HalResult::failed(ret.description()); } template static HalResult fromReturn(hardware::Return& ret, hardware::power::V1_0::Status status, T& data) { return HalResult::fromReturn(ret, status, T{data}); } // This will throw std::bad_optional_access if this result is not ok. const T& value() const { return mValue.value(); } bool isOk() const { return !mUnsupported && mValue.has_value(); } bool isFailed() const { return !mUnsupported && !mValue.has_value(); } bool isUnsupported() const { return mUnsupported; } const char* errorMessage() const { return mErrorMessage.c_str(); } private: std::optional mValue; std::string mErrorMessage; bool mUnsupported; explicit HalResult(T&& value) : mValue{std::move(value)}, mErrorMessage(), mUnsupported(false) {} explicit HalResult(std::string errorMessage, bool unsupported) : mValue(), mErrorMessage(std::move(errorMessage)), mUnsupported(unsupported) {} }; // Empty result template <> class HalResult { public: static HalResult ok() { return HalResult(); } static HalResult failed(std::string msg) { return HalResult(std::move(msg)); } static HalResult unsupported() { return HalResult(/* unsupported= */ true); } static HalResult fromStatus(const binder::Status& status) { if (checkUnsupported(status)) { return HalResult::unsupported(); } if (status.isOk()) { return HalResult::ok(); } return HalResult::failed(std::string(status.toString8().c_str())); } static HalResult fromStatus(const ndk::ScopedAStatus& ndkStatus) { if (ndkStatus.isOk()) { return HalResult::ok(); } if (checkUnsupported(ndkStatus)) { return HalResult::unsupported(); } return HalResult::failed(ndkStatus.getDescription()); } template static HalResult fromReturn(hardware::Return& ret) { return ret.isOk() ? HalResult::ok() : HalResult::failed(ret.description()); } bool isOk() const { return !mUnsupported && !mFailed; } bool isFailed() const { return !mUnsupported && mFailed; } bool isUnsupported() const { return mUnsupported; } const char* errorMessage() const { return mErrorMessage.c_str(); } private: std::string mErrorMessage; bool mFailed; bool mUnsupported; explicit HalResult(bool unsupported = false) : mErrorMessage(), mFailed(false), mUnsupported(unsupported) {} explicit HalResult(std::string errorMessage) : mErrorMessage(std::move(errorMessage)), mFailed(true), mUnsupported(false) {} }; } // namespace android::power