# 一、需求 1、瞭解IMS相關知識體系 2、RILD 與 RILJ、IMS回調消息的機制 # 二、相關概念 ## 2.1 IMS IMS全稱是IP Multimedia Subsystem,中文意義為IP多媒體子系統。IMS是一種基於IP基礎結構,能夠融合數據、話音和移動等網路技術的系統。 **I ...
一、需求
1、瞭解IMS相關知識體系
2、RILD 與 RILJ、IMS回調消息的機制
二、相關概念
2.1 IMS
IMS全稱是IP Multimedia Subsystem,中文意義為IP多媒體子系統。IMS是一種基於IP基礎結構,能夠融合數據、話音和移動等網路技術的系統。
IP = 基於IP 的傳輸,基於IP的會話控制,基於IP的業務實現
Multimedia = 語音、視頻、圖片、文本等多種媒體組合,在多種接入基礎之上具有不同能力的終端組合
Subsvstem = 依賴於現有網路技術和網路設備發展的網路,最大程度重用現有網路系統
(我個人理解IMS是一個很大的概念,它不單單特指:IMS服務、IMS PDN等。它類似GSM,WCDMA,LTE一樣,是一種體繫結構,包含了好多內容)
2.2 Volte
VoLTE是Voice over LTE的縮寫,是基於 IMS 的語音業務。VoLTE基於IP多媒體子系統(IMS)網路,在LTE上使用為控制層面和語音服務的媒體層面特製的配置文件,使語音服務作為數據流在LTE數據承載網路中進行傳輸,而不再需要維護和依賴傳統的電路交換語音網路。通俗的來講,就是語音通話建立在4G流量之上,無需再依托於2G/3G網,全部承載於4G網路中,最終實現數據與語音業務在同一網路下的統一,使4G網路不再僅僅提供流量數據業務支撐,還提供語音及視頻通話支持,讓4G網路利用最大化。
移動用戶肯定都遇到過這個問題,在玩網路游戲時一則電話打進來,游戲就斷網了,這並非手機硬體問題,而是移動4G手機是通過2G信號進行語音通訊,所以通話過程中系統會自動將網路從4G切換到2G。
2.3 CS域與PS域
我們瞭解到的數據傳輸有兩個域,分別是CS域和PS域。我們常說的CS域就是電路交換域,通常用於語音通話,在2G和3G中都有應用到;我們常說的PS域就是分組交換域,通常用於數據業務,在3G、4G和5G中都有應用到。而還有一個IMS(IP多媒體子系統),相當於是PS域上的一個子系統,IMS的存在可以讓用戶在PS域上同時使用語音通話和數據業務
2.3.1 CS域
CS(Circuit Switched)域,即電路交換域。首先需要建立一條傳輸數據的連接,建立完成之後開始數據的傳輸,此連接不會斷開,直到數據傳輸完畢,才可以釋放掉連接。所以一條鏈路只電路交換的特點是獨占一條鏈路,一直用於數據傳輸。可靠性很高,但不高效。這就相當於是小時候玩的聽筒游戲,兩個紙杯子之間連著一條線,兩個人通話過程中,這條鏈路是不能斷開的,直到通話結束。
2.3.2 PS域
PS域(Packet Switch)錶面意思就是分組交換。PS 域不能直接進行語音業務,PS業務就是常見的數據業務,也包括流媒體業務、VOIP等等。具有高效的傳輸效率,但可靠性沒有CS域那麼高。
2.4 VOIP
VOIP是一個很寬泛的概念,VOIP(Voice over IP)的縮寫,只要是通過IP傳輸的語音電話,都可以稱為VOIP。如互聯網提供商提供(Skype、微信、teams等)、運營商提供的IMS(LTE時代公認的語音解決方案(VoLTE)。因為VoLTE是運營商在LTE層上附著IMS-PDN進行傳輸的,相對於純IP網路的skype、微信網路電話,通話質量會好很多。
2.5 URC消息
URC 是Unsolicited Result Code,即"非請求結果碼"。 一般的 AT命令 流程都是控制端發出 命令 ,被控端響應結果碼。 但當被控端有事件需要通知控制端時,就會主動發出 URC ,例如有呼叫打入、收到新簡訊息、自動關機等。
2.6 HIDL
HIDL的全稱是HAL interface definition language(硬體抽象層介面定義語言) ,是AndroidFramework 與Android HAL之間的介面。HIDL 旨在用於進程間通信(IPC)。Android O(8.0) 之前系統的升級牽扯多方協作,極為麻煩,HIDL機制的推出就是將 framework 與 hal 層分開,使得框架部分可以直接被覆蓋、更新,而不需要重新對 HAL 進行編譯,這樣在系統升級時,OEM 廠商 跳過 SoC廠商,先對 framework 進行升級。
三、環境
- 晶元:高通Qcm2290
- 版本:Android 11
四、設計思路
4.1 RIL結構圖

4.2 RIL相關模塊介紹
模塊 | 進程 | 介紹 |
---|---|---|
Dialer | com.android.dialer | 負責撥號、呼叫界面顯示 |
TeleService | com.android.phone | 負責通話邏輯,如實際向RIL撥號、掛電話,及電話狀態如撥號、振鈴、接通等的變更。 |
TelecomService | system_server | 負責邏輯控制,是溝通各個進程交互的橋梁。 |
telephony-common(RILJ) | jar,看哪個進程引用,主要是com.android.phone | 主要是phone模塊,hal層對應的java層客戶端的代碼,這個模塊的代碼就是跟hal下麵的C/C++服務進行通信的 |
RILD | RILD | 主要負責接發RILJ指令、Modem指令 |
MODEM | Modem | Modem是數據機的縮寫,它是一種用於數字信號和模擬信號之間轉換的設備。在手機中,Modem是一個硬體模塊,它負責處理與無線網路通信相關的任務,包括數據傳輸、語音通信和簡訊等。 |
4.2.1 Dialer模塊
源碼: LINUX\android\packages\apps\Dialer
4.2.2 TeleService模塊
源碼: LINUX\android\packages\services\Telephony
4.2.2.1 TeleService啟動
(1)設置persistent標記,此標記AMS會持續保證進程(com.android.phone)存活,意外掛掉也會自動重啟。
LINUX\android\packages\services\Telephony/AndroidManifest.xml
<application android:name="PhoneApp"
android:persistent="true"
...
android:directBootAware="true">
(2)SystemServer啟動後,ActivityManqgerService服務初始化完成後,啟動persistent進程,即Phone模塊被啟動。
LINUX\android\frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
void startPersistentApps(int matchFlags) {
...
synchronized (this) {
try {
final List<ApplicationInfo> apps = AppGlobals.getPackageManager()
.getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();
for (ApplicationInfo app : apps) {
if (!"android".equals(app.packageName)) {
addAppLocked(app, null, false, null /* ABI override */,
ZYGOTE_POLICY_FLAG_BATCH_LAUNCH);
}
}
} catch (RemoteException ex) {
}
}
}
4.2.3 TelecomService模塊
源碼: LINUX\android\packages\services\Telecomm
4.2.3.1 TelecomService啟動
Android設備剛開機,SystemServer進程初始化完成啟動完系統的核心服務如AMS、PMS後,就會載入系統其它服務,這其中就包含了一個與Telecom服務啟動相關的系統服務專門用於載入Telecom:
LINUX\android\frameworks\base\services\java\com\android\server\SystemServer.java
private void run() {
...
startBootstrapServices(t);
startCoreServices(t);
startOtherServices(t);
...
}
private void startOtherServices(@NonNull TimingsTraceAndSlog t)
...
//啟動Telecom服務的載入類
t.traceBegin("StartTelecomLoaderService");
mSystemServiceManager.startService(TelecomLoaderService.class);=
t.traceEnd();
//啟動telephony註冊服務,用於註冊監聽telephony狀態的介面
t.traceBegin("StartTelephonyRegistry");
telephonyRegistry = new TelephonyRegistry(context, new TelephonyRegistry.ConfigurationProvider());
ServiceManager.addService("telephony.registry", telephonyRegistry);
t.traceEnd();
...
//AMS初始化完成,啟動Telecom服務
mActivityManagerService.systemReady(() -> {
...
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_ACTIVITY_MANAGER_READY);
...
}, t);
...
}
在TelecomLoaderService類實現Telecom服務的bind工作,完成Telecom的啟動
LINUX\android\frameworks\base\services\core\java\com\android\server\telecom\TelecomLoaderService.java
private static final ComponentName SERVICE_COMPONENT = new ComponentName(
"com.android.server.telecom",
"com.android.server.telecom.components.TelecomService");
private static final String SERVICE_ACTION = "com.android.ITelecomService";
@Override
public void onBootPhase(int phase) {
if (phase == PHASE_ACTIVITY_MANAGER_READY) {
...
connectToTelecom();
}
}
//連接Telecom服務
private void connectToTelecom() {
synchronized (mLock) {
...
TelecomServiceConnection serviceConnection = new TelecomServiceConnection();
Intent intent = new Intent(SERVICE_ACTION);
intent.setComponent(SERVICE_COMPONENT);
int flags = Context.BIND_IMPORTANT | Context.BIND_FOREGROUND_SERVICE
| Context.BIND_AUTO_CREATE;
// Bind to Telecom and register the service
if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.SYSTEM)) {
mServiceConnection = serviceConnection;
}
}
}
private class TelecomServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
try {
ITelecomLoader telecomLoader = ITelecomLoader.Stub.asInterface(service);//返回TelecomService代理對象
ITelecomService telecomService = telecomLoader.createTelecomService(mServiceRepo);//返回TelecomService實現類
SmsApplication.getDefaultMmsApplication(mContext, false);
ServiceManager.addService(Context.TELECOM_SERVICE, telecomService.asBinder());//將TelecomService實現類註冊到serviceManager,以便後續方便引用
...
}
...
}
4.2.3.2 TeleComService消息處理模型
Telecom是Android的一個系統服務,其主要作用是管理Android系統當前的通話,如來電顯示,接聽電話,掛斷電話等功能,在Telephony模塊與上層UI之間起到了一個橋梁的作用。比如,Telephony有接收到新的來電時,首先會告知Telecom,然後由Telecom服務通知上層應用來電信息,並顯示來電界面。

