OpenHarmerny 短彩信之Framework系统源码解析

一年好景君须记,最是橙黄橘绿时。这篇文章主要讲述OpenHarmerny 短彩信之Framework系统源码解析相关的知识,希望能为你提供帮助。
作者:黄子轰
简介短彩信系统框架层,以OpenHarmerny SystemAbility 系统常驻服务,为上层提供JS API 接口,下层适配不同硬件厂商Modem。提供短彩信系统框架功能业务,提供短信收发和彩信编解码基础能力;主要功能有GSM/CDMA短信收发、短信PDU(Protocol data unit,协议数据单元)编解码、Wap Push接收处理 、小区广播接收、彩信通知、 彩信编解码和SIM卡短信记录增删改查等。
架构图

OpenHarmerny 短彩信之Framework系统源码解析

文章图片

?Framework框架图
短彩信服务通过safwk组件实现SystemAbility 注册、启动等相关接口;短彩信Framework由接口管理类、短信发送管理类、短信接收管理类,和彩信编解码工具类组成。
  • 接口管理类:SmsInterfaceManager 负责对外提供短信发送、SIM卡短信记录操作和配置相关接口,负责创建SmsSendManager 、SmsReceiveManager和smsMiscManager 对象。
  • 短信发送管理类: SmsSendManager创建GSM(GsmSmsSender) 、CDMA(CdmaSmsSender) 和网络策略管理(SmsNetworkPolicyManager)对象,并根据网络制式调度对应的GSM或CDMA对象发送短信。
  • 短信接收管理类: SmsReceiveManager 负责短信接收,监听来自RIL层的新短信信息;创建GSM(GsmSmsReceiveHandler) 和CDMA(CdmaSmsReceiveHandler) 对象;创建SmsWapPushHandler和SmsCellBroadcastHandler 对象。
  • 彩信编解码类:负责彩信PDU的编解码处理。
  • Misc管理类:负责Sim卡短信操作、小区广播配置、短信服务中心地址配置和默认卡槽配置等
代码结构Interfaces对外提供暴露接口,包括JS 接口定义,napi native C++ 的JS接口封装;frameworks 包括Native 接口定义和彩信编解码对外暴露的工具; sa_profile 提供SystemAbility 启动配置文件; sercives 包含了短信框架内部服务相关代码包括Gsm/Cdma Pdu 编解码工具和接收处理业务逻辑代码。
/base/telephony/sms_mms ├─ frameworks# 短彩信内部框架接口层 ├─ interfaces# 对外暴露的接口 │ ├─ innerkits │ └─ kits ├─ sa_profile# 启动配置文件 ├─ services# 服务内部代码 │ ├─ include# 头文件目录 │ ├─ cdma# CDMA制式源文件 │ └─ gsm# GSM制式源文件 ├─ test# 单元测试目录 └─ utils# 通用工具相关

参考文档路径:https://gitee.com/openharmony/telephony_sms_mms
发送短信时序图应用程序调用API发送短信,经过参数判断、鉴权、长短信拆分、PDU编码;添加到发送队列,调用RIL发送短信接口发送短信到接收端。并将发送状态返回应用调用者,完成一次短信发送过程。
  1. 上层应用调用发送短信的API JS接口,调用JS Napi 接口;
  2. JS Napi 调用Native 层C++ SendMessage 跨IPC 到SmsInterfaceManager对象;
  3. SmsInterfaceManager根据过滤策略来过滤掉短信和参数合法性检查;
  4. SmsInterfaceManager进行鉴权检查;
  5. SmsInterfaceManager调用TextBasedSmsDelivery或TextBasedSmsDelivery到SmsSendManager;
  6. SmsSendManager调用搜网服务来获取SIM卡和网络状态;
  7. GSM网络将创建GsmSmsSender,CDMA网络将创建CdmaSmsSender;
  8. GsmSmsSender或CdmaSmsSender将短信拆分并进行PDU编码然后放到队列中;
  9. 通过接口将短信发送到RIL层;
  10. 如果返回的状态失败将启动重发机制;
  11. 返回应用层发送的状态信息;
OpenHarmerny 短彩信之Framework系统源码解析

文章图片

?发送短信时序图
短信接收时序图
  1. SmsReceiveManager创建GsmSmsReceiveHandler和CdmaSmsReceiveHandler;
  2. GsmSmsReceiveHandler和CdmaSmsReceiveHandler分别注册事件到RIL层;
  3. RIL Adapter上报短信事件;
  4. GsmSmsReceiveHandler或CdmaSmsReceiveHandler调用SmsBaseMessage解析PDU数据。
  5. GsmSmsReceiveHandler和CdmaSmsReceiveHandler过滤无效短信;根据PDU头部信息将多段消息合并;
  6. 拦截黑名单短信;
  7. 将接收处理状态应答到RIL;
  8. 广播发送接收处理的短信信息到广播接收者;
