Android call setting 源碼分析 從頂層到底層(上)

來源:互聯網
上載者:User

Android 的 call setting 是用來設定與 simcard 相關的一些內容的應用程式,如網路,PIN等等,算是AP層。這裡就選擇其中一個項從原始碼讀下去直到底層,看看大概的結構和流程。

 在 Android 主菜單中選擇 setting->call setting->additional call setting->caller ID,會彈出來一個對話方塊來選擇,這個項是用來設定在用電話本撥打到電話的時候是否顯示對方的電話號碼。這裡就以這個設定為例來一步步讀下去。

 

AP層:

 call setting 的代碼和資源都是放在/packages/apps/Phone 的目錄下。其實 Android 的 setting AP 相關的資源都是放在/packages/apps/setting 下的。但是看 /packages/apps/Settings/res/xml/settings.xml 中:

 

 <PreferenceScreen android:key="call_settings" android:title="@string/call_settings_title" android:summary="@string/call_settings_summary">

 <intent android:action="android.intent.action.MAIN" android:targetPackage="com.android.phone" android:targetClass="com.android.phone.CallFeaturesSetting" />
 </PreferenceScreen>

 從這裡就可以知道,android 的call setting 的包指向了 phone,並且知道了入口是 CallFeaturesSetting 類。
 在/packages/apps/Phone/res/call_featrue_setting.xml 中有call setting 的介面布局:
 <PreferenceScreen android:key="button_more_expand_key" android:title="@string/labelMore" android:persistent="false">
 ...
 


 <ListPreference android:key="button_clir_key" ... />
 這個button_clir_key就是對應的 caller ID 的那個按鈕,從這裡可以看出是一個ListPreference,點擊會出現一個列表框。裡面出現的內容布局都在這裡定義。相關的xml檔都在/packages/apps/Phone/res 下。
 接著就是AP的代碼了,在/packages/apps/Phone/src 下。前面說了入口是 CallFeaturesSetting:
 public class CallFeaturesSetting extends PreferenceActivity {
    …

    private PreferenceScreen mSubMenuFDNSettings;

    private ListPreference mButtonCLIR;

    private CheckBoxPreference mButtonCW;

  ...

  protected void onCreate(…) {

    …


    PreferenceScreen prefSet = getPreferenceScreen();

     mButtonCLIR  =   (ListPreference) prefSet.findPreference(BUTTON_CLIR_KEY);

  ...

 定義的 mButtonCLIR 就是對應caller ID 的變數。在onCreate中初始化,用findPreference來找到XML中對應的資源。

 然後是對這個按鈕的響應代碼:

 

 public boolean onPreferenceChange(Preference preference, Object objValue){

   if (preference == mButtonCLIR) {

   handleCLIRClickRequest(mButtonCLIR.findIndexOfValue((String) objValue));

  ...

 }

 private void handleCLIRClickRequest(int i) {

   …

    mPhone.setOutgoingCallerIdDisplay(i,Message.obtain(mSetOptionComplete, EVENT_CLIR_EXECUTED));

 }

 

 可以看到最終是調用 mPhone.setOutgoingCallerIdDisplay 來完成真正的設定。這個 mPhone 是

com.android.internal.telephony.Phone,mPhone 的調用就進入 framework 層了。

 

Framework層:

 相關的代碼在/frameworks/base/telephony/java 中。先從 Phone 開始,這是一個 interface,真正實現是在

com.android.internal.telephony.gsm.GSMPhone 中:

 

 public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete) {
         mCM.setCLIR(commandInterfaceCLIRMode,
                 h.obtainMessage(EVENT_SET_CLIR_COMPLETE, commandInterfaceCLIRMode, 0, onComplete));
     }

 

 這裡是調用 mCM.setCLIR。mCM 是一個 CommandsInterface,真正實現是在 RIL.java 檔案中。這下到了framework中

真正辦實事的地方。同樣是在com.android.internal.telephony.gsm 下,RIL類中:

 

     public void setCLIR(int clirMode, Message result)

     {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_SET_CLIR, result);
         rr.mp.writeInt(1);
         rr.mp.writeInt(clirMode);
           

  ...
         send(rr);
     }

 

 這裡順便說一下,RIL與底層是用socket來通訊。所以send(rr)最終是把RIL_REQUEST_SET_CLIR發給底層,底層會有一個守護

進程來接收framework層的資訊,並且把結果傳達上去。繼續看下send的代碼:

 

 private void  send(RILRequest rr)
     {
         Message msg;
         msg = mSender.obtainMessage(EVENT_SEND, rr);
         acquireWakeLock();
         msg.sendToTarget();
     }

 

 是發一個EVENT_SEND的message給系統。那麼找這個 handle 這個 message 的地方,還是同一個檔案裡,RIL.RILSender類

裡面的handleMessage:

 

 public void  handleMessage(Message msg)

 {

  RILRequest rr = (RILRequest)(msg.obj);

  switch (msg.what) {
                case EVENT_SEND:


                        LocalSocket s;
                        s = mSocket;


   ...
                        byte[] data;
                        data = rr.mp.marshall();
                        rr.mp.recycle();
                        rr.mp = null;
                        // parcel length in big endian
                        dataLength[0] = dataLength[1] = 0;
                        dataLength[2] = (byte)((data.length >> 8) & 0xff);
                        dataLength[3] = (byte)((data.length) & 0xff);
                        s.getOutputStream().write(dataLength);                   
                        s.getOutputStream().write(data);

 ...

 

 這裡的mSocket 在就是與底層溝通的socket,有興趣可以看看相關代碼。

 到這裡 framework 層也算告一段落,在下去就是底層的C部分了。放在下一篇文章在寫吧。


作者 liujian885

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.