Android指令處理流程源碼追蹤

1.撥號界面輸入*#06#,顯示IMEI號,這是怎麼出來的?

2.如何快速的找出Android平臺中的指令?


1. 在DialpadFragment中的EditText註冊一個Textchanged的監聽器TextWatcher,

   當EditText中的內容發生變化時會調用相應的回調函數,TextWatcher是一個接口:

public interface TextWatcher extends NoCopySpan {
    public void beforeTextChanged(CharSequence s, int start,int count, int after);
    public void onTextChanged(CharSequence s, int start, int before, int count);
    public void afterTextChanged(Editable s);
}
在DialpadFragment中實現了該接口:

    public void afterTextChanged(Editable input) {
        // When DTMF dialpad buttons are being pressed, we delay SpecialCharSequencMgr sequence,
        // since some of SpecialCharSequenceMgr's behavior is too abrupt for the "touch-down"
        // behavior.
        if (!mDigitsFilledByIntent &&
                SpecialCharSequenceMgr.handleChars(getActivity(), input.toString(), mDigits)) {
            // A special sequence was entered, clear the digits
            mDigits.getText().clear();
        }
        if (isDigitsEmpty()) {
            mDigitsFilledByIntent = false;
            mDigits.setCursorVisible(false);
        }else {
		mDigits.setCursorVisible(true);  
	}

        updateDialAndDeleteButtonEnabledState();
        loadSmartDialEntries();

        refreshDigitTextSize(input);
    }
指令處理的主角:SpecialCharSequenceMgr.handleChars(getActivity(), input.toString(), mDigits)

看 其方法的主體:

    static boolean handleChars(Context context, String input, boolean useSystemWindow,
            EditText textField) {

        //get rid of the separators so that the string gets parsed correctly
        String dialString = PhoneNumberUtils.stripSeparators(input);

        if (handlePRLVersion(context, dialString)
                || handleModemTestDisplay(context, dialString)
                || handleIMEIDisplay(context, dialString, useSystemWindow)
                || handleRegulatoryInfoDisplay(context, dialString)
                || handlePinEntry(context, dialString)
                || handleAdnEntry(context, dialString, textField)
                || handleSecretCode(context, dialString)
            return true;
        }

        return false;
    }
這裏有個handleIMEIDisplay(context, dialString, useSystemWindow),看其主體:

    static boolean handleIMEIDisplay(Context context, String input, boolean useSystemWindow) {
        if (input.equals(MMI_IMEI_DISPLAY)) {   <span style="color:#3333ff;"> //</span><span style="font-family: Arial, Helvetica, sans-serif;"><span style="color:#3333ff;">MMI_IMEI_DISPLAY = "*#06#"</span></span>
            if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) {
                return handleMSimIMEIDisplay(context);<span style="background-color: rgb(255, 255, 255);"><span style="color:#3333ff;">//顯示IMEI號</span></span>
            }
            int subscription = MSimTelephonyManager.getDefault().getPreferredVoiceSubscription();
            int phoneType;
            if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) {
                phoneType = ((MSimTelephonyManager)context.getSystemService(
                        Context.MSIM_TELEPHONY_SERVICE)).getCurrentPhoneType(subscription);
            } else {
                phoneType = ((TelephonyManager)context.getSystemService(
                        Context.TELEPHONY_SERVICE)).getCurrentPhoneType();
            }
         if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
                showIMEIPanel(context, useSystemWindow);<span style="font-family: Arial, Helvetica, sans-serif;"><span style="color:#3333ff;">//顯示IMEI號</span></span>
                return true;
            } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
                showMEIDPanel(context, useSystemWindow);<span style="font-family: Arial, Helvetica, sans-serif;"><span style="color:#3333ff;">//顯示IMEI號</span></span>
                return true;
            }
        }

        return false;
    }
至此IMEI號的顯示流程都呈現出來。

2.在handleChars中還有對其他指令進行處理的方法:

handleModemTestDisplay、handleRegulatoryInfoDisplay、handleSecretCode等,

其中handleSecretCode是對*#*#。。#*#* 這一類的指令進行集中處理,看源碼:

  static boolean handleSecretCode(Context context, String input) {
        // Secret codes are in the form *#*#<code>#*#*
        int len = input.length();
        if (len > 8 && input.startsWith("*#*#") && input.endsWith("#*#*")) {

            Intent intent = new Intent(TelephonyIntents.SECRET_CODE_ACTION,
                    Uri.parse("android_secret_code://" + input.substring(4, len - 4)));
            context.sendBroadcast(intent);
            return true;
        }

        return false;
    }
可以看到是發送的一個廣播,廣播的action是 :

public static final String SECRET_CODE_ACTION ="android.provider.Telephony.SECRET_CODE";
data是一個URI,

所以在平臺裏面的所有AndroidManifest.xml 文件中查找android.provider.Telephony.SECRET_CODE,

即可找出平臺中所有*#*#。。#*#* 類型的指令,如:

<receiver android:name="TestingSettingsBroadcastReceiver">
            <intent-filter>
                 <action android:name="android.provider.Telephony.SECRET_CODE" />
                 <data android:scheme="android_secret_code" android:host="837851" />
            </intent-filter>
</receiver>


     <receiver android:name="TestingSettingsBroadcastReceiver">
            <intent-filter>
                 <action android:name="android.provider.Telephony.SECRET_CODE" />
                 <data android:scheme="android_secret_code" android:host="4636" />
            </intent-filter>
       </receiver>







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章