您的位置:首页 > 移动开发 > Android开发

Android L Phone进程初始化_02

2015-02-26 19:28 337 查看
本文代码目录以高通平台Android 5.0为基础,可能与AOSP有不同之处。

* 如转帖请注明它来自这里 http://blog.csdn.net/shrimpcolo?viewmode=contents*

概述

上一篇文章主要是说明了2个问题:Phone进程初始化

1) Phone进程在创建过程中的入口以及各个关系类的用途,没有深入展开

2) RIL的实例化过程

那么本篇是在上文的基础上,针对各个关系类展开描述。目的还是只有一个,剥洋葱!!

目标

针对上文中的主要关系类,展开学习。主要是学习,在Phone进程中有什么作用,扮演什么角色。

梳理清楚几个关键的消息注册,包括MT(来电)消息注册,状态改变消息注册。这是基础,懂得了这些,会有助于分析定位问题。

—————————————–感觉又是一个坑啊———————————————

再探PhoneGlobal

public void onCreate() {
if (VDBG) Log.v(LOG_TAG, "onCreate()...");

ContentResolver resolver = getContentResolver();

// Cache the "voice capable" flag.
// This flag currently comes from a resource (which is
// overrideable on a per-product basis):
sVoiceCapable =
getResources().getBoolean(com.android.internal.R.bool.config_voice_capable);
// ...but this might eventually become a PackageManager "system
// feature" instead, in which case we'd do something like:
// sVoiceCapable =
//   getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_VOICE_CALLS);

if (phone == null) {
// Initialize the telephony framework
//这就是上篇的主要内容,初始化Phone数组,RIL数组,PhoneProxy... ...
PhoneFactory.makeDefaultPhones(this);
//忽略此处,(其实很重要,是跟双卡侦测有关系的)
int numPhones = TelephonyManager.getDefault().getPhoneCount();
if(numPhones > 1) PrimarySubSelectionController.init(this);

// Get the default phone
//得到默认的Phone接口,其实就是在PhoneFactory中的sProxyPhones[0]
/* //使用默认的phoneproxy和RIL接口
//sProxyPhone = sProxyPhones[0];
*/
phone = PhoneFactory.getDefaultPhone();

// Start TelephonyDebugService After the default phone is created.
Intent intent = new Intent(this, TelephonyDebugService.class);
startService(intent);

//这个是高通自有的,phone 和 mPhones的关系是, phone = mPhones[0]
mPhones = new PhoneProxy[numPhones];
mPhones = PhoneFactory.getPhones();

*1) CallManager是phone进程的一部分,负责消息注册 处理,上报,承上启下的作用.*
mCM = CallManager.getInstance();
for (Phone ph : mPhones) {
mCM.registerPhone(ph);//注册的部分,细节需要说明
}

// Create the NotificationMgr singleton, which is used to display
// status bar icons and control other status bar behavior.
*2) 这里会稍微说明下,以后会写一篇关于通话过程中的notification显示的文章*
notificationMgr = NotificationMgr.init(this);

mHandler.sendEmptyMessage(EVENT_START_SIP_SERVICE);
//获得phone type类型,这个是在new phone的时候就知道了的
int phoneType = phone.getPhoneType();

if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
// Create an instance of CdmaPhoneCallState and initialize it to IDLE
cdmaPhoneCallState = new CdmaPhoneCallState();
cdmaPhoneCallState.CdmaPhoneCallStateInit();
}
//以下是些其他重要的东西,电话会跟电源相关,会有自己的wakelock, 当然也跟Keygurad有联系
// before registering for phone state changes
mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, LOG_TAG);
// lock used to keep the processor awake, when we don't care for the display.
mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK
| PowerManager.ON_AFTER_RELEASE, LOG_TAG);

mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);

// get a handle to the service so that we can use it later when we
// want to set the poke lock.
mPowerManagerService = IPowerManager.Stub.asInterface(
ServiceManager.getService("power"));

// Get UpdateLock to suppress system-update related events (e.g. dialog show-up)
// during phone calls.
mUpdateLock = new UpdateLock("phone");

if (DBG) Log.d(LOG_TAG, "onCreate: mUpdateLock: " + mUpdateLock);

CallLogger callLogger = new CallLogger(this, new CallLogAsync());

callGatewayManager = CallGatewayManager.getInstance();