OpenHarmerny 短彩信之Framework系统源码解析

文章图片

?接收短信时序图
代码分析 1.SmsService 启动
服务入口类 SmsService.cpp 继承safwk组件的SystemAblility类;由SA系统服务管理框架(samgr)拉起服务。采用telephony.cfg + profile.xml + libtel_sms_mms.z.so的方式由init进程执行对应的telephony.cfg文件拉起SmsService SystemAbility对应的telephony进程,并执行void SmsService::OnStart()
class SmsService : public SystemAbility, public SmsInterfaceStub DECLARE_DELAYED_SINGLETON(SmsService) DECLARE_SYSTEM_ABILITY(SmsService) // necessary public: void OnStart() override; void OnStop() override; private: constexpr static uint32_t CONNECT_SERVICE_WAIT_TIME = 2000; // ms bool Init(); bool registerToService_ = false; ServiceRunningState state_ = ServiceRunningState::STATE_NOT_START; ; // namespace Telephony // namespace OHOS

2.模块初始化
SmsService 服务启动后,调用OnStart() 函数;并创建服务内部类,初始化内部资源,包括SmsInterfaceManager、SmsSendManager、SmsReceiveManager 对象创建和初始化
void SmsService::OnStart()TELEPHONY_LOGI("SmsService::OnStart start service Enter."); if (state_ == ServiceRunningState::STATE_RUNNING) TELEPHONY_LOGE("msService has already started."); return; if (!Init()) TELEPHONY_LOGE("failed to init SmsService"); return; state_ = ServiceRunningState::STATE_RUNNING; TELEPHONY_LOGI("SmsService::OnStart start service Exit."); bool SmsService::Init()if (!registerToService_) WaitCoreServiceToInit(); return true; //等待核心服务完成初始化,并调用InitModule 初始化内部内部代码 void SmsService::WaitCoreServiceToInit()std::thread connectTask([& ]() while (true) TELEPHONY_LOGI("connect core service ..."); if (CoreManagerInner::GetInstance().IsInitFinished()) InitModule(); TELEPHONY_LOGI("SmsService Connection successful"); break; std::this_thread::sleep_for(milliseconds(CONNECT_SERVICE_WAIT_TIME)); ); connectTask.detach();

3.服务对外提供Native IPC 接口实现
SmsService.cpp 继承SmsInterfaceStub.cpp ;SmsInterfaceStub 是native层对外接口IPC服务端代码,继承了并实现了IPC 对外接口ISmsServiceInterface用于跨进程对外提供navtive C++ API 接口; OnRemoteRequest() 是服务端的请求入口,通过请求Id 遍历memberFuncMap_ 调用对应的实现方法
int SmsInterfaceStub::OnRemoteRequest(uint32_t code, MessageParcel & data, MessageParcel & reply, MessageOption & option) int32_t result = 0; std::u16string myDescripter = SmsInterfaceStub::GetDescriptor(); std::u16string remoteDescripter = data.ReadInterfaceToken(); if (myDescripter == remoteDescripter) auto itFunc = memberFuncMap_.find(code); if (itFunc != memberFuncMap_.end()) auto memberFunc = itFunc-> second; if (memberFunc != nullptr) (this-> *memberFunc)(data, reply, option); else TELEPHONY_LOGE("memberFunc is nullptr"); else TELEPHONY_LOGE("itFunc was not found"); else TELEPHONY_LOGE("descriptor checked fail"); return result; // 添加memberFuncMap 请求处理函数 SmsInterfaceStub::SmsInterfaceStub()memberFuncMap_[TEXT_BASED_SMS_DELIVERY] = & SmsInterfaceStub::OnSendSmsTextRequest; memberFuncMap_[DATA_BASED_SMS_DELIVERY] = & SmsInterfaceStub::OnSendSmsDataRequest; memberFuncMap_[SET_SMSC_ADDRESS] = & SmsInterfaceStub::OnSetSmscAddr; memberFuncMap_[GET_SMSC_ADDRESS] = & SmsInterfaceStub::OnGetSmscAddr; memberFuncMap_[ADD_SIM_MESSAGE] = & SmsInterfaceStub::OnAddSimMessage; memberFuncMap_[DEL_SIM_MESSAGE] = & SmsInterfaceStub::OnDelSimMessage; memberFuncMap_[UPDATE_SIM_MESSAGE] = & SmsInterfaceStub::OnUpdateSimMessage; memberFuncMap_[GET_ALL_SIM_MESSAGE] = & SmsInterfaceStub::OnGetAllSimMessages; memberFuncMap_[SET_CB_CONFIG] = & SmsInterfaceStub::OnSetCBConfig; memberFuncMap_[SET_DEFAULT_SMS_SLOT_ID] = & SmsInterfaceStub::OnSetDefaultSmsSlotId; memberFuncMap_[GET_DEFAULT_SMS_SLOT_ID] = & SmsInterfaceStub::OnGetDefaultSmsSlotId; memberFuncMap_[SPLIT_MESSAGE] = & SmsInterfaceStub::OnSplitMessage; memberFuncMap_[GET_SMS_SEGMENTS_INFO] = & SmsInterfaceStub::OnGetSmsSegmentsInfo; memberFuncMap_[GET_IMS_SHORT_MESSAGE_FORMAT] = & SmsInterfaceStub::OnGetImsShortMessageFormat; memberFuncMap_[IS_IMS_SMS_SUPPORTED] = & SmsInterfaceStub::OnIsImsSmsSupported; memberFuncMap_[HAS_SMS_CAPABILITY] = & SmsInterfaceStub::OnHasSmsCapability;

