blob: 268a6e7d4da7150663a0c9b51d63c7903bdc5626 [file] [log] [blame]
/*
* Copyright (C) 2024 The LineageOS Project
*
* SPDX-License-Identifier: Apache-2.0
*/
#define LOG_TAG "SehRadioManager"
#include "aidl/SehRadioNetworkIndication.h"
#include "aidl/SehRadioNetworkResponse.h"
#include "hidl/SehRadioIndication.h"
#include "hidl/SehRadioResponse.h"
#include <thread>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <aidl/vendor/samsung/hardware/radio/network/ISehRadioNetwork.h>
#include <vendor/samsung/hardware/radio/2.2/ISehRadio.h>
using namespace std::chrono_literals;
using android::sp;
using android::String16;
using android::wp;
using android::base::GetIntProperty;
using android::base::ReadFileToString;
using android::base::Split;
using android::hardware::hidl_death_recipient;
using android::hardware::hidl_vec;
using android::hidl::base::V1_0::IBase;
using aidl::vendor::samsung::hardware::radio::network::ISehRadioNetwork;
using aidl::vendor::samsung::hardware::radio::network::implementation::SehRadioNetworkIndication;
using aidl::vendor::samsung::hardware::radio::network::implementation::SehRadioNetworkResponse;
using vendor::samsung::hardware::radio::V2_2::ISehRadio;
using vendor::samsung::hardware::radio::V2_2::SehVendorConfiguration;
using vendor::samsung::hardware::radio::V2_2::implementation::SehRadioIndication;
using vendor::samsung::hardware::radio::V2_2::implementation::SehRadioResponse;
using AidlVendorConfig = aidl::vendor::samsung::hardware::radio::network::SehVendorConfiguration;
template <typename C>
std::vector<C> LoadConfiguration(std::string data) {
std::vector<C> config;
for (std::string line : Split(data, "\n")) {
if (line == "\0") break;
std::vector<std::string> parts = Split(line, "=");
if (parts.size() == 2) {
config.push_back(C(parts[0], parts[1]));
LOG(INFO) << line;
} else {
LOG(ERROR) << "Invalid data: " << line;
}
}
return config;
}
bool died = false;
void onRILDDeath(void* cookie) {
if (died) return;
died = true;
LOG(ERROR) << "SehRadio died, sleeping for 10s before restarting";
std::this_thread::sleep_for(10000ms);
exit(1);
}
struct RilHidlDeathRecipient : public hidl_death_recipient {
void serviceDied(uint64_t cookie, const wp<IBase>& who) override { onRILDDeath((void*)cookie); }
};
static const auto gHalDeathRecipient = AIBinder_DeathRecipient_new(onRILDDeath);
static const auto gHidlHalDeathRecipient = sp<RilHidlDeathRecipient>::make();
int main() {
ABinderProcess_setThreadPoolMaxThreadCount(0);
ABinderProcess_startThreadPool();
std::string content;
if (!ReadFileToString("/vendor/etc/sehradiomanager.conf", &content)) {
LOG(WARNING) << "Could not read config, setting defaults";
content = "FW_READY=1";
}
int slotCount = GetIntProperty("ro.vendor.multisim.simslotcount", 1);
for (int slot = 1; slot <= slotCount; slot++) {
auto slotName = "slot" + std::to_string(slot);
auto aidlSvcName = std::string(ISehRadioNetwork::descriptor) + "/" + slotName;
if (AServiceManager_isDeclared(aidlSvcName.c_str())) {
auto config = LoadConfiguration<AidlVendorConfig>(content);
auto samsungIndication = ndk::SharedRefBase::make<SehRadioNetworkIndication>();
auto samsungResponse = ndk::SharedRefBase::make<SehRadioNetworkResponse>();
auto svc = ISehRadioNetwork::fromBinder(
ndk::SpAIBinder(AServiceManager_waitForService(aidlSvcName.c_str())));
svc->setResponseFunctions(samsungResponse, samsungIndication);
svc->setVendorSpecificConfiguration(0x4242, config);
AIBinder_linkToDeath(svc->asBinder().get(), gHalDeathRecipient, 0);
AIBinder_incStrong(svc->asBinder().get());
} else {
auto config = LoadConfiguration<SehVendorConfiguration>(content);
auto samsungIndication = sp<SehRadioIndication>::make();
auto samsungResponse = sp<SehRadioResponse>::make();
auto svc = ISehRadio::getService(slotName);
svc->setResponseFunction(samsungResponse, samsungIndication);
svc->setVendorSpecificConfiguration(0x3232, hidl_vec(config));
svc->linkToDeath(gHidlHalDeathRecipient, 0);
svc->incStrong(gHidlHalDeathRecipient.get());
}
LOG(INFO) << "Done (slot" << slot << ")";
}
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reach
}