4.2.4 telephony-common模塊
源碼: LINUX\android\frameworks\opt\telephony
telephony-common模塊最終編譯會生成一個java library,主要是phone模塊在引用,hal層對應的java層客戶端的代碼RILJ,這個模塊的代碼就是跟hal下麵的C/C++服務進行通信的。
LINUX\android\frameworks\opt\telephony\Android.bp
java_library {
name: "telephony-common",
installable: true,
...
}
4.2.5 Telecom_Framewrok模塊
源碼:LINUX\android\frameworks\base\telecomm
android提供的phone的一些sdk的代碼,最終編譯完成打包進framework.jar
LINUX\android\frameworks\base\Android.bp
filegroup {
name: "framework-telecomm-sources",
srcs: [
"telecomm/java/**/*.java",
"telecomm/java/**/*.aidl",
],
path: "telecomm/java",
}
framework-telecomm-sources => framework-non-updatable-sources => framework-non-updatable-sources => framework-minus-apex => framework
4.2.6 Telephony_Framewrok模塊
源碼: LINUX\android\frameworks\base\telephony
android提供的phone的一些sdk的代碼,最終編譯完成打包進framework.jar
LINUX\android\frameworks\base\Android.bp
filegroup {
name: "framework-telephony-sources",
srcs: [
"telephony/java/**/*.java",
"telephony/java/**/*.aidl",
],
path: "telephony/java",
}
framework-telephony-sources => framework-non-updatable-sources => framework-non-updatable-sources => framework-minus-apex => framework
4.2.7 RIL模塊
源碼: LINUX\android\hardware\ril
RIL模塊由rild守護進程、libril.so、librefrence.so三部分組成:
4.2.7.1 RILD守護進程
源碼: LINUX\android\hardware\ril\rild
RILD主要起到承上啟下的作用,作為modem和RILJ的通信的中轉站。RILD可分為兩部分,一是負責與RILJ通訊的部分,主要通過HIDL通信;另一個是負責與modem交互,主要通過AT指令。
4.2.7.1.1 RILD啟動
(1)開機時,通過RC文件啟動RILD進程
@LINUX\android\hardware\ril\rild\rild.rc
service vendor.ril-daemon /vendor/bin/hw/rild
class main
user radio
disabled
group radio cache inet misc audio log readproc wakelock
capabilities BLOCK_SUSPEND NET_ADMIN NET_RAW
(2)RILD啟動後,會執行main啊方法,初始化RILD相關操作
@LINUX\android\hardware\ril\rild\rild.c
int main(int argc, char **argv) {
...
rilInit =
(const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))
dlsym(dlHandle, "RIL_Init");
...
//初始化reference,輪詢modem指令
funcs = rilInit(&s_rilEnv, argc, rilArgv);
RLOGD("RIL_Init rilInit completed");
//在rild註冊reference的回調函數
RIL_register(funcs);
...
}
4.2.7.2 libril共用庫
源碼: LINUX\android\hardware\ril\libril
libril.so是共用庫,主要負責同上層的通信工作,接收ril的請求,並傳遞給librefrence_ril.so,同時將librefrence_ril.so返回的消息送給調用進程
4.2.7.3 librefrence共用庫
源碼: LINUX\android\hardware\ril\reference-ril
librefrence_ril.so是共用庫,是由各手機廠商自己實現,在rild進程運行中通過dlopen方式載入,主要負責跟modem硬體通信,轉換來自libril的請求為AT命令,同時監聽Modem的反饋信息給libril
4.3 RIL相關模塊通訊
4.3.1 通訊架構圖