4.多卡方案实现
根据卡槽数量创建对应的SmsInterfaceManager 对象,并用slotSmsInterfaceManagerMap_管理;服务启动后会调用InitModule() 方法并根据卡槽数量创建多个SmsInterfaceManager每个SmsInterfaceManager对象代码每一个卡槽。
void SmsInterfaceStub::InitModule() static bool bInitModule = false; if (!bInitModule) bInitModule = true; std::lock_guard< std::mutex> lock(mutex_); for (int32_t slotId = 0; slotId < SIM_SLOT_COUNT; ++slotId) slotSmsInterfaceManagerMap_[slotId] = std::make_shared< SmsInterfaceManager> (slotId); if (slotSmsInterfaceManagerMap_[slotId] == nullptr) return; slotSmsInterfaceManagerMap_[slotId]-> InitInterfaceManager(); TELEPHONY_LOGI("SmsInterfaceStub InitModule slotId = %publicd",slotId);

5.短信发送流程
JS 发送短信接口 function sendMessage(options: SendMessageOptions): void, 位于sms_mms/interfaces/kits/js/@ohos.telephony.sms.d.ts 会调用位于sms_mms/frameworks/js/napi/src/napi_sms.cpp Napi 封装的SendMessage发送短信接口
static napi_value SendMessage(napi_env env, napi_callback_info info)size_t parameterCount = 1; napi_value parameters[1] = 0; napi_value thisVar = nullptr; void *data = https://www.songbingjia.com/android/nullptr; napi_get_cb_info(env, info, & parameterCount, parameters, & thisVar, & data); int32_t messageMatchResult = MatchSendMessageParameters(env, parameters, parameterCount); NAPI_ASSERT(env, messageMatchResult != MESSAGE_PARAMETER_NOT_MATCH,"type mismatch"); auto asyncContext = std::make_unique< SendMessageContext> ().release(); if (asyncContext == nullptr) std::string errorCode = std::to_string(napi_generic_failure); std::string errorMessage = "error at SendMessageContext is nullptr"; NAPI_CALL(env, napi_throw_error(env, errorCode.c_str(), errorMessage.c_str())); return nullptr; ParseMessageParameter(messageMatchResult, env, parameters[0], *asyncContext); napi_create_reference(env, thisVar, DEFAULT_REF_COUNT, & asyncContext-> thisVarRef); napi_value resourceName = nullptr; napi_create_string_utf8(env, "SendMessage", NAPI_AUTO_LENGTH, & resourceName); napi_create_async_work(env, nullptr, resourceName, NativeSendMessage, SendMessageCallback, (void *)asyncContext, & (asyncContext-> work)); napi_queue_async_work(env, asyncContext-> work); return NapiUtil::CreateUndefined(env);

