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>

Android指令处理流程源码追踪,布布扣,bubuko.com

时间: 2024-10-23 20:28:48

Android指令处理流程源码追踪的相关文章

Activity启动流程源码分析之Launcher启动(二)

1.前述 在前一篇文章中我们简要的介绍Activity的启动流程Activity启动流程源码分析之入门(一),当时只是简单的分析了一下流程,而且在上一篇博客中我们也说了Activity的两种启动方式,现在我们就来分析其中的第一种方式--Launcher启动,这种启动方式的特点是会创建一个新的进程来加载相应的Activity(基于Android5.1源码). 2.Activity启动流程时序图 好啦,接下来我们先看一下Launcher启动Activity的时序图: 好啦,接下来我们将上述时序图用代

JobTracker启动流程源码级分析

org.apache.hadoop.mapred.JobTracker类是个独立的进程,有自己的main函数.JobTracker是在网络环境中提交及运行MR任务的核心位置. main方法主要代码有两句: 1 //创建jobTracker对象 2 JobTracker tracker = startTracker(new JobConf()); 3 //启动各个服务,包括JT内部一些重要的服务或者线程 4 tracker.offerService(); 一.startTracker(new Jo

A2dp初始化流程源码分析

蓝牙启动的时候,会涉及到各个profile 的启动.这篇文章分析一下,蓝牙中a2dp profile的初始化流程. 我们从AdapterState.java中对于USER_TURN_ON 消息的处理说起: switch(msg.what) { case USER_TURN_ON: notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_ON); mPendingCommandState.setTurningOn(true); transit

SpringSecurity 默认表单登录页展示流程源码

SpringSecurity 默认表单登录页展示流程源码 本篇主要讲解 SpringSecurity提供的默认表单登录页 它是如何展示的的流程, 涉及 1.FilterSecurityInterceptor, 2.ExceptionTranslationFilter , 3.DefaultLoginPageGeneratingFilter 过滤器, 并且简单介绍了 AccessDecisionManager 投票机制 ?1.准备工作(体验SpringSecurity默认表单认证) ??1.1 创

Android Touch事件派发流程源码分析

分native侧事件派发到java侧和Framework派发事件到UI,流程看源码即可,此处不赘叙, Native侧派发事件的干活类图如下: Framework侧派发事件的类图如下: 从Activity.dispatchTouchEvent开始,Action_Down事件派发的时序如下: 分析Android 5.0源码可知,ViewGroup的事件派发是一个后序遍历树的递归过程,在Action_Down事件的处理中做了两个事情: 1.递归查找touchTarget,并标记在ViewGroup的m

5.Spark Streaming流计算框架的运行流程源码分析2

1 spark streaming 程序代码实例 代码如下: [html] view plain copy object OnlineTheTop3ItemForEachCategory2DB { def main(args: Array[String]){ val conf = new SparkConf() //创建SparkConf对象 //设置应用程序的名称,在程序运行的监控界面可以看到名称 conf.setAppName("OnlineTheTop3ItemForEachCategor

HBase的put流程源码分析

hbase是一个nosql型数据库,本文我们会分析一下客户的数据是通过什么样的路径写入到hbase的. HBase作为一种列族数据库,其将相关性较高的列聚合成一个列族单元,不同的列族单元物理上存储在不同的文件(HFile)内.一个表的数据会水平切割成不同的region分布在集群中不同的regionserver上.客户端访问集群时会首先得到该表的region在集群中的分布,之后的数据交换由客户端和regionserver间通过rpc通信实现,下面我们从hbase源码里探究客户端put数据的流程.本

Spring Security教程(八):用户认证流程源码详解

本篇文章主要围绕下面几个问题来深入源码: 用户认证流程 认证结果如何在多个请求之间共享 获取认证用户信息 一.用户认证流程 上节中提到Spring Security核心就是一系列的过滤器链,当一个请求来的时候,首先要通过过滤器链的校验,校验通过之后才会访问用户各种信息. 这里要说明的是在过滤器的最前端有一个SecurityContextPersistenceFilter,当请求进来和返回的时候都会经过这个过滤器,它主要存放用户的认证信息.这里先简单提一下,后面会详解. 当用户发送登录请求的时候(

neutron ml2 network创建流程源码解析

Neutron的整体架构分为三层. Server —> plugin —>agent 启动server之后neutron会将请求路径和对应的处理函数进行映射. 具体的处理函数由plugin来提供,plugin做的事情有两个: 1)在数据库中创建资源 2)发送rpc请求到具体的agent 所有的plugin提供统一的接口,包括核心资源的增删改查. neutron原生提供ml2这一plugin,ml2plugin分为类型驱动和机制驱动. 下面从创建network的角度来看一下neutron的整个调