android系统中Phone类型配置

来源:互联网 发布:抢购软件 编辑:程序博客网 时间:2024/05/21 08:50

android系统启动起来后,在 telephony framework层,该启动 CDMAPhone 还是 GSMPhone ?

先从网上摘一段说明:

Phone描述了对电话的所有操作接口。PhoneBase直接从Phone 派生而来。而另外两个类,CDMAPhone和GSMPhone,又从PhoneBase派生而来,分别代表对CDMA 和GSM的操作。

PhoneProxy也从Phone直接派生而来。当前不需要区分具体是CDMA Phone还是GSM Phone时,可使用PhoneProxy。GSMPhone和CDMAPhone实现了Phone中定义的接口。接口类Phone定义了一套API,这套API用于使用RIL发送AT命令请求,也还有一套register和unregister函数;当调用者对一些内部状态感兴趣时,可以调用对应的register函数,当状态变化时可以得到及时通知。

PhoneBase实现了Phone接口中定义的部分函数,还有一部分由其子类GSMPhone和CDMAPhone实现。honeProxy是GSMPhone和CDMAPhone的代理,让使用者不用关注手机到底是GSM还是CDMA,它遵守Phone定义的API接口,因此继承Phone。

PhoneFactory在创建Phone对象时,拥有的是PhoneProxy对象,PhoneProxy根据实际的网络类型创建对应的GSMPhone或CDMAPhone。PhoneFactory同样拥有CommandInterface的接口对象,即RIL的实例,该RIL实例将被传递给GSMPhone或CDMAPhone,即GSMPhone或CDMAPhone引用它,实现与rild的交互。

GSMPhone和CDMAPhone继承自PhoneBase,它们(包括PhoneProxy)都是一个Handler。这样,它们就可以在线程的循环Looper.loop中处理来自RILJ或自身发送的各种Message。PhoneFactory负责创建各个Phone实例,其成员及成员函数为static,可以保证创建的实例在系统运行时的唯一性。

详细介绍请查看 Android Phone设计介绍 


查看了好多资料,都没有看到介绍如何来配置当前系统的Phone类型,大多数都是先假设为GSMPhone类型,然后继续讲解RIL流程。

下面我们就来分析下android中系统中是如何确定Phone类型的:

1 在 packages\apps\Phone\src\com\android\phone\PhoneApp.java的oncreate函数中

onCreate() {...// Initialize the telephony frameworkPhoneFactory.makeDefaultPhones(this);// Get the default phonephone = PhoneFactory.getDefaultPhone();...}

2 我们跳转到PhoneFactory.java中的makeDefaultPhones函数,在此函数中继续调用makeDefaultPhone(context)

makeDefaultPhone(Context context) {...    int preferredNetworkMode = RILConstants.PREFERRED_NETWORK_MODE;    int networkMode = Settings.Secure.getInt(context.getContentResolver(),                        Settings.Secure.PREFERRED_NETWORK_MODE, preferredNetworkMode);...int phoneType = getPhoneType(networkMode);                if (phoneType == Phone.PHONE_TYPE_GSM) {                    Log.d(LOG_TAG, "Creating GSMPhone");                    sProxyPhone = new PhoneProxy(new GSMPhone(context,                            sCommandsInterface, sPhoneNotifier));                } else if (phoneType == Phone.PHONE_TYPE_CDMA) {                    switch (BaseCommands.getLteOnCdmaModeStatic()) {                        case Phone.LTE_ON_CDMA_TRUE:                            Log.d(LOG_TAG, "Creating CDMALTEPhone");                            sProxyPhone = new PhoneProxy(new CDMALTEPhone(context,                                sCommandsInterface, sPhoneNotifier));                            break;                        case Phone.LTE_ON_CDMA_FALSE:                        default:                            Log.d(LOG_TAG, "Creating CDMAPhone");                            sProxyPhone = new PhoneProxy(new CDMAPhone(context,                                    sCommandsInterface, sPhoneNotifier));                            break;                    }                }...}

在RILConstants.java中有定义

int NETWORK_MODE_WCDMA_PREF     = 0; /* GSM/WCDMA (WCDMA preferred) */
int NETWORK_MODE_CDMA           = 4; /* CDMA and EvDo (auto mode, according to PRL)
int PREFERRED_NETWORK_MODE      = NETWORK_MODE_WCDMA_PREF;

在frameworks\base\core\java\android\provider\Settings.java中有定义
public static final String PREFERRED_NETWORK_MODE = "preferred_network_mode";
所以,preferredNetworkMode = RILConstants.PREFERRED_NETWORK_MODE;是先设置默认为GSMPhone类型

从 Settings.Secure.getInt(context.getContentResolver(),Settings.Secure.PREFERRED_NETWORK_MODE, preferredNetworkMode);
我们可以知道判断Phone类型时从secure数据库中读取"preferred_network_mode"字段的取值来确定的getPhoneType(networkMode)是将读到的值转换为Phone类型值,这个很简单不分析啦!

接下来要分析的是什么地方会写secure数据库中"preferred_network_mode"字段的值呢?


3 secure数据库是在首次开机的时候创建的,我们可以通过恢复出厂设置来模拟首次开机的情况
在frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\DatabaseHelper.java的Oncreate函数中有:

createSecureTable(db);loadSettings(db);private void createSecureTable(SQLiteDatabase db) {        db.execSQL("CREATE TABLE secure (" +                "_id INTEGER PRIMARY KEY AUTOINCREMENT," +                "name TEXT UNIQUE ON CONFLICT REPLACE," +                "value TEXT" +                ");");        db.execSQL("CREATE INDEX secureIndex1 ON secure (name);");    }private void loadSettings(SQLiteDatabase db) {        loadSystemSettings(db);       loadSecureSettings(db);  //我们要分析的是这里  }

在loadSecureSettings函数中:
int type;        if (BaseCommands.getLteOnCdmaModeStatic() == Phone.LTE_ON_CDMA_TRUE) {            type = Phone.NT_MODE_GLOBAL;        } else {            type = SystemProperties.getInt("ro.telephony.default_network",                                                RILConstants.PREFERRED_NETWORK_MODE);        }        loadSetting(stmt, Settings.Secure.PREFERRED_NETWORK_MODE, type);

看到这里,我们知道Phone类型是由上面的type取值决定的

BaseCommands.getLteOnCdmaModeStatic( ) 一般返回Phone.LTE_ON_CDMA_FALSE,目前还没碰到为LTE_ON_CDMA_TRUE的情况,暂不分析这个。

那么我们看下面的分支:

SystemProperties.getInt("ro.telephony.default_network",  RILConstants.PREFERRED_NETWORK_MODE);

分析到这里就知道了 Phone类型最终是由 系统属性"ro.telephony.default_network"来配置的


好啦,我们可以配置Phone的类型啦:

GSMPhone:  

  设置  ro.telephony.default_network=0     //即 NETWORK_MODE_WCDMA_PREF 

   或者 不添加系统属性ro.telephony.default_network,这样就直接用默认值PREFERRED_NETWORK_MODE

CDMAPhone:

设置  ro.telephony.default_network=4     //即 NETWORK_MODE_CDMA


0 0
原创粉丝点击