SendMessage 最终会调用 sms_mms/frameworks/js/napi/src/napi_sms.cppActuallySendMessage函数; ActuallySendMessage 调用Native C++ 提供发送短信的单例类SmsServiceManagerClient 这个类是现实了鸿蒙系统IPC 通讯框架的客户端;用于C/S架构与SmsService 服务通讯。SmsServiceManagerClient SendMessage() 接口需要两个回调对象分别是SendCallback和DeliveryCallback 用于返回服务发送短信的状态结果回调
static bool ActuallySendMessage(napi_env env, SendMessageContext & parameter)std::unique_ptr< SendCallback> sendCallback = std::make_unique< SendCallback> (hasSendCallback, env, parameter.thisVarRef, parameter.sendCallbackRef); std::unique_ptr< DeliveryCallback> deliveryCallback = std::make_unique< DeliveryCallback> ( hasDeliveryCallback, env, parameter.thisVarRef, parameter.deliveryCallbackRef); //文本类型的短信 if (parameter.messageType == TEXT_MESSAGE_PARAMETER_MATCH) int32_t sendResult = DelayedSingleton< SmsServiceManagerClient> ::GetInstance()-> SendMessage( parameter.slotId, parameter.destinationHost, parameter.serviceCenter, parameter.textContent, sendCallback.release(), deliveryCallback.release()); TELEPHONY_LOGI("NativeSendMessage SendTextMessage execResult = %publicd", sendResult); if (sendResult == ERROR_NONE) return true; else return false; // 数据类型的短信 else if (parameter.messageType == RAW_DATA_MESSAGE_PARAMETER_MATCH) if (parameter.rawDataContent.size() > 0) uint16_t arrayLength = static_cast< uint16_t> (parameter.rawDataContent.size()); int32_t sendResult = DelayedSingleton< SmsServiceManagerClient> ::GetInstance()-> SendMessage(parameter.slotId, parameter.destinationHost, parameter.serviceCenter, parameter.destinationPort, & parameter.rawDataContent[0], arrayLength, sendCallback.release(), deliveryCallback.release()); TELEPHONY_LOGI("NativeSendMessage SendRawDataMessage execResult = %publicd", sendResult); if (sendResult == ERROR_NONE) return true; else return false; return false; //Native C++ 发送短信接口函数 int32_t SmsServiceManagerClient::SendMessage(int32_t slotId, const std::u16string desAddr, const std::u16string scAddr, const std::u16string text, const sptr< ISendShortMessageCallback> & callback, const sptr< IDeliveryShortMessageCallback> & deliveryCallback)if (InitSmsServiceProxy()) smsServiceInterface_-> SendMessage(slotId, desAddr, scAddr, text, callback, deliveryCallback); TELEPHONY_LOGI("execute SendMessage\\n"); return ERROR_NONE; return ERROR_SERVICE_UNAVAILABLE; // InitSmsServiceProxy 用于初始化与SmsService IPC 通许连接工作 bool SmsServiceManagerClient::InitSmsServiceProxy()if (smsServiceInterface_ == nullptr) std::lock_guard< std::mutex> lock(mutex_); sptr< ISystemAbilityManager> systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (!systemAbilityManager) TELEPHONY_LOGE(" Get system ability mgr failed."); return false; sptr< IRemoteObject> remoteObject = systemAbilityManager-> GetSystemAbility(TELEPHONY_SMS_MMS_SYS_ABILITY_ID); if (!remoteObject) TELEPHONY_LOGE("Get SMS Service Failed."); return false; smsServiceInterface_ = iface_cast< ISmsServiceInterface> (remoteObject); if ((!smsServiceInterface_) || (!smsServiceInterface_-> AsObject())) TELEPHONY_LOGE("Get SMS Service Proxy Failed."); return false; recipient_ = new SmsServiceInterfaceDeathRecipient(); if (!recipient_) TELEPHONY_LOGE("Failed to create death Recipient ptr SmsServiceInterfaceDeathRecipient!"); return false; smsServiceInterface_-> AsObject()-> AddDeathRecipient(recipient_); return true;

通过SmsServiceManagerClient 的SendMessage 调用最终会通过IPC 调用到 sms_mms/services/sms_interfacestub.cpp 的OnRemoteRequest() 函数,通过定义的codeId 从memberFuncMap 遍历出OnSendSmsTextRequest() 方法并执行;OnSendSmsTextRequest主要是IPC数据的反序列号并调用SmsService 实现的SendMessage()方法
void SmsInterfaceStub::OnSendSmsTextRequest(MessageParcel & data, MessageParcel & reply, MessageOption & option)int32_t result = 0; sptr< ISendShortMessageCallback> sendCallback = nullptr; sptr< IDeliveryShortMessageCallback> deliveryCallback = nullptr; int32_t slotId = data.ReadInt32(); u16string desAddr = data.ReadString16(); u16string scAddr = data.ReadString16(); u16string text = data.ReadString16(); sptr< IRemoteObject> remoteSendCallback = data.ReadRemoteObject(); sptr< IRemoteObject> remoteDeliveryCallback = data.ReadRemoteObject(); if (remoteSendCallback != nullptr) sendCallback = iface_cast< ISendShortMessageCallback> (remoteSendCallback); if (remoteDeliveryCallback != nullptr) deliveryCallback = iface_cast< IDeliveryShortMessageCallback> (remoteDeliveryCallback); TELEPHONY_LOGI("MessageID::TEXT_BASED_SMS_DELIVERY %publicd", slotId); SendMessage(slotId, desAddr, scAddr, text, sendCallback, deliveryCallback); reply.WriteInt32(result); void SmsService::SendMessage(int32_t slotId, const u16string desAddr, const u16string scAddr, const u16string text, const sptr< ISendShortMessageCallback> & sendCallback, const sptr< IDeliveryShortMessageCallback> & deliveryCallback)// 权限校验 if (!TelephonyPermission::CheckPermission(Permission::SEND_MESSAGES)) SmsSender::SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN); TELEPHONY_LOGE("Check Permission Failed, No Has Telephony Send Messages Permisson."); return; // 获取对应slotId 对应的SmsInterfaceManager 对象 std::shared_ptr< SmsInterfaceManager> interfaceManager = GetSmsInterfaceManager(slotId); ............ interfaceManager-> TextBasedSmsDelivery(StringUtils::ToUtf8(desAddr), StringUtils::ToUtf8(scAddr), StringUtils::ToUtf8(text), sendCallback, deliveryCallback);