// Create the CallController singleton, which is the interface
// to the telephony layer for user-initiated telephony functionality
// (like making outgoing calls.)
*3) 从上面的描述说,这个会跟outgoing calls相关,但是从现在我看到的MO流程是不一样的,并没有走callcontroller中的placecall,或许我忽略了什么??*
callController = CallController.init(this, callLogger, callGatewayManager);

// Create the CallerInfoCache singleton, which remembers custom ring tone and
// send-to-voicemail settings.
//
// The asynchronous caching will start just after this call.
callerInfoCache = CallerInfoCache.init(this);

// Monitors call activity from the telephony layer
*4) 看名字就知道了使用了监听者模式,这个是一个非常重要的设计模式,在Phone模块使用频繁,需要讲解下*
callStateMonitor = new CallStateMonitor(mCM);

// Bluetooth manager
bluetoothManager = new BluetoothManager();
*5) 是phone服务的实现类,在内部可以直接使用,第三方apps不能直接获取,需要使用TelephonyManager来间接使用该服务。*
phoneMgr = PhoneInterfaceManager.init(this, phone);

// Create the CallNotifer singleton, which handles
// asynchronous events from the telephony layer (like
// launching the incoming-call UI when an incoming call comes
// in.)
*6) 这个是通知的主类,所谓“通知”是指 当有phone状态变化或是有来自telephony layer层的事件的时候,会触发该类,然后通过此类通知UI层*
notifier = CallNotifier.init(this, phone, callLogger, callStateMonitor,
bluetoothManager);

// register for ICC status
IccCard sim = phone.getIccCard();
if (sim != null) {
if (VDBG) Log.v(LOG_TAG, "register for ICC status");
sim.registerForPersoLocked(mHandler, EVENT_PERSO_LOCKED, null);
}

// register for MMI/USSD
mCM.registerForMmiComplete(mHandler, MMI_COMPLETE, null);

// register connection tracking to PhoneUtils
PhoneUtils.initializeConnectionHandler(mCM);

// Register for misc other intent broadcasts.
IntentFilter intentFilter =
new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intentFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
intentFilter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
intentFilter.addAction(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
intentFilter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
registerReceiver(mReceiver, intentFilter);

//set the default values for the preferences in the phone.
PreferenceManager.setDefaultValues(this, R.xml.network_setting, false);

PreferenceManager.setDefaultValues(this, R.xml.call_feature_setting, false);

// Make sure the audio mode (along with some
// audio-mode-related state of our own) is initialized
// correctly, given the current state of the phone.
PhoneUtils.setAudioMode(mCM);
}

cdmaOtaProvisionData = new OtaUtils.CdmaOtaProvisionData();
cdmaOtaConfigData = new OtaUtils.CdmaOtaConfigData();
cdmaOtaScreenState = new OtaUtils.CdmaOtaScreenState();
cdmaOtaInCallScreenUiState = new OtaUtils.CdmaOtaInCallScreenUiState();

// XXX pre-load the SimProvider so that it's ready
resolver.getType(Uri.parse("content://icc/adn"));

// start with the default value to set the mute state.
mShouldRestoreMuteOnInCallResume = false;

// TODO: Register for Cdma Information Records
// phone.registerCdmaInformationRecord(mHandler, EVENT_UNSOL_CDMA_INFO_RECORD, null);

// Read HAC settings and configure audio hardware
*声音设置,这里不关注*
if (getResources().getBoolean(R.bool.hac_enabled)) {
int hac = android.provider.Settings.System.getInt(phone.getContext().getContentResolver(),
android.provider.Settings.System.HEARING_AID,
0);
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
audioManager.setParameter(CallFeaturesSetting.HAC_KEY, hac != 0 ?
CallFeaturesSetting.HAC_VAL_ON :
CallFeaturesSetting.HAC_VAL_OFF);
}
}


1. CallManager

mCM = CallManager.getInstance();
for (Phone ph : mPhones) {
mCM.registerPhone(ph);//注册的部分,细节需要说明
}


mCM = CallManager.getInstance();

跟踪代码发现如下内容:

/**
* get singleton instance of CallManager
* @return CallManager
*/
public static CallManager getInstance() {
return INSTANCE;
}


–>

private static final CallManager INSTANCE = new CallManager();


–>

private CallManager() {
mPhones = new ArrayList<Phone>();
mRingingCalls = new ArrayList<Call>();
mBackgroundCalls = new ArrayList<Call>();
mForegroundCalls = new ArrayList<Call>();
mDefaultPhone = null;
}


说明

