Implement Minimal Telephony
Bug: 310710841
Test: atest CtsTelephonyTestCases
Test: atest CtsCarrierApiTestCases
Change-Id: Ia1a5567419871a9c64abb38f2f0e0951cad3fd7b
diff --git a/radio/aidl/minradio/libminradio/modem/RadioModem.cpp b/radio/aidl/minradio/libminradio/modem/RadioModem.cpp
new file mode 100644
index 0000000..1c1c5fa
--- /dev/null
+++ b/radio/aidl/minradio/libminradio/modem/RadioModem.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2023 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 <libminradio/modem/RadioModem.h>
+
+#include <libminradio/debug.h>
+#include <libminradio/response.h>
+
+#define RADIO_MODULE "Modem"
+
+namespace android::hardware::radio::minimal {
+
+using namespace ::android::hardware::radio::minimal::binder_printing;
+using ::aidl::android::hardware::radio::RadioIndicationType;
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::modem;
+namespace aidlRadio = ::aidl::android::hardware::radio;
+constexpr auto ok = &ScopedAStatus::ok;
+
+RadioModem::RadioModem(std::shared_ptr<SlotContext> context,
+ std::vector<aidlRadio::RadioTechnology> rats)
+ : RadioSlotBase(context) {
+ int32_t ratBitmap = 0;
+ for (auto rat : rats) {
+ CHECK(rat > aidlRadio::RadioTechnology::UNKNOWN) << "Invalid RadioTechnology: " << rat;
+ CHECK(rat <= aidlRadio::RadioTechnology::NR)
+ << ": " << rat << " not supported yet: "
+ << "please verify if RadioAccessFamily for this RadioTechnology is a bit-shifted 1";
+ ratBitmap |= 1 << static_cast<int32_t>(rat);
+ }
+ mRatBitmap = ratBitmap;
+}
+
+std::string RadioModem::getModemUuid() const {
+ // Assumes one modem per slot.
+ return std::format("com.android.minradio.modem{}", mContext->getSlotIndex());
+}
+
+std::string RadioModem::getSimUuid() const {
+ // Assumes one SIM per slot.
+ return std::format("com.android.minradio.sim{}", mContext->getSlotIndex());
+}
+
+ScopedAStatus RadioModem::enableModem(int32_t serial, bool on) {
+ LOG_NOT_SUPPORTED << on;
+ return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ScopedAStatus RadioModem::getBasebandVersion(int32_t serial) {
+ LOG_CALL;
+ respond()->getBasebandVersionResponse( //
+ noError(serial), std::format("libminradio V{}", IRadioModem::version));
+ return ok();
+}
+
+ScopedAStatus RadioModem::getDeviceIdentity(int32_t serial) {
+ LOG_AND_RETURN_DEPRECATED();
+}
+
+ScopedAStatus RadioModem::getHardwareConfig(int32_t serial) {
+ LOG_CALL;
+
+ aidl::HardwareConfig modem1Config{
+ .type = aidl::HardwareConfig::TYPE_MODEM,
+ .uuid = getModemUuid(),
+ .state = aidl::HardwareConfig::STATE_ENABLED,
+ .modem = {{
+ .rilModel = 0, // 0=single (one-to-one relationship for hw and ril daemon)
+ .rat = static_cast<aidlRadio::RadioTechnology>(mRatBitmap),
+ .maxVoiceCalls = 0,
+ .maxDataCalls = 1,
+ .maxStandby = 1,
+ }},
+ };
+
+ aidl::HardwareConfig sim1Config{
+ .type = aidl::HardwareConfig::TYPE_SIM,
+ .uuid = getSimUuid(),
+ .state = aidl::HardwareConfig::STATE_ENABLED,
+ .sim = {{
+ .modemUuid = getModemUuid(),
+ }},
+ };
+
+ respond()->getHardwareConfigResponse(noError(serial), {modem1Config, sim1Config});
+ return ok();
+}
+
+ScopedAStatus RadioModem::getModemActivityInfo(int32_t serial) {
+ LOG_CALL_IGNORED;
+ const aidl::ActivityStatsTechSpecificInfo generalActivityStats{
+ .txmModetimeMs = {0, 0, 0, 0, 0},
+ };
+ const aidl::ActivityStatsInfo info{
+ // idleModeTimeMs doesn't make sense for external modem, but the framework
+ // doesn't allow for ModemActivityInfo.isEmpty
+ .idleModeTimeMs = 1,
+ .techSpecificInfo = {generalActivityStats},
+ };
+ respond()->getModemActivityInfoResponse(noError(serial), info);
+ return ok();
+}
+
+ScopedAStatus RadioModem::getModemStackStatus(int32_t serial) {
+ LOG_CALL;
+ respond()->getModemStackStatusResponse(noError(serial), true);
+ return ok();
+}
+
+ScopedAStatus RadioModem::getRadioCapability(int32_t serial) {
+ LOG_CALL;
+ aidl::RadioCapability cap{
+ .session = 0,
+ .phase = aidl::RadioCapability::PHASE_FINISH,
+ .raf = mRatBitmap, // rafs are nothing else than rat masks
+ .logicalModemUuid = getModemUuid(),
+ .status = aidl::RadioCapability::STATUS_SUCCESS,
+ };
+ respond()->getRadioCapabilityResponse(noError(serial), cap);
+ return ok();
+}
+
+ScopedAStatus RadioModem::nvReadItem(int32_t serial, aidl::NvItem) {
+ LOG_AND_RETURN_DEPRECATED();
+}
+
+ScopedAStatus RadioModem::nvResetConfig(int32_t serial, aidl::ResetNvType resetType) {
+ LOG_CALL << resetType; // RELOAD is the only non-deprecated argument
+ respond()->nvResetConfigResponse(notSupported(serial));
+ return ok();
+}
+
+ScopedAStatus RadioModem::nvWriteCdmaPrl(int32_t serial, const std::vector<uint8_t>&) {
+ LOG_AND_RETURN_DEPRECATED();
+}
+
+ScopedAStatus RadioModem::nvWriteItem(int32_t serial, const aidl::NvWriteItem&) {
+ LOG_AND_RETURN_DEPRECATED();
+}
+
+ScopedAStatus RadioModem::requestShutdown(int32_t serial) {
+ LOG_NOT_SUPPORTED;
+ return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ScopedAStatus RadioModem::responseAcknowledgement() {
+ LOG_CALL_NOSERIAL;
+ return ok();
+}
+
+ScopedAStatus RadioModem::sendDeviceState(int32_t serial, aidl::DeviceStateType type, bool state) {
+ LOG_CALL_IGNORED << type << ' ' << state;
+ respond()->sendDeviceStateResponse(noError(serial));
+ return ok();
+}
+
+ScopedAStatus RadioModem::setRadioCapability(int32_t serial, const aidl::RadioCapability& rc) {
+ LOG_NOT_SUPPORTED << rc;
+ respond()->setRadioCapabilityResponse(notSupported(serial), {});
+ return ok();
+}
+
+ScopedAStatus RadioModem::setRadioPower(int32_t serial, bool powerOn, bool forEmergencyCall,
+ bool preferredForEmergencyCall) {
+ LOG_CALL_IGNORED << powerOn << " " << forEmergencyCall << " " << preferredForEmergencyCall;
+ respond()->setRadioPowerResponse(noError(serial));
+ indicate()->radioStateChanged(RadioIndicationType::UNSOLICITED,
+ powerOn ? aidl::RadioState::ON : aidl::RadioState::OFF);
+ return ok();
+}
+
+ScopedAStatus RadioModem::setResponseFunctions(
+ const std::shared_ptr<aidl::IRadioModemResponse>& response,
+ const std::shared_ptr<aidl::IRadioModemIndication>& indication) {
+ LOG_CALL_NOSERIAL << response << ' ' << indication;
+ CHECK(response);
+ CHECK(indication);
+ respond = mResponseTracker =
+ ndk::SharedRefBase::make<RadioModemResponseTracker>(ref<aidl::IRadioModem>(), response);
+ indicate = indication;
+
+ indicate()->rilConnected(RadioIndicationType::UNSOLICITED);
+ indicate()->radioStateChanged(RadioIndicationType::UNSOLICITED, aidl::RadioState::ON);
+
+ return ok();
+}
+
+} // namespace android::hardware::radio::minimal
diff --git a/radio/aidl/minradio/libminradio/modem/RadioModemResponseTracker.cpp b/radio/aidl/minradio/libminradio/modem/RadioModemResponseTracker.cpp
new file mode 100644
index 0000000..eb9bcf7
--- /dev/null
+++ b/radio/aidl/minradio/libminradio/modem/RadioModemResponseTracker.cpp
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+// see assert2_no_op in ResponseTracker.cpp
+#define __assert2 assert2_no_op
+#define __noreturn__ const
+#include <aidl/android/hardware/radio/modem/BnRadioModemResponse.h>
+#undef __assert2
+#undef __noreturn__
+#include <cassert>
+
+#include <libminradio/modem/RadioModemResponseTracker.h>
+
+#include <libminradio/debug.h>
+
+#define RADIO_MODULE "ModemResponse"
+
+namespace android::hardware::radio::minimal {
+
+using namespace ::android::hardware::radio::minimal::binder_printing;
+using ::aidl::android::hardware::radio::RadioResponseInfo;
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::modem;
+
+RadioModemResponseTracker::RadioModemResponseTracker(
+ std::shared_ptr<aidl::IRadioModem> req,
+ const std::shared_ptr<aidl::IRadioModemResponse>& resp)
+ : ResponseTracker(req, resp) {}
+
+ResponseTrackerResult<aidl::ImeiInfo> RadioModemResponseTracker::getImei() {
+ auto serial = newSerial();
+ if (auto status = request()->getImei(serial); !status.isOk()) return status;
+ return getResult<aidl::ImeiInfo>(serial);
+}
+
+ScopedAStatus RadioModemResponseTracker::getImeiResponse(
+ const RadioResponseInfo& info, const std::optional<aidl::ImeiInfo>& respData) {
+ LOG_CALL_RESPONSE << respData;
+ if (isTracked(info.serial)) return handle(info, respData.value_or(aidl::ImeiInfo{}));
+ return IRadioModemResponseDelegator::getImeiResponse(info, respData);
+}
+
+} // namespace android::hardware::radio::minimal