SmsInterfaceManager 对象TextBasedSmsDelivery 用于发送短信接口调用SmsSendManager对象的 TextBasedSmsDelivery();根据当前sloidId 卡的网络状态 调用Gsm 或者Cdma 来进一步发送短信处理
void SmsSendManager::TextBasedSmsDelivery(const string & desAddr, const string & scAddr, const string & text, const sptr< ISendShortMessageCallback> & sendCallback, const sptr< IDeliveryShortMessageCallback> & deliveryCallback)......此处省略..... NetWorkType netWorkType = networkManager_-> GetNetWorkType(); TELEPHONY_LOGI("netWorkType = %publicd.", netWorkType); if (netWorkType == NetWorkType::NET_TYPE_GSM) gsmSmsSender_-> TextBasedSmsDelivery(desAddr, scAddr, text, sendCallback, deliveryCallback); else if (netWorkType == NetWorkType::NET_TYPE_CDMA) cdmaSmsSender_-> TextBasedSmsDelivery(desAddr, scAddr, text, sendCallback, deliveryCallback); else SmsSender::SendResultCallBack( sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_SERVICE_UNAVAILABLE); TELEPHONY_LOGI("network unknown send error.");

Gsm或者Cdma 长短信分段和PDU的编码过程,入口函数GsmSmsSender::TextBasedSmsDelivery()或者CdmaSmsSender::TextBasedSmsDelivery() 并构造SmsSendIndexer 对象添加到Map队列中,并调用CoreService 提供的发送短信接口发送,等待发送结果;拿Gsm制式的来分析,代码如下
void GsmSmsSender::TextBasedSmsDelivery(const string & desAddr, const string & scAddr, const string & text, const sptr< ISendShortMessageCallback> & sendCallback, const sptr< IDeliveryShortMessageCallback> & deliveryCallback)bool isMore = false; bool isStatusReport = false; int ret = 0; int headerCnt; int cellsInfosSize; unsigned char msgRef8bit; SmsCodingScheme codingType; GsmSmsMessage gsmSmsMessage; std::vector< struct SplitInfo> cellsInfos; // 长短信分段拆分 gsmSmsMessage.SplitMessage(cellsInfos, text, CheckForce7BitEncodeType(), codingType); isStatusReport = (deliveryCallback == nullptr) ? false : true; std::shared_ptr< struct SmsTpdu> tpdu = gsmSmsMessage.CreateDefaultSubmitSmsTpdu(desAddr, scAddr, text, isStatusReport, codingType); ....部分代码省略......... std::unique_lock< std::mutex> lock(mutex_); for (int i = 0; i < cellsInfosSize; i++) std::shared_ptr< SmsSendIndexer> indexer = nullptr; std::string segmentText; segmentText.append((char *)(cellsInfos[i].encodeData.data()), cellsInfos[i].encodeData.size()); ....部分代码省略......... // 编码PDU std::shared_ptr< struct EncodeInfo> encodeInfo = gsmSmsMessage.GetSubmitEncodeInfo(scAddr, isMore); if (encodeInfo == nullptr) SendResultCallBack(indexer, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN); TELEPHONY_LOGE("create encodeInfo encodeInfo nullptr error."); continue; // 构造填充SmsSendIndexer对象 SetSendIndexerInfo(indexer, encodeInfo, msgRef8bit); indexer-> SetUnSentCellCount(unSentCellCount); indexer-> SetHasCellFailed(hasCellFailed); SendSmsToRil(indexer); //判断是否是IMS网络域,调用CoreService 不同的接口进行发送 void GsmSmsSender::SendSmsToRil(const shared_ptr< SmsSendIndexer> & smsIndexer)....部分代码省略......... GsmSimMessageParam smsData; smsData.refId = refId; smsData.smscPdu = StringUtils::StringToHex(smsIndexer-> GetEncodeSmca()); if (!isImsNetDomain_ & & smsIndexer-> GetPsResendCount() == 0) uint8_t tryCount = smsIndexer-> GetCsResendCount(); if (tryCount > 0) smsIndexer-> UpdatePduForResend(); smsData.pdu = StringUtils::StringToHex(smsIndexer-> GetEncodePdu()); if (tryCount == 0 & & smsIndexer-> GetHasMore()) TELEPHONY_LOGI("SendSmsMoreMode pdu len = %publiczu", smsIndexer-> GetEncodePdu().size()); CoreManagerInner::GetInstance().SendSmsMoreMode(slotId_, RadioEvent::RADIO_SEND_SMS_EXPECT_MORE, smsData, shared_from_this()); else TELEPHONY_LOGI("SendSms pdu len = %publiczu", smsIndexer-> GetEncodePdu().size()); CoreManagerInner::GetInstance().SendGsmSms(slotId_, RadioEvent::RADIO_SEND_SMS, smsData, shared_from_this()); else TELEPHONY_LOGI("ims network domain send sms interface.!"); smsIndexer-> SetPsResendCount(smsIndexer-> GetPsResendCount() + 1); smsData.pdu = StringUtils::StringToHex(smsIndexer-> GetEncodePdu()); if (smsIndexer-> GetHasMore()) CoreManagerInner::GetInstance().SendSmsMoreMode(slotId_, RadioEvent::RADIO_SEND_SMS_EXPECT_MORE, smsData, shared_from_this()); else CoreManagerInner::GetInstance().SendGsmSms(slotId_, RadioEvent::RADIO_SEND_SMS, smsData, shared_from_this());

