Android13 Telephony从App到RILD的交互机制

Android13 Telephony 从App到RILD的交互机制概要

适用于Android 13版本,其它版本可能有差异
1.Android phone入口
1.1 PhoneApp
代码路径
packages\services\Telephony
phone进程是各个功能模块开始的地方
<manifest xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:androidprv=“http://schemas.android.com/apk/prv/res/android”
package=“com.android.phone”
coreApp=“true”
android:sharedUserId=“android.uid.phone”
android:sharedUserLabel=“@string/phoneAppLabel”

<application android:name=“PhoneApp”
android:persistent=“true”

PhoneApp(telephony的Application)是最初的代码入口
public void onCreate() {
if (UserHandle.myUserId() == 0) {
// We are running as the primary user, so should bring up the
// global phone state.
mPhoneGlobals = new PhoneGlobals(this);
mPhoneGlobals.onCreate();

        TelecomAccountRegistry.getInstance(this).setupOnBoot();
    }
}

1.2 PhoneGlobals
在PhoneGlobals的onCreate函数里,开始了Phone对象的创建(PhoneFactory.makeDefaultPhones).
public void onCreate() {
if (VDBG) Log.v(LOG_TAG, “onCreate()…”);

PhoneFactory.makeDefaultPhones(this);
}
1.3 PhoneFactory
在PhoneFactory中makeDefaultPhones为每张sim卡分别创建一个phone对象,一个ril对象及RadioConfig等相关配置。代码路径:frameworks/opt/telephony/src/java/com/android/internal/telephony/PhoneFactory.java
public static void makeDefaultPhone(Context context) {

/* In case of multi SIM mode two instances of Phone, RIL are created,
where as in single SIM mode only instance. isMultiSimEnabled() function checks
whether it is single SIM or multi SIM mode */
int numPhones = TelephonyManager.getDefault().getActiveModemCount();

            int[] networkModes = new int[numPhones];
            sPhones = new Phone[numPhones];
            sCommandsInterfaces = new RIL[numPhones];
            sTelephonyNetworkFactories = new TelephonyNetworkFactory[numPhones];

for (int i = 0; i < numPhones; i++) {
// reads the system properties and makes commandsinterface
// Get preferred network type.
networkModes[i] = RILConstants.PREFERRED_NETWORK_MODE;

                Rlog.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkModes[i]));
                sCommandsInterfaces[i] = new RIL(context,
                        RadioAccessFamily.getRafFromNetworkType(networkModes[i]),
                        cdmaSubscription, i);
            }

            if (numPhones > 0) {
                final RadioConfig radioConfig = RadioConfig.make(context,
                        sCommandsInterfaces[0].getHalVersion());
                sRadioHalCapabilities = RadioInterfaceCapabilityController.init(radioConfig,
                        sCommandsInterfaces[0]);
            } else {
                // There is no command interface to go off of
                final RadioConfig radioConfig = RadioConfig.make(context, HalVersion.UNKNOWN);
                sRadioHalCapabilities = RadioInterfaceCapabilityController.init(
                        radioConfig, null);
            }


for (int i = 0; i < numPhones; i++) {
sPhones[i] = createPhone(context, i);
}
用phone对象创建对应的sTelephonyNetworkFactories(移动数据)
for (int i = 0; i < numPhones; i++) {
sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
Looper.myLooper(), sPhones[i]);
}

2.RILJ与RILD连接架构
Android8以后RILJ和RILD使用HIDL架构通信,JAVA 通过绑定式 HAL 直接连接到 HW service,如下图:
在这里插入图片描述