五、詳細設計
5.1 Dialer撥號
5.1.1 Dialer應用撥號時序圖

5.1.2 Dialer撥號界面顯示
Dialer應用為撥號提供了界面顯示,同時也是撥號請求的觸發點
@LINUX\android\packages\apps\Dialer\java\com\android\dialer\dialpadview\DialpadFragment.java
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
...
View fragmentView = inflater.inflate(R.layout.dialpad_fragment, container, false);//撥號界面佈局載入
...
return fragmentView;
}
@Override
public void onClick(View view) {
int resId = view.getId();
if (resId == R.id.dialpad_floating_action_button) {
view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
handleDialButtonPressed();//撥號按鈕點擊事件
}
...
}
5.1.3 Dialer許可權檢查
Dialer應用會進行許可權檢查,判斷當前是否為預設撥號盤,且當前應用是否聲明CALL_PHONE許可權。
public static boolean placeCall(Context context, Intent intent) {
if (hasCallPhonePermission(context)) {//許可權檢查
getTelecomManager(context).placeCall(intent.getData(), intent.getExtras());
return true;
}
return false;
}
@Deprecated
public static boolean hasCallPhonePermission(Context context) {
return isDefaultDialer(context) || hasPermission(context, Manifest.permission.CALL_PHONE);//判斷當前是否為預設撥號盤,且當前應用是否聲明CALL_PHONE許可權
}
5.1.4 與TelecomService通信
Dialer應用通過TelecomManager對象,將撥號請求消息,通過binder的方式,通知TelecomService進程。
@LINUX\android\frameworks\base\telecomm\java\android\telecom\TelecomManager.java
@RequiresPermission(anyOf = {android.Manifest.permission.CALL_PHONE,
android.Manifest.permission.MANAGE_OWN_CALLS})
public void placeCall(Uri address, Bundle extras) {
ITelecomService service = getTelecomService();//獲取服務端代理對象
if (service != null) {
if (address == null) {
Log.w(TAG, "Cannot place call to empty address.");
}
try {
service.placeCall(address, extras == null ? new Bundle() : extras,
mContext.getOpPackageName(), mContext.getAttributionTag());//通過binder實現跨進程通信,將撥號請求發給TelecomService進程
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#placeCall", e);
}
}
}
5.2 TelecomService處理撥號流程
5.2.1 TelecomService處理撥號時序圖

5.2.2 往InCallService發送請求
(1)startOutgoingCall開始呼叫請求
Dialer進程的撥號請求傳遞到TelecomService進程後,通過startOutgoingCall方法開始請求打開呼叫界面
@LINUX\android\packages\services\Telecomm\src\com\android\server\telecom\CallIntentProcessor.java
static void processOutgoingCallIntent(
Context context,
CallsManager callsManager,
Intent intent,
String callingPackage,
DefaultDialerCache defaultDialerCache) {
...
// Send to CallsManager to ensure the InCallUI gets kicked off before the broadcast returns
CompletableFuture<Call> callFuture = callsManager
.startOutgoingCall(handle, phoneAccountHandle, clientExtras, initiatingUser,
intent, callingPackage);//開始呼叫請求
final Session logSubsession = Log.createSubsession();
callFuture.thenAccept((call) -> {
if (call != null) {
Log.continueSession(logSubsession, "CIP.sNOCI");
try {
broadcaster.processCall(call, disposition);//發送廣播,切換成非同步請求
} finally {
Log.endSession();
}
}
});
}
(2)綁定InCallService
InCallServiceImpl是InCallService的子類,在Dialer進程,而TelecomService進程與InCallServiceImpl也是通過bind實現跨進程通信。
@LINUX\android\packages\services\Telecomm\src\com\android\server\telecom\InCallController.java
public static final String SERVICE_INTERFACE = "android.telecom.InCallService";
public int connect(Call call) {
...
Intent intent = new Intent(InCallService.SERVICE_INTERFACE);
intent.setComponent(mInCallServiceInfo.getComponentName());
...
//綁定InCallService類型服務,最終綁定InCallServiceImpl
if (!mContext.bindServiceAsUser(intent, mServiceConnection,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE |
Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS |
Context.BIND_ABOVE_CLIENT,
UserHandle.CURRENT)) {
Log.w(this, "Failed to connect.");
mIsConnected = false;
}
...
}
(3)啟動InCallActivity呼叫界面
當InCallServiceImpl被TelecomService進程綁定後,會調用onBind函數,接著啟動InCallActivity呼叫界面
@LINUX\android\packages\apps\Dialer\java\com\android\incallui\InCallServiceImpl.java
public IBinder onBind(Intent intent) {
...
InCallPresenter.getInstance().onServiceBind();
InCallPresenter.getInstance().maybeStartRevealAnimation(intent);//開啟顯示動畫
TelecomAdapter.getInstance().setInCallService(this);
...
return iBinder;
}
@LINUX\android\packages\apps\Dialer\java\com\android\incallui\InCallPresenter.java
public void maybeStartRevealAnimation(Intent intent) {
...
//啟動InCallActivity呼叫界面
final Intent activityIntent =
InCallActivity.getIntent(context, false, true, false /* forFullScreen */);
activityIntent.putExtra(TouchPointManager.TOUCH_POINT, touchPoint);
context.startActivity(activityIntent);
}
5.2.3 廣播下發消息
TelecomService進程發出一個定向廣播,由TelecomService進程中的NewOutgoingCallBroadcastIntentReceiver對象接收。
(1)TelecomService進程發送廣播
@LINUX\android\packages\services\Telecomm\src\com\android\server\telecom\NewOutgoingCallIntentBroadcaster.java
private void broadcastIntent(
Intent originalCallIntent,
String number,
boolean receiverRequired,
UserHandle targetUser) {
Intent broadcastIntent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);
...
//發送廣播
mContext.sendOrderedBroadcastAsUser(
broadcastIntent,
targetUser,
android.Manifest.permission.PROCESS_OUTGOING_CALLS,
AppOpsManager.OP_PROCESS_OUTGOING_CALLS,
options.toBundle(),
receiverRequired ? new NewOutgoingCallBroadcastIntentReceiver() : null,
null, // scheduler
Activity.RESULT_OK, // initialCode
number, // initialData: initial value for the result data (number to be modified)
null); // initialExtras
}
(2)TelecomService進程接收廣播
@LINUX\android\packages\services\Telecomm\src\com\android\server\telecom\NewOutgoingCallIntentBroadcaster.java
public class NewOutgoingCallBroadcastIntentReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
...
placeOutgoingCallImmediately(mCall, resultHandleUri, gatewayInfo,
mIntent.getBooleanExtra(
TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false),
mIntent.getIntExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
VideoProfile.STATE_AUDIO_ONLY));//繼續下發呼叫請求
...
}
}
同一個應用中為什麼要使用廣播來傳遞消息呢?因為Dialer進程發起撥號請求後,會將消息發給TelecomService進程,通過該進程的placeCall方法層層調用,此時方法是同步調用。直到調用了broadcastIntent,通過廣播方式將同步方法轉換成非同步處理,即當前的呼叫請求下發給TelecomService進程處理,同Dialer進程的呼叫請求結束。
5.2.4 往TeleService下發請求
(1)placeOutgoingCall 下發呼叫請求
接收廣播後,通過placeOutgoingCall方法繼續下發撥號請求
private void placeOutgoingCallImmediately(Call call, Uri handle, GatewayInfo gatewayInfo,
boolean speakerphoneOn, int videoState) {
...
mCall.setNewOutgoingCallIntentBroadcastIsDone();
mCallsManager.placeOutgoingCall(call, handle, gatewayInfo, speakerphoneOn, videoState);
}
(2)綁定TeleService
binder綁定TeleService服務,實現跨進程通信,同時將將撥號請求分發給TeleService進程,由TeleService進程繼續處理
@LINUX\android\packages\services\Telecomm\src\com\android\server\telecom\ConnectionServiceWrapper.java
public void createConnection(final Call call, final CreateConnectionResponse response) {
BindCallback callback = new BindCallback() {
@Override
public void onSuccess() {
...
mServiceInterface.createConnection(...);//與TeleService綁定成功後,發起創建通話連接請求
...
}
@Override
public void onFailure() {
...
}
};
mBinder.bind(callback, call);//綁定TeleService
}
}
@LINUX\android\packages\services\Telecomm\src\com\android\server\telecom\ServiceBinder.java
public static final String SERVICE_INTERFACE = "android.telecom.ConnectionService";
void bind(BindCallback callback, Call call) {
...
if (mServiceConnection == null) {
Intent serviceIntent = new Intent(mServiceAction).setComponent(mComponentName);//該對象為SERVICE_INTERFACE
...
if (mUserHandle != null) {
isBound = mContext.bindServiceAsUser(serviceIntent, connection, bindingFlags,
mUserHandle);//綁定TeleService
}
...
}
}
5.3 TeleService下發撥號請求
5.3.1 TeleService下發撥號請求時序圖