初始化CallManager,仅仅是初始化了 3个Calls List和1个Phone List。这里有个问题,Ringing Calls, Background Calls, Foreground Calls是什么?或者说是按照什么标准分类的?

要说明这个问题,也顺带的把后续要说明的Call的状态分类。统一在这里说明下。(注意,不要忘记上面我们的问题)

Phone: 理解为我家的座机。

座机不用的时候是空闲状态 IDLE(空闲);

来电话了,此时座机是响铃状态 RINGING(响铃);

通话过程中,此时座机状态是通话状态 OFFHOOK(摘机:通话中或是拨号中)

Call: 理解为使用我家的座机来打电话。

ACTIVE: 电话处于活动状态。

HOLDING: 电话处于保持状态,类似暂停一样,不过通话时间还是要算的哦。

DIALING: 电话处于拨号状态,使用座机拨了号码。

ALERTING: 电话处于振铃状态,这是针对拨号者而言的,对方此时的状态是INCOMING或是WAITING。

INCOMING:电话处于来电状态,手机当前处于IDLE状态时的来电是incoming

WAITING: 电话处于等待状态,当你电话处于通话过程中,再来电的时的情况。

IDEL: 电话处于空闲状态

DISCONNECTING: 电话正在挂断状态,这个是一瞬间的状态。

DISCONNECTED: 电话已经挂断,之后会转到IDLE。

Connection:理解为一个通话连接

一通电话至少有一个连接,但是一通电话可以有多个连接,电话会议就是典型例子。

电话会议允许有5个连接存在,这个是GSM协议规定的。也就是说,使用智能手机,开通多方通话功能后,手机上最多有7个连接。包括 一个电话会议(5 个Connections),一通电话(1个Connection),一通来电(Connection)。

从上面的例子就可以引申出上面的问题,7个连接。当电话会议处于活动状态的,那么电话会议属于Foreground Call, 另外的一通电话是Background Call, 来电的就是Ringing Call。

至于这三个是如何划分的,也是按照CallState的状态划分。



mCM.registerPhone(ph);

/**
* Register phone to CallManager
* @param phone to be registered
* @return true if register successfully
*/
public boolean registerPhone(Phone phone) {
Phone basePhone = getPhoneBase(phone);

if (basePhone != null && !mPhones.contains(basePhone)) {

if (DBG) {
Rlog.d(LOG_TAG, "registerPhone(" +
phone.getPhoneName() + " " + phone + ")");
}

if (mPhones.isEmpty()) {
mDefaultPhone = basePhone;
}
//mPhones, mRingingCalls, mBackgroundCalls, mForegroundCalls都是list
mPhones.add(basePhone);
mRingingCalls.add(basePhone.getRingingCall());
mBackgroundCalls.add(basePhone.getBackgroundCall());
mForegroundCalls.add(basePhone.getForegroundCall());
//注册重要的Phone状态
registerForPhoneStates(basePhone);
return true;
}
return false;
}


–>

private void registerForPhoneStates(Phone phone) {
... ...
CallManagerHandler handler = mHandlerMap.get(phone);
if (handler != null) {
Rlog.d(LOG_TAG, "This phone has already been registered.");
return;
}

// New registration, create a new handler instance and register the phone.
handler = new CallManagerHandler();
mHandlerMap.put(phone, handler);

// for common events supported by all phones
phone.registerForPreciseCallStateChanged(handler, EVENT_PRECISE_CALL_STATE_CHANGED, null);
... ...
phone.registerForNewRingingConnection(handler, EVENT_NEW_RINGING_CONNECTION, null);
phone.registerForUnknownConnection(handler, EVENT_UNKNOWN_CONNECTION, null);
phone.registerForIncomingRing(handler, EVENT_INCOMING_RING, null);
... ...
phone.registerForSuppServiceFailed(handler, EVENT_SUPP_SERVICE_FAILED, null);
phone.registerForServiceStateChanged(handler, EVENT_SERVICE_STATE_CHANGED, null);

// for events supported only by GSM, CDMA and IMS phone
if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM ||
phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA ||
phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
phone.setOnPostDialCharacter(handler, EVENT_POST_DIAL_CHARACTER, null);
}

// for events supported only by CDMA phone
... ...

// for events supported only by IMS phone
if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
phone.registerForOnHoldTone(handler, EVENT_ONHOLD_TONE, null);
}
}


2. Notification Manager