3.RILJ
3.1RIL.java初始化
代码路径:frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java
PhoneFactory初始化ril调用的接口是proxies为null的这个:
@UnsupportedAppUsage
public RIL(Context context, int allowedNetworkTypes, int cdmaSubscription, Integer instanceId) {
this(context, allowedNetworkTypes, cdmaSubscription, instanceId, null);
}
初始化各分类RadioProxy
if (proxies == null) {
mServiceProxies.put(DATA_SERVICE, new RadioDataProxy());
mServiceProxies.put(MESSAGING_SERVICE, new RadioMessagingProxy());
mServiceProxies.put(MODEM_SERVICE, new RadioModemProxy());
mServiceProxies.put(NETWORK_SERVICE, new RadioNetworkProxy());
mServiceProxies.put(SIM_SERVICE, new RadioSimProxy());
mServiceProxies.put(VOICE_SERVICE, new RadioVoiceProxy());
} else {
mServiceProxies = proxies;
}

registerRIL
TelephonyDevController tdc = TelephonyDevController.getInstance();
if (proxies == null) {
// TelephonyDevController#registerRIL will call getHardwareConfig.
// To prevent extra requests when running tests, only registerRIL when proxies is null
tdc.registerRIL(this);
}
/**
* each RIL call this interface to register/unregister the unsolicited hardware
* configuration callback data it can provide.
/
public static void registerRIL(CommandsInterface cmdsIf) {
/
get the current configuration from this ril… /
cmdsIf.getHardwareConfig(sRilHardwareConfig);
/
… process it … /
if (sRilHardwareConfig != null) {
AsyncResult ar = (AsyncResult) sRilHardwareConfig.obj;
if (ar.exception == null) {
handleGetHardwareConfigChanged(ar);
}
}
/
and register for async device configuration change. */
cmdsIf.registerForHardwareConfigChanged(sTelephonyDevController, EVENT_HARDWARE_CONFIG_CHANGED, null);
}

初始化RadioProxy
// Set radio callback; needed to set RadioIndication callback (should be done after
// wakelock stuff is initialized above as callbacks are received on separate binder threads)
for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) {
if (service == RADIO_SERVICE) {
getRadioProxy(null);
} else {
if (proxies == null) {
// Prevent telephony tests from calling the service
getRadioServiceProxy(service, null);
}
}
}