6.短信下发到core_service、ril_adapter源码分析
参考文档路径:https://gitee.com/openharmony/telephony_core_service
https://gitee.com/openharmony/telephony_ril_adapter
由于core_service服务和短彩信服务在同一个进程中,所以我们通过CoreManagerInner::GetInstance()来获取核心服务的单例对象,调用SendGsmSms或SendCdmaSms函数发送短信。
int32_t CoreManagerInner::SendGsmSms(int32_t slotId, int32_t eventId, GsmSimMessageParam & gsmMessage, const std::shared_ptr< AppExecFwk::EventHandler> & handler)if (telRilManager_ == nullptr) TELEPHONY_LOGE("telRilManager is null!"); return TELEPHONY_ERR_LOCAL_PTR_NULL; AppExecFwk::InnerEvent::Pointer response = AppExecFwk::InnerEvent::Get(eventId, gsmMessage.refId); response-> SetOwner(handler); return telRilManager_-> SendGsmSms(slotId, gsmMessage.smscPdu, gsmMessage.pdu, response);

SendGsmSms函数将eventId、refId和handler对象封装到response对象中再转发到telRilManager的SendGsmSms函数。
/*********************** TelRilNetwork end ****************************/ /*********************** TelRilSms start ******************************/ int32_t TelRilManager::SendGsmSms( int32_t slotId, std::string smscPdu, std::string pdu, const AppExecFwk::InnerEvent::Pointer & response)return TaskSchedule(response, "TelRilSms", GetTelRilSms(slotId), & TelRilSms::SendGsmSms, smscPdu, pdu);

TelRilManager::SendGsmSms里面只有一个TaskSchedule函数调用,其实TaskSchedule是个模板函数,就是为了统一下所有任务调用。
template< typename ResponsePtr, typename ClassTypePtr, typename FuncType, typename... ParamTypes> inline int32_t TaskSchedule(ResponsePtr & _result, const std::string _module, ClassTypePtr & _obj, FuncType & & _func, ParamTypes & & ..._args) constif (_func != nullptr) // The reason for using native member function access here is to //remove std::unique_ptr to prevent copying. // The reason for not directly using pointers to access member functions is: //_obj is a smart pointer, not a native pointer. return (_obj.*(_func))(std::forward< ParamTypes> (_args)..., _result); else TELEPHONY_LOGE("%publics - this %publicp: %publics", _module.c_str(), & _obj, "null pointer"); return HRIL_ERR_NULL_POINT;

这个模板函数最终会调用TelRilSms::SendGsmSms并且将response插入到函数的最后一个参数中。
int32_t TelRilSms::SendGsmSms(std::string & smsPdu, std::string & pdu, const AppExecFwk::InnerEvent::Pointer & response)std::shared_ptr< TelRilRequest> telRilRequest = CreateTelRilRequest(HREQ_SMS_SEND_GSM_SMS, response); if (telRilRequest == nullptr) TELEPHONY_LOGE("telRilRequest is nullptr"); return TELEPHONY_ERR_LOCAL_PTR_NULL; TELEPHONY_LOGI("telRilRequest-> serialId_:%publicd", telRilRequest-> serialId_); MessageParcel data; data.WriteInt32(slotId_); GsmSmsMessageInfo mGsmSmsMessageInfo = ConstructGsmSendSmsRequestLinkList(smsPdu, pdu); mGsmSmsMessageInfo.serial = telRilRequest-> serialId_; mGsmSmsMessageInfo.Marshalling(data); MessageParcel reply; OHOS::MessageOption option = OHOS::MessageOption::TF_ASYNC; if (cellularRadio_-> SendRequest(HREQ_SMS_SEND_GSM_SMS, data, reply, option)) TELEPHONY_LOGE("cellularRadio_-> SendRequest fail"); return TELEPHONY_ERR_SUCCESS;