// Create the NotificationMgr singleton, which is used to display
// status bar icons and control other status bar behavior.
2) 这里会稍微说明下,只会初始化一次,以后会直接使用
notificationMgr = NotificationMgr.init(this);


/**
* Initialize the singleton NotificationMgr instance.
*
* This is only done once, at startup, from PhoneApp.onCreate().
* From then on, the NotificationMgr instance is available via the
* PhoneApp's public "notificationMgr" field, which is why there's no
* getInstance() method here.
*/
/* package */ static NotificationMgr init(PhoneGlobals app) {
synchronized (NotificationMgr.class) {
if (sInstance == null) {
sInstance = new NotificationMgr(app);
} else {
Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);
}
return sInstance;
}
}


–>

/**
* Private constructor (this is a singleton).
* @see #init(PhoneGlobals)
*/
private NotificationMgr(PhoneGlobals app) {
mApp = app;
mContext = app;
//需要使用系统的NotificationManager服务
mNotificationManager =
(NotificationManager) app.getSystemService(Context.NOTIFICATION_SERVICE);
//获得StatusBarManager服务
mStatusBarManager =
(StatusBarManager) app.getSystemService(Context.STATUS_BAR_SERVICE);
mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE);
statusBarHelper = new StatusBarHelper();
}


3. CallController

// Create the CallController singleton, which is the interface
// to the telephony layer for user-initiated telephony functionality
// (like making outgoing calls.)
// 3) 从上面的描述说,这个会跟outgoing calls相关,但是5.0的MO流程跟4.4是不一样的,并没有走callcontroller中的placecall,或许我忽略了什么??
callController = CallController.init(this, callLogger, callGatewayManager);


/**
* Initialize the singleton CallController instance.
*
* This is only done once, at startup, from PhoneApp.onCreate().
* From then on, the CallController instance is available via the
* PhoneApp's public "callController" field, which is why there's no
* getInstance() method here.
*/
/* package */ static CallController init(PhoneGlobals app, CallLogger callLogger,
CallGatewayManager callGatewayManager) {
synchronized (CallController.class) {
if (sInstance == null) {
sInstance = new CallController(app, callLogger, callGatewayManager);
} else {
Log.wtf(TAG, "init() called multiple times!  sInstance = " + sInstance);
}
return sInstance;
}
}


–>

/**
* Private constructor (this is a singleton).
* @see init()
*/
private CallController(PhoneGlobals app, CallLogger callLogger,
CallGatewayManager callGatewayManager) {
if (DBG) log("CallController constructor: app = " + app);
mApp = app;
mCM = app.mCM;
mCallLogger = callLogger;
mCallGatewayManager = callGatewayManager;
}


4. CallStateMonitor

// Monitors call activity from the telephony layer
// 4) 看名字就知道了使用了监听者模式,这个是一个非常重要的设计模式,在Phone模块使用频繁,需要讲解下
callStateMonitor = new CallStateMonitor(mCM);


讲解这个之前,需要简单复习下观察者模式是什么样子的,强烈建议参考 程杰老师的《大话设计模式》中的 观察者模式这一章节你,值得拥有!!!



/**
* Register for call state notifications with the CallManager.
*/
private void registerForNotifications() {
... ...
//callManager.registerForNewRingingConnection(this, PHONE_NEW_RINGING_CONNECTION, null);
//callManager.registerForPreciseCallStateChanged(this, PHONE_STATE_CHANGED, null);
//callManager.registerForDisconnect(this, PHONE_DISCONNECT, null);
//callManager.registerForUnknownConnection(this, PHONE_UNKNOWN_CONNECTION_APPEARED, null);
callManager.registerForCdmaOtaStatusChange(this, EVENT_OTA_PROVISION_CHANGE, null);
//callManager.registerForCallWaiting(this, PHONE_CDMA_CALL_WAITING, null);
callManager.registerForDisplayInfo(this, PHONE_STATE_DISPLAYINFO, null);
callManager.registerForSignalInfo(this, PHONE_STATE_SIGNALINFO, null);
callManager.registerForInCallVoicePrivacyOn(this, PHONE_ENHANCED_VP_ON, null);
callManager.registerForInCallVoicePrivacyOff(this, PHONE_ENHANCED_VP_OFF, null);
//callManager.registerForRingbackTone(this, PHONE_RINGBACK_TONE, null);
//callManager.registerForResendIncallMute(this, PHONE_RESEND_MUTE, null);
//callManager.registerForPostDialCharacter(this, PHONE_ON_DIAL_CHARS, null);
}