protected IRadio getRadioProxy(Message result) {

通过IRadio的getService()获取HIDL的客户端,参数为mPhoneId,即slot id;因此每个卡槽,对应一个HIDL service。

try {
if (mDisabledRadioServices.get(RADIO_SERVICE).contains(mPhoneId)) {
riljLoge(“getRadioProxy: mRadioProxy for " + HIDL_SERVICE_NAME[mPhoneId]
+ " is disabled”);
} else {
try {
mRadioProxy = android.hardware.radio.V1_6.IRadio.getService(
HIDL_SERVICE_NAME[mPhoneId], true);
mRadioVersion = RADIO_HAL_VERSION_1_6;
} catch (NoSuchElementException e) {
}

            if (mRadioProxy == null) {
                try {
                    mRadioProxy = android.hardware.radio.V1_5.IRadio.getService(
                            HIDL_SERVICE_NAME[mPhoneId], true);
                    mRadioVersion = RADIO_HAL_VERSION_1_5;
                } catch (NoSuchElementException e) {
                }
            }

            if (mRadioProxy == null) {
                try {
                    mRadioProxy = android.hardware.radio.V1_4.IRadio.getService(
                            HIDL_SERVICE_NAME[mPhoneId], true);
                    mRadioVersion = RADIO_HAL_VERSION_1_4;
                } catch (NoSuchElementException e) {
                }
            }

            if (mRadioProxy == null) {
                try {
                    mRadioProxy = android.hardware.radio.V1_3.IRadio.getService(
                            HIDL_SERVICE_NAME[mPhoneId], true);
                    mRadioVersion = RADIO_HAL_VERSION_1_3;
                } catch (NoSuchElementException e) {
                }
            }

            if (mRadioProxy == null) {
                try {
                    mRadioProxy = android.hardware.radio.V1_2.IRadio.getService(
                            HIDL_SERVICE_NAME[mPhoneId], true);
                    mRadioVersion = RADIO_HAL_VERSION_1_2;
                } catch (NoSuchElementException e) {
                }
            }

            if (mRadioProxy == null) {
                try {
                    mRadioProxy = android.hardware.radio.V1_1.IRadio.getService(
                            HIDL_SERVICE_NAME[mPhoneId], true);
                    mRadioVersion = RADIO_HAL_VERSION_1_1;
                } catch (NoSuchElementException e) {
                }
            }

            if (mRadioProxy == null) {
                try {
                    mRadioProxy = android.hardware.radio.V1_0.IRadio.getService(
                            HIDL_SERVICE_NAME[mPhoneId], true);
                    mRadioVersion = RADIO_HAL_VERSION_1_0;
                } catch (NoSuchElementException e) {
                }
            }

通过linkToDeath增加binder意外断开之后的处理。
通过setResponseFunctions传入mRadioResponse, mRadioIndication,它们负责底层消息的接收和监听。

            if (mRadioProxy != null) {
                if (!mIsRadioProxyInitialized) {
                    mIsRadioProxyInitialized = true;
                    mRadioProxy.linkToDeath(mRadioProxyDeathRecipient,
                            mServiceCookies.get(RADIO_SERVICE).incrementAndGet());
                    mRadioProxy.setResponseFunctions(mRadioResponse, mRadioIndication);
                }
            } else {
                mDisabledRadioServices.get(RADIO_SERVICE).add(mPhoneId);
                riljLoge("getRadioProxy: set mRadioProxy for "
                        + HIDL_SERVICE_NAME[mPhoneId] + " as disabled");
            }
        }
    } 

3.2 调用底层
以拨号为例
TelephonyManager.dial->
RIL.java
@Override
public void dial(xxx) {

//获取 RadioVoiceProxy 客户端对象,RadioVoiceProxy
RadioVoiceProxy voiceProxy = getRadioServiceProxy(RadioVoiceProxy.class, result);
//封装待发送请求
RILRequest rr = obtainRequest(RIL_REQUEST_DIAL, result, mRILDefaultWorkSource);

//远程调用,直接到达HW service
@Override
public void dial(String address, boolean isEmergencyCall, EmergencyNumber emergencyNumberInfo,
boolean hasKnownUserIntentEmergency, int clirMode, UUSInfo uusInfo, Message result) {
if (isEmergencyCall && mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_4)
&& emergencyNumberInfo != null) {
emergencyDial(address, emergencyNumberInfo, hasKnownUserIntentEmergency, clirMode,
uusInfo, result);
return;
}
RadioVoiceProxy voiceProxy = getRadioServiceProxy(RadioVoiceProxy.class, result);
if (!voiceProxy.isEmpty()) {
RILRequest rr = obtainRequest(RIL_REQUEST_DIAL, result, mRILDefaultWorkSource);

        if (RILJ_LOGD) {
            // Do not log function arg for privacy
            riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
        }

        try {
            voiceProxy.dial(rr.mSerial, address, clirMode, uusInfo);
        } catch (RemoteException | RuntimeException e) {
            handleRadioProxyExceptionForRR(VOICE_SERVICE, "dial", e);
        }
    }
}

4.RILD
代码路径hardware\ril
4.1 初始化
每个卡槽一个 HIDL server端RadioImpl,存储在radioService中

从 rild.c 开始:
int main(int argc, char **argv) {

//加载reference-ril.so(代码在reference-ril/reference-ril.c),获取rilInit函数指针,并通过它获取相关函数指针。
dlHandle = dlopen(rilLibPath, RTLD_NOW);
rilInit =
(const RIL_RadioFunctions ()(const struct RIL_Env *, int, char **))
dlsym(dlHandle, “RIL_Init”);
rilInit 对应的是reference-ril.c的RIL_Init函数指针
然后调用rilInit 得到reference系列回调函数指针存储于funcs 。
// functions returned by ril init function in vendor ril
const RIL_RadioFunctions funcs;
funcs = rilInit(&s_rilEnv, argc, rilArgv);
RIL_RadioFunctions的定义在ril.h中
typedef struct {
int version; /
set to RIL_VERSION */
RIL_RequestFunc onRequest;
RIL_RadioStateRequest onStateRequest;
RIL_Supports supports;
RIL_Cancel onCancel;
RIL_GetVersion getVersion;
} RIL_RadioFunctions;

//注册RIL函数
RIL_register(funcs);
函数实现在libril/ril.cpp中,最终会调用:
radio::registerService(&s_callbacks, s_commands);
其实现在libril/ril_service.cpp,函数指针也会传递到这里
void radio::registerService(RIL_RadioFunctions *callbacks, CommandInfo *commands) {
using namespace android::hardware;
int simCount = 1;
const char *serviceNames[] = {HIDL server端的名字,即 slot1、slot2.
会为每个卡槽创建且注册一个RadioImpl(HIDL server端)
android::RIL_getServiceName()
#if (SIM_COUNT >= 2)
, RIL2_SERVICE_NAME
#if (SIM_COUNT >= 3)
, RIL3_SERVICE_NAME
#if (SIM_COUNT >= 4)
, RIL4_SERVICE_NAME
#endif
#endif
#endif
};

#if (SIM_COUNT >= 2)
simCount = SIM_COUNT;
#endif

s_vendorFunctions = callbacks;
s_commands = commands;
for (int i = 0; i < simCount; i++) {
    pthread_rwlock_t *radioServiceRwlockPtr = getRadioServiceRwlock(i);
    int ret = pthread_rwlock_wrlock(radioServiceRwlockPtr);
    assert(ret == 0);

    radioService[i] = new RadioImpl;
    radioService[i]->mSlotId = i;
    RLOGD("registerService: starting android::hardware::radio::V1_1::IRadio %s",
            serviceNames[i]);
    (void) radioService[i]->registerAsService(serviceNames[i]);

    ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
    assert(ret == 0);
.....

}

4.2 响应上层请求
以上层发起拨号为例
从上文中“调用底层”的章节中可知,在 RIL.java 是直接远程调用 dial() 函数,因此,直达 RadioImpl 中的 dial() 函数,代码在文libril/ril_service.cpp 中,如下:
Return RadioImpl::dial(int32_t serial, const Dial& dialInfo) {

//HIDL到这里,调用 CALL_ONREQUEST() 拨号
CALL_ONREQUEST(RIL_REQUEST_DIAL, &dial, sizeOfDial, pRI, mSlotId);
调用到onRequest

从初始化流程可知,这些函数指针会调用到reference-ril/reference-ril.c
/*** Callback methods from the RIL library to us ***/

/**

  • Call from RIL to us to make a RIL_REQUEST
  • Must be completed with a call to RIL_onRequestComplete()
  • RIL_onRequestComplete() may be called from any thread, before or after
  • this function returns.
  • Because onRequest function could be called from multiple different thread,
  • we must ensure that the underlying at_send_command_* function
  • is atomic.
    */
    static void
    onRequest (int request, void *data, size_t datalen, RIL_Token t)
    {
    ATResponse *p_response;
    int err;

    case RIL_REQUEST_DIAL:
    requestDial(data, datalen, t);

    }

最后在requestDail中at_send_command(在atchannel.c中实现)完成调用流程,并调用RIL_onRequestComplete完成闭环。
static void requestDial(void *data, size_t datalen __unused, RIL_Token t)
{
RIL_Dial *p_dial;
char *cmd;
const char *clir;
int ret;

p_dial = (RIL_Dial *)data;

switch (p_dial->clir) {
    case 1: clir = "I"; break;  /*invocation*/
    case 2: clir = "i"; break;  /*suppression*/
    default:
    case 0: clir = ""; break;   /*subscription default*/
}

asprintf(&cmd, "ATD%s%s;", p_dial->address, clir);

ret = at_send_command(cmd, NULL);

free(cmd);

/* success or failure is ignored by the upper layer here.
   it will call GET_CURRENT_CALLS and determine success that way */
RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);

}

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值