5.3.2 TeleService類圖

5.3.3 TelephonyConnectionService啟動
@LINUX\android\packages\services\Telephony\AndroidManifest.xml
<service
android:singleUser="true"
android:name="com.android.services.telephony.TelephonyConnectionService"
android:label="@string/pstn_connection_service_label"
android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE" >
<intent-filter>
<action android:name="android.telecom.ConnectionService" />
</intent-filter>
</service>
5.3.4 TeleService撥號請求下發(GsmCdmaPhone)
在teleService會獲取當前呼叫的phone對象,如GsmCdmaPhone、ImsPhone、SipPhone,來決定要從用哪一種通訊方式進行呼叫。
@LINUX\android\packages\services\Telephony\src\com\android\services\telephony\TelephonyConnectionService.java
public Connection onCreateOutgoingConnection(
PhoneAccountHandle connectionManagerPhoneAccount,
final ConnectionRequest request) {
...
if (PhoneAccount.SCHEME_VOICEMAIL.equals(scheme)) {
// TODO: We don't check for SecurityException here (requires
// CALL_PRIVILEGED permission).
final Phone phone = getPhoneForAccount(request.getAccountHandle(),
false /* isEmergencyCall */, null /* not an emergency call */);//獲取Phone對象,決定採用的通訊方式
...
}
...
if (!isEmergencyNumber) {
...
return placeOutgoingConnection(request, resultConnection, phone);//往RILD繼續下發消息
}
...
}
5.3.5 TeleService撥號請求下發(ImsPhone)
Android 9 引入了一個名為 ImsService 的新 SystemApi 介面,可以幫助實現IP多媒體子系統。ImsService API 是在 Android 平臺與供應商或運營商提供的 IMS 實現之間明確定義的介面。即IMS的具體實現是由供應商或運營商實現。 android提供了相關的系統SystemApi介面。
5.3.5.1 時序圖

5.3.5.2 IMS與CDMA、GSM時序切換
與普通的CS通話一致,由Dialer撥號應用,到Telecom,TeleService。區別在於,在GsmCdmaPhone#diale()中,判斷是否支持ims通話。
public Connection dial(String dialString, @NonNull DialArgs dialArgs)
throws CallStateException {
...
boolean useImsForCall = useImsForCall(dialArgs)
&& !shallDialOnCircuitSwitch(dialArgs.intentExtras)
&& (isWpsCall ? allowWpsOverIms : true);//是否使用IMS通訊方式
...
if ((useImsForCall && (!isMmiCode || isPotentialUssdCode))
|| (isMmiCode && useImsForUt)
|| useImsForEmergency) {
try {
if (DBG) logd("Trying IMS PS call");
return imsPhone.dial(dialString, dialArgs);//使用IMS通話
} ...
}
...
if (isPhoneTypeGsm()) {
return dialInternal(dialString, new DialArgs.Builder<>()
.setIntentExtras(dialArgs.intentExtras)
.build());//使用GSM通話
} else {
return dialInternal(dialString, dialArgs);//其他通話方式
}
}
5.4 RILD處理撥號請求
5.4.1 RILD撥號請求消息下發時序圖