注意到,这里注释了好多跟来电相关的注册,仅仅保留了几个其他的消息,说明来电通知这块不会使用CallStateMonitor来承担了,由其他的人士去完成了。

6. CallNotifer

注意 这里的编号是6, 是按照PhoneGlobals.onCreate()中的顺序而来, 4,6一起是为了说明观察者模式

// Create the CallNotifer singleton, which handles
// asynchronous events from the telephony layer (like
// launching the incoming-call UI when an incoming call comes
// in.)
// 6) 这个是通知的主类,所谓“通知”是指 当有phone状态变化或是有来自telephony layer层的事件的时候,会触发该类,然后通过此类通知UI层
notifier = CallNotifier.init(this, phone, callLogger, callStateMonitor,
bluetoothManager);


结合4 ,6 来具体说明下观察者模式的在CallStateMonitor 和 CallNotifer中的使用。

图形:Observer4CallStateMonitor.jpg



说明:

不需要关注CallManager类的内容。CallStateMonitor 和 CallNotifer都是继承自Handler,都自己重写了Handler中的handleMessage方法。

这里subject 和 Observe都是一个类 Handler,CallStateMonitor当成subjectState, CallNotifer当成concreteObserver。handleMessage就是其中的Notify方法。

CallStateMonitor中有addListener(Handler handler),用于将外界对CallStateMonitor感兴趣的Handler (如CallNotifer), 放入自己的Handler list中。当然外界的CallNotifer也需要有CallStateMonitor这个subjectState的实例(参数变量或是成员变量),然后才能使用他的addListener方法。

一旦CallStateMonitor有处理到HandleMessage到,就会以如下的方式调用:

@Override
public void handleMessage(Message msg) {
if (DBG) {
Log.d(LOG_TAG, "handleMessage(" + msg.what + ")");
}

for (Handler handler : registeredHandlers) {
handler.handleMessage(msg);
}
}


5. PhoneInterfaceManger

// 5) 是phone服务的实现类,在内部可以直接使用,第三方apps不能直接获取,需要使用TelephonyManager来间接使用该服务。
phoneMgr = PhoneInterfaceManager.init(this, phone);


/**
* Initialize the singleton PhoneInterfaceManager instance.
* This is only done once, at startup, from PhoneApp.onCreate().
*/
/* package */ static PhoneInterfaceManager init(PhoneGlobals app, Phone phone) {
synchronized (PhoneInterfaceManager.class) {
if (sInstance == null) {
//new PhoneInterfaceManager 实例
sInstance = new PhoneInterfaceManager(app, phone);
} else {
Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);
}
return sInstance;
}
}


–>

//都是为了“phone”服务的运行做准备
/** Private constructor; @see init() */
private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {
mApp = app;
mPhone = phone;
mCM = PhoneGlobals.getInstance().mCM;
mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
//这是一个Handle,处理phone主线中的消息,主要是供系统内部的其他apps或是纯粹的第三方app来使用。
mMainThreadHandler = new MainThreadHandler();
carrierPrivilegeConfigs =
PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
//这一步就是把phone服务加入ServiceManager中,是的外界可以使用【phone】服务
publish();
}


–>

private void publish() {
if (DBG) log("publish: " + this);
ServiceManager.addService("phone", this);
}


小结

这篇本想回答两个问题:

针对上文中的主要关系类,展开学习。主要是学习,在Phone进程中有什么作用,扮演什么角色。

梳理清楚几个关键的消息注册,包括MT(来电)消息注册,状态改变消息注册。这是基础,懂得了这些,会有助于分析定位问题。

但是分析代码,发现问题 1. 算是将清楚了,但是问题 2. 却没有说明白。而是偏向了Phone 状态, Call 状态的分类, 这个很重要

建议去查看 @seven同学写的Phone浅析,非常的详细,也非常的用心。

Android 4.4 Kitkat Phone工作流程浅析(八)__Phone状态分析

关于MT来电的消息注册在CallManager中提及了,因为有了消息的注册:

phone.registerForNewRingingConnection(handler, EVENT_NEW_RINGING_CONNECTION, null);
phone.registerForIncomingRing(handler, EVENT_INCOMING_RING, null);


只要沿着
phone.registerForNewRingingConnection


->

phoneBase.registerForNewRingingConnection


保存到特定列表中。然后反向分析是谁调用了

mNewRingingConnectionRegistrants.notifyRegistrants(ar)


也就梳理清楚了消息注册流程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息