在TelRilSms::SendGsmSms函数中我们调用CreateTelRilRequest来将serialId、response和HREQ_SMS_SEND_GSMSMS等保存到一个map中方便我们后续将短信发送的状态上报到短彩信服务中。下面MessageParcel data将pdu、smscpdu、serialId序列化到data中,最后通过cellularRadio-> SendRequest通过IPC将数据发送到ril_adapter服务中。
进入Ril层我们分析services\\hril_hdf\\src\\hril_hdf.c这个文件,hril_hdf.c是ril_adapter层加载vendor库、注册发送和响应函数、启动读写线程、事件调度的入口。
static int32_t RilAdapterDispatch( struct HdfDeviceIoClient *client, int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply)int32_t ret; static pthread_mutex_t dispatchMutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(& dispatchMutex); TELEPHONY_LOGI("RilAdapterDispatch cmd:%publicd", cmd); ret = DispatchRequest(cmd, data); pthread_mutex_unlock(& dispatchMutex); return ret; static struct IDeviceioservice g_rilAdapterService = .Dispatch = RilAdapterDispatch, .Open = NULL, .Release = NULL, ;

我们看到.Dispatch = RilAdapterDispatch说明事件调度入口就是进入RilAdapterDispatch函数。RilAdapterDispatch函数里面主要加互斥锁调用DispatchRequest(cmd, data)这个事件分发最终调用到hril_sms文件的HRilSms::SendGsmSms函数。
int32_t HRilSms::SendGsmSms(struct HdfSBuf *data)struct GsmSmsMessageInfo message; MessageParcel *parcel = nullptr; const int32_t COUNT_STRINGS_VALUE = https://www.songbingjia.com/android/2; if (SbufToParcel(data, & parcel)) TELEPHONY_LOGE("RilAdapter failed to do SbufToParcel"); return HRIL_ERR_INVALID_PARAMETER; if (parcel == nullptr) TELEPHONY_LOGE("parcel int32_t SendGsmSms is nullptr!"); return HRIL_ERR_INVALID_PARAMETER; if (!message.ReadFromParcel(*parcel)) TELEPHONY_LOGE("RilAdapter failed to do ReadFromParcel!"); return HRIL_ERR_INVALID_PARAMETER; return RequestWithStrings( message.serial, HREQ_SMS_SEND_GSM_SMS, COUNT_STRINGS_VALUE, message.smscPdu.c_str(), message.pdu.c_str());

HRilSms::SendGsmSms函数将core_service发送下来的数据反序列化到struct GsmSmsMessageInfo message中,最后调用RequestWithStrings函数。最后将数据转发到vendor库的at_sms.c文件的ReqSendGsmSms函数
void ReqSendGsmSms(const ReqDataInfo *requestInfo, const char *const *data, size_t dataLen)//省略非核心代码 //向modem发送AT +CMGS指令 err = SendCommandSmsLock(cmd, smsPdu, "+CMGS:", 0, & responseInfo); if (err != 0 || (responseInfo != NULL & & !responseInfo-> success)) HandlerSmsResult(& response, & reportInfo, requestInfo, & err, responseInfo); return; //获取发送后状态 HandleResult(& err, result, responseInfo, & response); reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0); //上报发送后的状态 OnSmsReport(GetSlotId(requestInfo), reportInfo, (const uint8_t *)& response, sizeof(HRilSmsResponse)); FreeResponseInfo(responseInfo);

ReqSendGsmSms函数将AT指令下发到modem并且将发送的状态上报。上报流程和下发流程类似不做具体分析。
7.短信上报ril_adapter、core_service源码分析
首先打开vendor_adapter.c我们可以看到EventListeners函数。
static void EventListeners(void)int32_t waitNextTryTime = SLEEP_TIME; const char *devicePath = DEVICE_PATH; char atTtyPath[PARAMETER_SIZE] = 0; usleep(DELAY_WAIT_MS); // Prevent slow loading of system properties. if (GetParameter(AT_TTY_PATH, "", atTtyPath, PARAMETER_SIZE) > 0) devicePath = atTtyPath; TELEPHONY_LOGI("opening AT interface %publics", devicePath); AtSetOnUnusual(AtOnUnusual); for (; ; ) while (g_fd < 0) if (devicePath != NULL) g_fd = open(devicePath, O_RDWR); if (g_fd > = 0 & & !memcmp(devicePath, DEVICE_PATH_DEFAULT, sizeof(DEVICE_PATH_DEFAULT) - 1)) struct termios ios; tcgetattr(g_fd, & ios); ios.c_lflag = 0; tcsetattr(g_fd, TCSANOW, & ios); if (g_fd < 0) TELEPHONY_LOGE("ril vendorlib,opening AT interface. retrying..."); sleep(waitNextTryTime); g_atStatus = 0; int32_t ret = ATStartReadLoop(g_fd, OnNotifyOps); if (ret < 0) TELEPHONY_LOGE("AtRead error %d\\n", ret); return; ModemInit(); sleep(1); WaitAtClose();