5.4.2 RILJ往RILD發送指令
RILJ往RILD發送指令,請求撥號的消息下發如下:
@LINUX\android\frameworks\opt\telephony\src\java\com\android\internal\telephony\RIL.java
@Override
public void dial(String address, boolean isEmergencyCall, EmergencyNumber emergencyNumberInfo,
boolean hasKnownUserIntentEmergency, int clirMode, UUSInfo uusInfo,
Message result) {
...
IRadio radioProxy = getRadioProxy(result);
if (radioProxy != null) {
RILRequest rr = obtainRequest(RIL_REQUEST_DIAL, result,
mRILDefaultWorkSource);
...
try {
radioProxy.dial(rr.mSerial, dialInfo);//請求撥號
} catch (RemoteException | RuntimeException e) {
handleRadioProxyExceptionForRR(rr, "dial", e);
}
}
}
5.4.3 RILD接收到RILJ指令
RILD接收到RILJ指令,JAVA層與HAL層通過HIDL方式綁定,即HAL也會有對應的dial映射方法。
@LINUX\android\hardware\ril\libril\ril_service.cpp
#define CALL_ONREQUEST(a, b, c, d, e) \
s_vendorFunctions->onRequest((a), (b), (c), (d), ((RIL_SOCKET_ID)(e)))
Return<void> RadioImpl::dial(int32_t serial, const Dial& dialInfo) {
...
CALL_ONREQUEST(RIL_REQUEST_DIAL, &dial, sizeOfDial, pRI, mSlotId);
memsetAndFreeStrings(2, dial.address, uusInfo.uusData);
return Void();
}
5.4.4 RILD和reference側消息傳遞
onRequest方法是在哪裡被實現的?我們需要關註下s_vendorFunctions是在哪個地方賦值的。關於s_vendorFunctions全局變數,當我們調用reference中的RIL_Init完成初始化時,就會得到reference返回當前鏈接庫提供的介面函數,通過該介面函數我們便可實現rild側與reference側的通訊(reference側也是跑在rild進程,但是考慮到reference一般由modem廠商客制化,不清楚其內部實現,故以下將其稱為reference側,以便更好地區分該模塊)。
@LINUX\android\hardware\ril\libril\ril.cpp
extern "C" void
RIL_register (const RIL_RadioFunctions *callbacks) {
...
memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));//對象拷貝
...
radio::registerService(&s_callbacks, s_commands);//註冊回調函數
...
}
@LINUX\android\hardware\ril\libril\ril_service.cpp
void radio::registerService(RIL_RadioFunctions *callbacks, CommandInfo *commands) {
...
s_vendorFunctions = callbacks;//將回調函數對象賦值,以實現rild側與reference側的引用
s_commands = commands;
...
}
5.4.5 reference側接收到消息
reference層接收到消息, 從onRequest可以看出,reference中對所有的命令請求進行判別,然後選擇不同的處理方式。
@LINUX\android\hardware\ril\reference-ril\reference-ril.c
static void onRequest (int request, void *data, size_t datalen, RIL_Token t)
{
...
switch (request) {
...
case RIL_REQUEST_DIAL:
requestDial(data, datalen, t);//撥號請求
break;
case RIL_REQUEST_HANGUP://掛斷電話請求
requestHangup(data, datalen, t);
break;
...
}
}
static void requestDial(void *data, size_t datalen __unused, RIL_Token t)
{
...
ret = at_send_command(cmd, NULL);//往modem層發送指令
...
/* 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);
}
5.4.6 reference側將消息發送至modem側
reference側將消息發送至modem側,at_send_command() -> at_send_command_full() -> at_send_command_full_nolock(),經過上面的操作,就將一條命令通過串口方式傳輸到了Modem側。其間,完成了兩個重要動作:1、通過writeline發送數據到Modem;2、阻塞當前線程,等待Modem回應。
@LINUX\android\hardware\ril\reference-ril\atchannel.c
static int at_send_command_full_nolock (const char *command, ATCommandType type,
const char *responsePrefix, const char *smspdu,
long long timeoutMsec, ATResponse **pp_outResponse)
{
...
err = writeline (command);//將命令通過AT指令方式寫入modem側
if (err < 0) {
goto error;
}
...
while (sp_response->finalResponse == NULL && s_readerClosed == 0) {
if (timeoutMsec != 0) {
err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts);//阻塞線程,直到modem側消息返回
}
...
}
...
return err;
}
5.4.7 modem側發送消息至reference側
modem側發送消息至reference側,我們需要如何喚醒阻塞的線程呢?當我們發送數據或命令給Modem的時候,阻塞了當前的線程,阻塞的目的就是等待Modem的回應,而如果Modem有數據上來,那麼肯定是先被reference的ReaderLoop檢測到並處理,因此,也應該是在ReaderLoop的消息處理中去喚醒當前阻塞的線程,而且應該把Modem的反饋傳輸給阻塞線程。
@LINUX\android\hardware\ril\reference-ril\atchannel.c
static void *readerLoop(void *arg __unused)
{
for (;;) {
...
line = readline();//讀取modem返回數據
...
if(isSMSUnsolicited(line)) {
...
} else {
processLine(line);//解析消息
}
}
...
return NULL;
}
static void processLine(const char *line)
{
...
if (sp_response == NULL) {
/* no command pending */
handleUnsolicited(line);//處理URC消息
} else if (isFinalResponseSuccess(line)) {
sp_response->success = 1;
handleFinalResponse(line);//發送回應消息
}
...
}
static void handleFinalResponse(const char *line)
{
sp_response->finalResponse = strdup(line);
pthread_cond_signal(&s_commandcond);//發送一個信號給另外一個正在處於阻塞等待狀態的線程,使其脫離阻塞狀態
}
5.4.8 reference側輪詢modem指令
reference側輪詢modem指令,ReaderLoop輪詢modem消息又是在哪裡實現的呢?RILD進程被創建後,會通過RIL_Init初始化相關的reference相關準備工作,其中涉及到打開與modem側的AT通道,監聽modem上報消息。
@LINUX\android\hardware\ril\reference-ril\atchannel.c
const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
{
...
ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);//創建mainLoop線程
...
}
static void *
mainLoop(void *param __unused)
{
...
for (;;) {
...
ret = at_open(fd, onUnsolicited);//打開AT通道並把處理URC消息的方法onUnsolicited傳進去
...
}
}
@LINUX\android\hardware\ril\reference-ril\atchannel.c
int at_open(int fd, ATUnsolHandler h)
{
...
ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr);//創建readerLooper線程,讀取AT指令並處理modem側消息
...
}
六、RIL指令
6.1 RILJ主動發送指令
源碼: android\hardware\ril\libril\ril_commands.h
指令 | 功能 |
---|---|
RIL_REQUEST_GET_SIM_STATUS | 獲取SIM卡狀態 |
RIL_REQUEST_ENTER_SIM_PIN | 請求輸入SIM的PIN碼(PIN碼是用來保護SIM卡安全的密碼。PIN碼的初始值一般是1234,可以進行更改) |
RIL_REQUEST_ENTER_SIM_PUK | 請求PUK碼和新的PIN碼的輸入(PUK碼是用來解PIN碼的解鎖碼,共8位長) |
RIL_REQUEST_ENTER_SIM_PIN2 | 請求輸入SIM的PIN2碼(進入某種特殊功能時,如設置固定號碼、設置通話計費等,所要輸入的個人識別碼) |
RIL_REQUEST_ENTER_SIM_PUK2 | 請求PUK2碼和新的PIN2碼的輸入(PUK2碼就是專門用來為被鎖上的PIN2碼解鎖的) |
RIL_REQUEST_CHANGE_SIM_PIN | 請求更改PIN碼 |
RIL_REQUEST_CHANGE_SIM_PIN2 | 請求更改PIN2碼 |
RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION | 請求輸入網路個人碼以便去激活 |
RIL_REQUEST_GET_CURRENT_CALLS | 請求獲取當前呼叫列表 |
RIL_REQUEST_DIAL | 初始化一個語音呼叫 |
RIL_REQUEST_GET_IMSI | 取SIM卡中的國際移動用戶識別碼IMSI(區別移動用戶的標誌,儲存在SIM卡中,可用於區別移動用戶的有效信息) |
RIL_REQUEST_HANGUP | 掛斷某一激活的通話 |
RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND | 掛斷所有等待的或者保持的通話 |
RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND | 釋放所有激活的通話並激活保持的或者等待的通話 |
RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE | 話連接狀態的轉換,將所有激活的通話轉為保持或等待狀態(通話狀態:IDLE、ACTIVE、HOLDING、WAITING等) |
RIL__CONFERENCE | 請求加入電話會議 |
RIL_REQUEST_UDUB | 發送用戶確定用戶忙UDUB(user determined user busy)信號 |
RIL_REQUEST_LAST_CALL_FAIL_CAUSE | 請求最近一次通話中斷的錯誤碼 |
RIL_REQUEST_SIGNAL_STRENGTH | 請求當前的信號強度等相關信息 |
RIL_REQUEST_VOICE_REGISTRATION_STATE | 請求當前註冊狀態(描述的是信號柱的顯示) |
RIL_REQUEST_DATA_REGISTRATION_STATE | 請求當前註冊狀態(描述的是3G、4G的顯示) |
RIL_REQUEST_OPERATOR | 請求運營商名稱 |
RIL_REQUEST_RADIO_POWER | 請求打開無線電通訊 |
RIL_REQUEST_DTMF | 發起DTMF請求(在手機中,常用的DTMF場景是使用手機撥打一些服務臺電話,比如客服熱線10086、10000之類;電話接入之後,有對應的語音提示輸入不同的數字進入不同的菜單,或者要修改資料,對方要驗證我們的賬號和密碼,這時打開手機撥號盤,輸入數字信息,對方就知道我們輸入的內容是什麼。) |
RIL_REQUEST_SEND_SMS | 發送簡訊 |
RIL_REQUEST_SEND_SMS_EXPECT_MORE | 發送簡訊,且支持串聯簡訊 |
RIL_REQUEST_SETUP_DATA_CALL | 請求打開數據流量 |
RIL_REQUEST_SIM_IO | 獲取SIM卡號 |
RIL_REQUEST_SEND_USSD | 請求一個USSD業務(ussd即非結構化補充數據業務,是一種全球移動通信系統 (GSM) 協議,用於發送消息和文本文件。USSD代碼一般以*開頭,以#結尾,可用於執行一些隱藏功能。) |
RIL_REQUEST_CANCEL_USSD | 撤銷一個USSD業務 |
RIL_REQUEST_GET_CLIR | 查詢當前呼叫號碼是否隱藏請求 |
RIL_REQUEST_SET_CLIR | 設置呼叫號碼是否隱藏 |
RIL_REQUEST_QUERY_CALL_FORWARD_STATUS | 查詢呼叫轉移的狀態 |
RIL_REQUEST_SET_CALL_FORWARD | 設置呼叫轉移 |
RIL_REQUEST_QUERY_CALL_WAITING | 查詢呼叫等待信息 |
RIL_REQUEST_SET_CALL_WAITING | 設置呼叫等待狀態(當行動電話用戶正在進行通話時,又有呼叫向您發來。這時發起新呼叫的一方被置於等待,待原通話結束後再將新呼叫接入。) |
RIL_REQUEST_SMS_ACKNOWLEDGE | 用於簡訊消息的傳送應答 |
RIL_REQUEST_GET_IMEI | 獲取IMEI號 |
RIL_REQUEST_GET_IMEISV | 獲取IMEISV號(MEI有15位,最後一位是Check digit,即檢驗位;IMEISV有16位,是去掉了Check digit,加上了兩位SVN,即software version number。) |
RIL_REQUEST_ANSWER | 接聽電話請求 |
RIL_REQUEST_DEACTIVATE_DATA_CALL | 斷開數據流量業務 |
RIL_REQUEST_QUERY_FACILITY_LOCK | 查詢設備鎖定狀態 |
RIL_REQUEST_SET_FACILITY_LOCK | 設置設備鎖定狀態 |
RIL_REQUEST_CHANGE_BARRING_PASSWORD | 修改呼叫限制密碼 |
RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE | 查詢網路選擇 |
RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC | 設置網路選擇為自動 |
RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL | 設置網路選擇為手動 |
RIL_REQUEST_QUERY_AVAILABLE_NETWORKS | 查詢可用網路列表 |
RIL_REQUEST_DTMF_START | 啟動DTMF功能 |
RIL_REQUEST_DTMF_STOP | 關閉DTMF功能 |
RIL_REQUEST_BASEBAND_VERSION | 獲取基帶版本 |
RIL_REQUEST_SEPARATE_CONNECTION | 將所有激活的呼叫掛起 |
RIL_REQUEST_SET_MUTE | 設置靜音 |
RIL_REQUEST_ALLOW_DATA | 設置雙卡數據切換 |
RIL_REQUEST_GET_MUTE | 獲取靜音狀態 |
RIL_REQUEST_QUERY_CLIP | 查詢主叫號碼(主叫號碼識別顯示補充業務。CLIP是指被叫移動用戶的補充業務,移動用戶接收呼叫時,網路向用戶提示主叫用戶的號碼。) |
RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE | 查詢上一次數據連接失敗原因 |
RIL_REQUEST_DATA_CALL_LIST | 查詢數據連接信息 |
RIL_REQUEST_RESET_RADIO | 複位模塊 |
RIL_REQUEST_OEM_HOOK_RAW | ??? |
RIL_REQUEST_OEM_HOOK_STRINGS | ??? |
RIL_REQUEST_SCREEN_STATE | 查詢屏幕狀態 |
RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION | 啟用/禁用來自網路的補充服務相關通知 |
RIL_REQUEST_WRITE_SMS_TO_SIM | 複製簡訊到SIM卡中 |
RIL_REQUEST_DELETE_SMS_ON_SIM | 刪除SIM卡簡訊 |
RIL_REQUEST_SET_BAND_MODE | 設置頻段模式 |
RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE | 查詢可用頻段模式 |
RIL_REQUEST_STK_GET_PROFILE | 查詢STK的配置信息 |
RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND | 請求打開STK子菜單 |
RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE | 獲取STK子菜單信息 |
RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM | 接受或拒絕來自SIM卡的呼叫設置請求。 |
RIL_REQUEST_EXPLICIT_CALL_TRANSFER | 請求呼叫轉接業務 |
RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE | 設置偏好的網路類型 |
RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE | 獲取偏好的網路類型 |
RIL_REQUEST_GET_NEIGHBORING_CELL_IDS | 獲取此設備上的相鄰單元列表 |
RIL_REQUEST_SET_LOCATION_UPDATES | 位置更新 |
RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE | 請求設置CDMA訂閱模式 |
RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE | 設置偏好漫游類型 |
RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE | 查詢偏好漫游類型 |
RIL_REQUEST_SET_TTY_MODE | 設置為聾啞模式 |
RIL_REQUEST_QUERY_TTY_MODE | 查詢聾啞模式狀態 |
RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE | 設置首選語音隱私(VP) |
RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE | 獲取當前設置的首選語音隱私(VP)模式。 |
RIL_REQUEST_CDMA_FLASH | ??? |
RIL_REQUEST_CDMA_BURST_DTMF | 發起DTMS請求 |
RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY | ??? |
RIL_REQUEST_CDMA_SEND_SMS | CDMA發送簡訊 |
RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE | CDMA簡訊消息的傳送應答 |
RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG | 獲取小區廣播配置,通過小區廣播通道(CBCH)將信息(如地理位置、天氣狀況等信息)傳到手機,再由用戶選擇接收的一種功能,通過此功能可向用戶提供位置信息,天氣預報等服務;是向中國移動的手機客戶按區域、按頻道發送各種實時、動態的分類信息的業務。 |
RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG | 設置小區廣播配置 |
RIL_REQUEST_GSM_SMS_BROADCAST_ACTIVATION | 小區廣播功能開關 |
RIL_REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG | CDMA獲取小區廣播配置 |
RIL_REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG | CDMA設置小區廣播配置 |
RIL_REQUEST_CDMA_SMS_BROADCAST_ACTIVATION | CDMA小區廣播開關 |
RIL_REQUEST_CDMA_SUBSCRIPTION | 查詢CDMA的實現模式(CDMA手機兩實現模式: 機卡分離式:用戶信息寫在單獨的UIM 卡機卡一體式:用戶信息寫在手機中的) |
RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM | CDMA複製短息到uim卡,RUIM是應用在CDMA2000手機的一種智能卡 |
RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM | CDMA刪除RUIM卡上簡訊 |
RIL_REQUEST_DEVICE_IDENTITY | 請求設備標識 |
RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE | 離開緊急回撥模式 |
RIL_REQUEST_GET_SMSC_ADDRESS | 獲取SMSC地址,網路簡訊息服務中心地址 |
RIL_REQUEST_SET_SMSC_ADDRESS | 設置SMSC地址 |
RIL_REQUEST_REPORT_SMS_MEMORY_STATUS | 通知modem,SMS的存儲情況 |
RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING | 通知modem,StkService已經啟動 |
RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE | 設置CDMA的實現模式 |
RIL_REQUEST_ISIM_AUTHENTICATION | ISIM認證 |
RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU | 確認收到成功或失敗的最後一條傳入簡訊,包括確認TPDU作為RP-ACK或RP-ERROR PDU的RP-User-Data元素髮送。 |
RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS | ??? |
RIL_REQUEST_VOICE_RADIO_TECH | 獲取當前的語音無線電技術。 |
RIL_REQUEST_GET_CELL_INFO_LIST | 獲取當前的信元信息 |
RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE | 設置信元信息的調用時間,即onCellInfoChanged的響應時間 |
RIL_REQUEST_SET_INITIAL_ATTACH_APN | 初始化APN |
RIL_REQUEST_IMS_REGISTRATION_STATE | 查詢IMS的註冊狀態 |
RIL_REQUEST_IMS_SEND_SMS | 請求IMS發送簡訊 |
RIL_REQUEST_SIM_TRANSMIT_APDU_BASIC | 在基本頻道上與SIM交換apdu |
RIL_REQUEST_SIM_OPEN_CHANNEL | 打開SIM無線通道 |
RIL_REQUEST_SIM_CLOSE_CHANNEL | 關閉SIM無線通道 |
RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL | 在邏輯通道上與SIM交換APDU。 |
RIL_REQUEST_NV_READ_ITEM | 讀取{@link RadioNVItems} / {@code ril_nv_items.h}中定義的NV項之一,用於部分CDMA運營商的設備配置。 |
RIL_REQUEST_NV_WRITE_ITEM | 寫一個定義在{@link RadioNVItems} / {@code ril_nv_items.h}的NV項,用於部分CDMA運營商的設備配置。 |
RIL_REQUEST_NV_WRITE_CDMA_PRL | 更新無線電NV存儲中的CDMA首選漫游列表(PRL)。用於部分CDMA運營商的設備配置。 |
RIL_REQUEST_NV_RESET_CONFIG | 執行modem配置複位。用於部分CDMA運營商的設備配置。 |
RIL_REQUEST_SET_UICC_SUBSCRIPTION | ??? |
RIL_REQUEST_ALLOW_DATA | 雙卡數據切換 |
RIL_REQUEST_GET_HARDWARE_CONFIG | 獲取RIL的硬體配置 |
RIL_REQUEST_SIM_AUTHENTICATION | SIM卡身份認證 |
RIL_REQUEST_GET_DC_RT_INFO | ??? |
RIL_REQUEST_SET_DC_RT_INFO_RATE | ??? |
RIL_REQUEST_SET_DATA_PROFILE | 發送當前運營商的數據配置文件到數據服務進行數據呼叫設置。這是僅適用於CDMA運營商,可通過OTA更改配置文件。數據服務應該總是使用最新的數據配置文件發送的框架。 |
RIL_REQUEST_SHUTDOWN | 關機 |
RIL_REQUEST_GET_RADIO_CAPABILITY | 獲取電話無線電功能 |
RIL_REQUEST_SET_RADIO_CAPABILITY | 設置電話無線電類型和接入技術。 |
RIL_REQUEST_START_LCE | 啟動LCE(鏈路容量估計)服務,並設置所需的報告間隔。 |
RIL_REQUEST_STOP_LCE | 停止LCE服務。 |
RIL_REQUEST_PULL_LCEDATA | 獲取LCE服務獲取容量數據。 |
RIL_REQUEST_GET_ACTIVITY_INFO | 請求modem的活動信息 |
RIL_REQUEST_SET_CARRIER_RESTRICTIONS | ??? |
RIL_REQUEST_GET_CARRIER_RESTRICTIONS | ??? |
RIL_REQUEST_SEND_DEVICE_STATE | 發送設備狀態到Modem |
RIL_REQUEST_SET_UNSOLICITED_RESPONSE_FILTER | 打開/關閉數據機的主動響應 |
RIL_REQUEST_SET_SIM_CARD_POWER | 設置SIM卡上電狀態。 @param state SIM卡狀態(斷電、上電、通過) |
RIL_REQUEST_SET_CARRIER_INFO_IMSI_ENCRYPTION | 設置加密IMSI和IMPI所需的運營商信息。 |
RIL_REQUEST_START_NETWORK_SCAN | 掃描網路 |
RIL_REQUEST_STOP_NETWORK_SCAN | 停止掃描網路 |
RIL_REQUEST_START_KEEPALIVE | 啟動長連接 |
RIL_REQUEST_STOP_KEEPALIVE | 停止長連接 |
6.2 RILJ被動接收指令
源碼: android\hardware\ril\libril\ril_unsol_commands.h
指令 | 功能 |
---|---|
RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED | 無線通信模塊狀態改變 |
RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED | 來電狀態改變 |
RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED | 信號狀態改變 |
RIL_UNSOL_RESPONSE_NEW_SMS | 收到簡訊 |
RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT | 簡訊發送狀態報告 |
RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM | ??? |
RIL_UNSOL_ON_USSD | ??? |
RIL_UNSOL_ON_USSD_REQUEST | ??? |
RIL_UNSOL_NITZ_TIME_RECEIVED | 通知更新終端系統的時間及時區 |
RIL_UNSOL_DATA_CALL_LIST_CHANGED | 數據連接狀態改變 |
RIL_UNSOL_SUPP_SVC_NOTIFICATION | ??? |
RIL_UNSOL_STK_SESSION_END | 通知會話結束 |
RIL_UNSOL_STK_PROACTIVE_COMMAND | 插卡開機,Modem檢測到有卡插入,這時候Modem會讀取SIM中的相關信息,並把消息上報給RIL層,顯示STK主菜單 |
RIL_UNSOL_STK_EVENT_NOTIFY | 用於STK事件分發 |
RIL_UNSOL_STK_CALL_SETUP | 發送來自modem的撥打電話的主動上報消息 |
RIL_UNSOL_SIM_SMS_STORAGE_FULL | 通知空間滿了 |
RIL_UNSOL_SIM_REFRESH | modem請求更新卡對應的文件信息 |
RIL_UNSOL_CALL_RING | 有來電時上報 |
RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED | SIM卡狀態改變 |
RIL_UNSOL_RESPONSE_CDMA_NEW_SMS | 接收到CDMA簡訊 |
RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS | ??? |
RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL | ??? |
RIL_UNSOL_RESTRICTED_STATE_CHANGED | 受限策略改變通知 |
RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE | 進入緊急回撥模式通知 |
RIL_UNSOL_CDMA_CALL_WAITING | 呼叫等待通知 |
RIL_UNSOL_CDMA_OTA_PROVISION_STATUS | ??? |
RIL_UNSOL_CDMA_INFO_REC | ??? |
RIL_UNSOL_OEM_HOOK_RAW | ??? |
RIL_UNSOL_RINGBACK_TONE | 電話鈴聲 |
RIL_UNSOL_RESEND_INCALL_MUTE | ??? |
RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED | 管理 機卡分離 Or 機卡一體的消息 |
RIL_UNSOL_CDMA_PRL_CHANGED | 優選漫游列表更新通知 |
RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE | 離開緊急回撥模式通知 |
RIL_UNSOL_RIL_CONNECTED | RIL連接成功通知 |
RIL_UNSOL_VOICE_RADIO_TECH_CHANGED | ??? |
RIL_UNSOL_CELL_INFO_LIST | ??? |
RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED | ??? |
RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED | ??? |
RIL_UNSOL_SRVCC_STATE_NOTIFY | ??? |
RIL_UNSOL_HARDWARE_CONFIG_CHANGED | ??? |
RIL_UNSOL_DC_RT_INFO_CHANGED | ??? |
RIL_UNSOL_RADIO_CAPABILITY | ??? |
RIL_UNSOL_ON_SS | ??? |
RIL_UNSOL_STK_CC_ALPHA_NOTIFY | ??? |
RIL_UNSOL_LCEDATA_RECV | ??? |
RIL_UNSOL_PCO_DATA | ??? |
RIL_UNSOL_MODEM_RESTART | modem重啟通知 |
RIL_UNSOL_CARRIER_INFO_IMSI_ENCRYPTION | ??? |
RIL_UNSOL_NETWORK_SCAN_RESULT | 通知網路掃描結果 |
RIL_UNSOL_KEEPALIVE_STATUS | 通知心跳狀態 |
七、參考資料
https://source.android.google.cn/docs/core/connect/ims?hl=zh-cn
http://www.taodudu.cc/news/show-3144813.html?action=onClick
http://baike.jld5.cn/news/51009.html
https://wiki.mbalib.com/wiki/IMS
https://blog.csdn.net/guyuewangyue/article/details/122866358
電路交換和分組交換區別:
https://www.elecfans.com/d/1308634.html
TeleComService介紹:
https://blog.csdn.net/qq_40587575/article/details/113753895
TeleService介紹:
https://www.jianshu.com/p/ff51295b84a1
Rild介紹:
https://www.freesion.com/article/21011164222/
https://blog.csdn.net/u014386544/article/details/52594400
RIL指令:
https://www.mianshigee.com/note/detail/23890yjg/
https://blog.csdn.net/iteye_6233/article/details/82230745
https://blog.csdn.net/u010961631/article/details/9446377/
https://blog.csdn.net/sjz4860402/article/details/51182078
http://www.2sim.cn/article/13
https://zhuanlan.zhihu.com/p/117218424
https://blog.csdn.net/u014386544/article/details/56851616