/* * 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; } RadioIndication& CallbackManager::indication() const { return *mRadioIndication; } 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