EventListeners中主要是ATStartReadLoop函数将创建一个线程读取modem上报的内容,在OnNotifyOps中短信上报内容是AT +CMT指令。将调用到OnSmsReport函数。
void OnNotifyOps(const char *s, const char *smsPdu)//省略非核心代码 if (IsCallNoticeCmd(s)) CallReportInfoProcess(s); else if (ReportStrWith(s, "+CMT:")) HRilSmsResponse smsResponse = ; smsResponse.pdu = (char *)smsPdu; reportInfo.notifyId = HNOTI_SMS_NEW_SMS; OnSmsReport(GetSlotId(NULL), reportInfo, (const uint8_t *)& smsResponse, strlen(smsResponse.pdu)); //省略非核心代码

OnReport最终会调到hril_manager.c中的OnSmsReport函数
void HRilManager::OnSmsReport( int32_t slotId, const ReportInfo *reportInfo, const uint8_t *response, size_t responseLen)OnReport(hrilSms_, slotId, reportInfo, response, responseLen);

在OnReport函数中查找notiMemberFuncMap的HNOTI_SMS_NEW_SMS对应的函数指针。
// Notification notiMemberFuncMap_[HNOTI_SMS_NEW_SMS] = & HRilSms::NewSmsNotify; notiMemberFuncMap_[HNOTI_SMS_NEW_CDMA_SMS] = & HRilSms::NewCdmaSmsNotify; notiMemberFuncMap_[HNOTI_SMS_STATUS_REPORT] = & HRilSms::SmsStatusReportNotify; notiMemberFuncMap_[HNOTI_SMS_NEW_SMS_STORED_ON_SIM] = & HRilSms::NewSmsStoredOnSimNotify; notiMemberFuncMap_[HNOTI_CB_CONFIG_REPORT] = & HRilSms::CBConfigNotify; int32_t HRilSms::NewSmsNotify(int32_t indType, const HRilErrNumber e, const void *response, size_t responseLen)//省略部分代码 std::unique_ptr< MessageParcel> parcel = std::make_unique< MessageParcel> (); if (parcel == nullptr) TELEPHONY_LOGE("parcel in NewSmsNotify is nullptr!"); return HRIL_ERR_GENERIC_FAILURE; if (!parcel-> WriteInterfaceToken(HRIL_INTERFACE_TOKEN)) TELEPHONY_LOGE("write interface token failed."); return HRIL_ERR_GENERIC_FAILURE; struct HdfSBuf *dataSbuf = ParcelToSbuf(parcel.get()); HRilResponseHeadInfo headInfo = 0; headInfo.slotId = GetSlotId(); headInfo.type = (HRilResponseTypes)indType; if (!HdfSbufWriteUnpadBuffer(dataSbuf, (const uint8_t *)& headInfo, sizeof(HRilResponseHeadInfo))) HdfSbufRecycle(dataSbuf); return HRIL_ERR_GENERIC_FAILURE; smsMessageInfo.Marshalling(*parcel.get()); indType = static_cast< int32_t> (ConvertIntToRadioNoticeType(indType)); //通过IPC上报数据到core_service if (DataSbuf(dataSbuf, indType) == HRIL_ERR_GENERIC_FAILURE) TELEPHONY_LOGE("DataSbuf in NewSmsNotify is failed!"); return HRIL_ERR_GENERIC_FAILURE; return HRIL_ERR_SUCCESS;

在NewSmsNotify函数我们主要将短信PDU、ID、类型序列化通过IPC上传到core_service。core_service在收到上报数据也只是转发到短彩信服务,这部分内容自行分析即可。
8.JS 发送短信示例
import sms from "@ohos.telephony.sms"; let msg: SendMessageOptions = slotId: 0, destinationHost: 123xxxxxxxx, content: 这是一封短信, sendCallback: (err, data) => if (err) // 接口调用失败,err非空 console.error(`failed to send message because $err.message`); return; // 接口调用成功,err为空 console.log(`success to send message: $data.result`); // 调用接口 sms.sendMessage(msg);

更多原创内容请关注:深开鸿技术团队入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。
想了解更多关于鸿蒙的内容,请访问:
51CTO 开源基础软件社区
https://ost.51cto.com/#bkwz
::: hljs-center
OpenHarmerny 短彩信之Framework系统源码解析

文章图片

【OpenHarmerny 短彩信之Framework系统源码解析】:::

    推荐阅读