diff --git a/radio/aidl/compat/libradiocompat/Android.bp b/radio/aidl/compat/libradiocompat/Android.bp index 9d568c4aa0..487d91b6b9 100644 --- a/radio/aidl/compat/libradiocompat/Android.bp +++ b/radio/aidl/compat/libradiocompat/Android.bp @@ -55,6 +55,7 @@ cc_library { "libutils", ], srcs: [ + "CallbackManager.cpp", "DriverContext.cpp", "RadioCompatBase.cpp", "RadioIndication.cpp", diff --git a/radio/aidl/compat/libradiocompat/CallbackManager.cpp b/radio/aidl/compat/libradiocompat/CallbackManager.cpp new file mode 100644 index 0000000000..c2eaed1959 --- /dev/null +++ b/radio/aidl/compat/libradiocompat/CallbackManager.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2021 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. + */ + +#include + +#include + +using namespace std::literals::chrono_literals; + +namespace android::hardware::radio::compat { + +/** + * How much setter thread will wait with setting response functions after the last + * setResponseFunctions call from the framework. Subsequent calls from the framework reset the + * clock, so this number should be larger than the longest time between setResponseFunctions calls + * from the framework. + * + * Real world measurements with Cuttlefish give <10ms delay between Modem and Data and <2ms delays + * between all others. + */ +static constexpr auto kDelayedSetterDelay = 100ms; + +CallbackManager::CallbackManager(std::shared_ptr context, sp hidlHal) + : mHidlHal(hidlHal), + mRadioResponse(sp::make(context)), + mRadioIndication(sp::make(context)), + mDelayedSetterThread(&CallbackManager::delayedSetterThread, this) {} + +CallbackManager::~CallbackManager() { + { + std::unique_lock lock(mDelayedSetterGuard); + mDelayedSetterDeadline = std::nullopt; + mDestroy = true; + mDelayedSetterCv.notify_all(); + } + mDelayedSetterThread.join(); +} + +RadioResponse& CallbackManager::response() const { + return *mRadioResponse; +} + +void CallbackManager::setResponseFunctionsDelayed() { + std::unique_lock lock(mDelayedSetterGuard); + mDelayedSetterDeadline = std::chrono::steady_clock::now() + kDelayedSetterDelay; + mDelayedSetterCv.notify_all(); +} + +void CallbackManager::delayedSetterThread() { + while (!mDestroy) { + std::unique_lock lock(mDelayedSetterGuard); + auto deadline = mDelayedSetterDeadline; + + // not waiting to set response functions + if (!deadline) { + mDelayedSetterCv.wait(lock); + continue; + } + + // waiting to set response functions, but not yet + if (*deadline > std::chrono::steady_clock::now()) { + mDelayedSetterCv.wait_until(lock, *deadline); + continue; + } + + mHidlHal->setResponseFunctions(mRadioResponse, mRadioIndication).assertOk(); + mDelayedSetterDeadline = std::nullopt; + } +} + +} // namespace android::hardware::radio::compat diff --git a/radio/aidl/compat/libradiocompat/RadioCompatBase.cpp b/radio/aidl/compat/libradiocompat/RadioCompatBase.cpp index 2364484f13..2a2d7a36e9 100644 --- a/radio/aidl/compat/libradiocompat/RadioCompatBase.cpp +++ b/radio/aidl/compat/libradiocompat/RadioCompatBase.cpp @@ -21,11 +21,10 @@ namespace android::hardware::radio::compat { RadioCompatBase::RadioCompatBase(std::shared_ptr context, sp hidlHal, - sp radioResponse, sp radioInd) + std::shared_ptr cbMgr) : mContext(context), mHal1_5(hidlHal), mHal1_6(V1_6::IRadio::castFrom(hidlHal)), - mRadioResponse(radioResponse), - mRadioIndication(radioInd) {} + mCallbackManager(cbMgr) {} } // namespace android::hardware::radio::compat diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp b/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp index d6399bfddf..5b22dbe6ca 100644 --- a/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp +++ b/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp @@ -88,7 +88,7 @@ ScopedAStatus RadioConfig::setResponseFunctions( mRadioConfigResponse->setResponseFunction(radioConfigResponse); mRadioConfigIndication->setResponseFunction(radioConfigIndication); - mHal1_1->setResponseFunctions(mRadioConfigResponse, mRadioConfigIndication); + mHal1_1->setResponseFunctions(mRadioConfigResponse, mRadioConfigIndication).assertOk(); return ok(); } diff --git a/radio/aidl/compat/libradiocompat/data/RadioData.cpp b/radio/aidl/compat/libradiocompat/data/RadioData.cpp index 91529c9af3..d2f368778f 100644 --- a/radio/aidl/compat/libradiocompat/data/RadioData.cpp +++ b/radio/aidl/compat/libradiocompat/data/RadioData.cpp @@ -32,7 +32,7 @@ namespace aidlCommon = ::aidl::android::hardware::radio; constexpr auto ok = &ScopedAStatus::ok; std::shared_ptr RadioData::respond() { - return mRadioResponse->dataCb(); + return mCallbackManager->response().dataCb(); } ScopedAStatus RadioData::allocatePduSessionId(int32_t serial) { @@ -129,16 +129,10 @@ ScopedAStatus RadioData::setInitialAttachApn(int32_t serial, const aidl::DataPro } ScopedAStatus RadioData::setResponseFunctions( - const std::shared_ptr& dataResponse, - const std::shared_ptr& dataIndication) { - LOG_CALL << dataResponse << ' ' << dataIndication; - - CHECK(dataResponse); - CHECK(dataIndication); - - mRadioResponse->setResponseFunction(dataResponse); - mRadioIndication->setResponseFunction(dataIndication); - + const std::shared_ptr& response, + const std::shared_ptr& indication) { + LOG_CALL << response << ' ' << indication; + mCallbackManager->setResponseFunctions(response, indication); return ok(); } diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h new file mode 100644 index 0000000000..f1a7b49c7a --- /dev/null +++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2021 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 "DriverContext.h" +#include "RadioIndication.h" +#include "RadioResponse.h" + +#include +#include + +#include + +namespace android::hardware::radio::compat { + +class CallbackManager { + sp mHidlHal; + sp mRadioResponse; + sp mRadioIndication; + + std::thread mDelayedSetterThread; + std::mutex mDelayedSetterGuard; + std::optional> mDelayedSetterDeadline + GUARDED_BY(mDelayedSetterGuard); + std::condition_variable mDelayedSetterCv GUARDED_BY(mDelayedSetterGuard); + bool mDestroy GUARDED_BY(mDelayedSetterGuard) = false; + + void setResponseFunctionsDelayed(); + void delayedSetterThread(); + + public: + CallbackManager(std::shared_ptr context, sp hidlHal); + ~CallbackManager(); + + RadioResponse& response() const; + + template + void setResponseFunctions(const std::shared_ptr& response, + const std::shared_ptr& indication) { + CHECK(response); + CHECK(indication); + + mRadioResponse->setResponseFunction(response); + mRadioIndication->setResponseFunction(indication); + setResponseFunctionsDelayed(); + } +}; + +} // namespace android::hardware::radio::compat diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioCompatBase.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioCompatBase.h index cd17541f69..eb22fff25d 100644 --- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioCompatBase.h +++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioCompatBase.h @@ -15,9 +15,8 @@ */ #pragma once +#include "CallbackManager.h" #include "DriverContext.h" -#include "RadioIndication.h" -#include "RadioResponse.h" #include @@ -30,12 +29,11 @@ class RadioCompatBase { sp mHal1_5; sp mHal1_6; - sp mRadioResponse; - sp mRadioIndication; + std::shared_ptr mCallbackManager; public: RadioCompatBase(std::shared_ptr context, sp hidlHal, - sp radioResponse, sp radioIndication); + std::shared_ptr cbMgr); }; } // namespace android::hardware::radio::compat diff --git a/radio/aidl/compat/libradiocompat/messaging/RadioMessaging.cpp b/radio/aidl/compat/libradiocompat/messaging/RadioMessaging.cpp index 650d1910ff..4d94e17e99 100644 --- a/radio/aidl/compat/libradiocompat/messaging/RadioMessaging.cpp +++ b/radio/aidl/compat/libradiocompat/messaging/RadioMessaging.cpp @@ -30,7 +30,7 @@ namespace aidl = ::aidl::android::hardware::radio::messaging; constexpr auto ok = &ScopedAStatus::ok; std::shared_ptr RadioMessaging::respond() { - return mRadioResponse->messagingCb(); + return mCallbackManager->response().messagingCb(); } ScopedAStatus RadioMessaging::acknowledgeIncomingGsmSmsWithPdu( // @@ -181,16 +181,10 @@ ScopedAStatus RadioMessaging::setGsmBroadcastConfig( } ScopedAStatus RadioMessaging::setResponseFunctions( - const std::shared_ptr& messagingResponse, - const std::shared_ptr& messagingIndication) { - LOG_CALL << messagingResponse << ' ' << messagingIndication; - - CHECK(messagingResponse); - CHECK(messagingIndication); - - mRadioResponse->setResponseFunction(messagingResponse); - mRadioIndication->setResponseFunction(messagingIndication); - + const std::shared_ptr& response, + const std::shared_ptr& indication) { + LOG_CALL << response << ' ' << indication; + mCallbackManager->setResponseFunctions(response, indication); return ok(); } diff --git a/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp b/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp index 3fff5ee317..d28b94041b 100644 --- a/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp +++ b/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp @@ -28,7 +28,7 @@ namespace aidl = ::aidl::android::hardware::radio::modem; constexpr auto ok = &ScopedAStatus::ok; std::shared_ptr RadioModem::respond() { - return mRadioResponse->modemCb(); + return mCallbackManager->response().modemCb(); } ScopedAStatus RadioModem::enableModem(int32_t serial, bool on) { @@ -133,16 +133,10 @@ ScopedAStatus RadioModem::setRadioPower(int32_t serial, bool powerOn, bool forEm } ScopedAStatus RadioModem::setResponseFunctions( - const std::shared_ptr& modemResponse, - const std::shared_ptr& modemIndication) { - LOG_CALL << modemResponse << ' ' << modemIndication; - - CHECK(modemResponse); - CHECK(modemIndication); - - mRadioResponse->setResponseFunction(modemResponse); - mRadioIndication->setResponseFunction(modemIndication); - + const std::shared_ptr& response, + const std::shared_ptr& indication) { + LOG_CALL << response << ' ' << indication; + mCallbackManager->setResponseFunctions(response, indication); return ok(); } diff --git a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp index 34e889db00..c94be63733 100644 --- a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp +++ b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp @@ -34,7 +34,7 @@ namespace aidl = ::aidl::android::hardware::radio::network; constexpr auto ok = &ScopedAStatus::ok; std::shared_ptr RadioNetwork::respond() { - return mRadioResponse->networkCb(); + return mCallbackManager->response().networkCb(); } ScopedAStatus RadioNetwork::getAllowedNetworkTypesBitmap(int32_t serial) { @@ -245,16 +245,10 @@ ScopedAStatus RadioNetwork::setNrDualConnectivityState(int32_t serial, } ScopedAStatus RadioNetwork::setResponseFunctions( - const std::shared_ptr& networkResponse, - const std::shared_ptr& networkIndication) { - LOG_CALL << networkResponse << ' ' << networkIndication; - - CHECK(networkResponse); - CHECK(networkIndication); - - mRadioResponse->setResponseFunction(networkResponse); - mRadioIndication->setResponseFunction(networkIndication); - + const std::shared_ptr& response, + const std::shared_ptr& indication) { + LOG_CALL << response << ' ' << indication; + mCallbackManager->setResponseFunctions(response, indication); return ok(); } diff --git a/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp b/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp index e72ac7ee99..b43f64f784 100644 --- a/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp +++ b/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp @@ -31,7 +31,7 @@ namespace aidl = ::aidl::android::hardware::radio::sim; constexpr auto ok = &ScopedAStatus::ok; std::shared_ptr RadioSim::respond() { - return mRadioResponse->simCb(); + return mCallbackManager->response().simCb(); } ScopedAStatus RadioSim::areUiccApplicationsEnabled(int32_t serial) { @@ -221,16 +221,10 @@ ScopedAStatus RadioSim::setFacilityLockForApp( // } ScopedAStatus RadioSim::setResponseFunctions( - const std::shared_ptr& simResponse, - const std::shared_ptr& simIndication) { - LOG_CALL << simResponse << ' ' << simIndication; - - CHECK(simResponse); - CHECK(simIndication); - - mRadioResponse->setResponseFunction(simResponse); - mRadioIndication->setResponseFunction(simIndication); - + const std::shared_ptr& response, + const std::shared_ptr& indication) { + LOG_CALL << response << ' ' << indication; + mCallbackManager->setResponseFunctions(response, indication); return ok(); } diff --git a/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp b/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp index 742fdbe844..7b1d1fa01e 100644 --- a/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp +++ b/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp @@ -31,7 +31,7 @@ namespace aidl = ::aidl::android::hardware::radio::voice; constexpr auto ok = &ScopedAStatus::ok; std::shared_ptr RadioVoice::respond() { - return mRadioResponse->voiceCb(); + return mCallbackManager->response().voiceCb(); } ScopedAStatus RadioVoice::acceptCall(int32_t serial) { @@ -238,16 +238,10 @@ ScopedAStatus RadioVoice::setPreferredVoicePrivacy(int32_t serial, bool enable) } ScopedAStatus RadioVoice::setResponseFunctions( - const std::shared_ptr& voiceResponse, - const std::shared_ptr& voiceIndication) { - LOG_CALL << voiceResponse << ' ' << voiceIndication; - - CHECK(voiceResponse); - CHECK(voiceIndication); - - mRadioResponse->setResponseFunction(voiceResponse); - mRadioIndication->setResponseFunction(voiceIndication); - + const std::shared_ptr& response, + const std::shared_ptr& indication) { + LOG_CALL << response << ' ' << indication; + mCallbackManager->setResponseFunctions(response, indication); return ok(); } diff --git a/radio/aidl/compat/service/service.cpp b/radio/aidl/compat/service/service.cpp index 6bcd4b0c61..7433feef17 100644 --- a/radio/aidl/compat/service/service.cpp +++ b/radio/aidl/compat/service/service.cpp @@ -19,13 +19,12 @@ #include #include #include +#include #include #include -#include #include #include #include -#include #include #include @@ -36,9 +35,8 @@ using namespace std::string_literals; static std::vector> gPublishedHals; template -static void publishRadioHal(std::shared_ptr context, - sp hidlHal, sp responseCb, - sp indicationCb, const std::string& slot) { +static void publishRadioHal(std::shared_ptr ctx, sp hidlHal, + std::shared_ptr cm, const std::string& slot) { const auto instance = T::descriptor + "/"s + slot; if (!AServiceManager_isDeclared(instance.c_str())) { LOG(INFO) << instance << " is not declared in VINTF (this may be intentional)"; @@ -46,7 +44,7 @@ static void publishRadioHal(std::shared_ptr context, } LOG(DEBUG) << "Publishing " << instance; - auto aidlHal = ndk::SharedRefBase::make(context, hidlHal, responseCb, indicationCb); + auto aidlHal = ndk::SharedRefBase::make(ctx, hidlHal, cm); gPublishedHals.push_back(aidlHal); const auto status = AServiceManager_addService(aidlHal->asBinder().get(), instance.c_str()); CHECK_EQ(status, STATUS_OK); @@ -59,17 +57,14 @@ static void publishRadio(std::string slot) { hidl_utils::linkDeathToDeath(radioHidl); auto context = std::make_shared(); + auto callbackMgr = std::make_shared(context, radioHidl); - auto responseCb = sp::make(context); - auto indicationCb = sp::make(context); - radioHidl->setResponseFunctions(responseCb, indicationCb).assertOk(); - - publishRadioHal(context, radioHidl, responseCb, indicationCb, slot); - publishRadioHal(context, radioHidl, responseCb, indicationCb, slot); - publishRadioHal(context, radioHidl, responseCb, indicationCb, slot); - publishRadioHal(context, radioHidl, responseCb, indicationCb, slot); - publishRadioHal(context, radioHidl, responseCb, indicationCb, slot); - publishRadioHal(context, radioHidl, responseCb, indicationCb, slot); + publishRadioHal(context, radioHidl, callbackMgr, slot); + publishRadioHal(context, radioHidl, callbackMgr, slot); + publishRadioHal(context, radioHidl, callbackMgr, slot); + publishRadioHal(context, radioHidl, callbackMgr, slot); + publishRadioHal(context, radioHidl, callbackMgr, slot); + publishRadioHal(context, radioHidl, callbackMgr, slot); } static void publishRadioConfig() {