`
zzbupt
  • 浏览: 84603 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Android通话和数据传输过程分析(转)

阅读更多

第三部分、第四部分:猫相关的各种状态的监听和通知机制/通话相关的图标变换的工作原理。
网络状态,edge,gprs图标的处理
a、注册监听部分
==>SystemServer.java
init2()
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
ServerThread.run()
com.android.server.status.StatusBarPolicy.installIcons(context, statusBar);
sInstance = new StatusBarPolicy(context, service);
// phone_signal
mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
mPhoneData = IconData.makeIcon("phone_signal",
null, com.android.internal.R.drawable.stat_sys_signal_null, 0, 0);
mPhoneIcon = service.addIcon(mPhoneData, null);
// register for phone state notifications.
((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE))
.listen(mPhoneStateListener,
PhoneStateListener.LISTEN_SERVICE_STATE
| PhoneStateListener.LISTEN_SIGNAL_STRENGTH
| PhoneStateListener.LISTEN_CALL_STATE
| PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
| PhoneStateListener.LISTEN_DATA_ACTIVITY);
//实际是调用的是TelephonyRegistry.listen,此listen函数会将Iphonestatelistener添加到对应的的handler数组中,到时来了事件会轮询回调。
// data_connection
mDataData = IconData.makeIcon("data_connection",
null, com.android.internal.R.drawable.stat_sys_data_connected_g, 0, 0);
mDataIcon = service.addIcon(mDataData, null);
service.setIconVisibility(mDataIcon, false);
b、 事件通知部分
==>PhoneFactory.java
makeDefaultPhones()
sPhoneNotifier = new DefaultPhoneNotifier();
useNewRIL(context);
phone = new GSMPhone(context, new RIL(context), sPhoneNotifier);
for example
==>DataConnectionTracker.java
notifyDefaultData(String reason)
phone.notifyDataConnection(reason);
mNotifier.notifyDataConnection(this, reason);
==>DefaultPhoneNotifier.java
mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
"telephony.registry"));
mRegistry.notifyDataConnection(convertDataState(sender.getDataConnectionState()),
sender.isDataConnectivityPossible(), reason, sender.getActiveApn(),
sender.getInterfaceName(null));

第五部分:gprs拨号上网的通路原理。
上层java程序调用gprs流程:
=>PhoneApp.java
onCreate()
PhoneFactory.makeDefaultPhones(this);
phone = new GSMPhone(context, new SimulatedCommands(), sPhoneNotifier);
mDataConnection = new DataConnectionTracker (this);
createAllPdpList();//建立缺省pdpconnection
pdp = new PdpConnection(phone);
dataLink = new PppLink(phone.mDataConnection);
dataLink.setOnLinkChange(this, EVENT_LINK_STATE_CHANGED, null);
dataLink = new PppLink(phone.mDataConnection);
dataLink.setOnLinkChange(this, EVENT_LINK_STATE_CHANGED, null);

//某个条件触发执行
trySetupData(String reason)
setupData(reason);
pdp = findFreePdp();
Message msg = obtainMessage();
msg.what = EVENT_DATA_SETUP_COMPLETE;
msg.obj = reason;
pdp.connect(apn, msg);
phone.mCM.setupDefaultPDP(apn.apn, apn.user, apn.password,
obtainMessage(EVENT_SETUP_PDP_DONE));

//收到EVENT_SETUP_PDP_DONE消息
=>pdpconnection.java
handleMessage()
case EVENT_SETUP_PDP_DONE:
dataLink.connect();//dataLink是pppLink.java
SystemService.start(SERVICE_PPPD_GPRS);//启动pppd_grps服务
poll.what = EVENT_POLL_DATA_CONNECTION;
sendMessageDelayed(poll, POLL_SYSFS_MILLIS);//启动轮询,看是否成功连接gprs
checkPPP()//每隔5秒轮询,看是否连接成功,或断开
//如果已经连接
mLinkChangeRegistrant.notifyResult(LinkState.LINK_UP);
//执行到pdpconnection.handleMessage()
case EVENT_LINK_STATE_CHANGED
onLinkStateChanged(ls);
case LINK_UP:
notifySuccess(onConnectCompleted);
onCompleted.sendToTarget();

//执行dataConnectionTracker.java的handleMessage()
case EVENT_DATA_SETUP_COMPLETE
notifyDefaultData(reason);
setupDnsProperties();
setState(State.CONNECTED);
phone.notifyDataConnection(reason);
startNetStatPoll();
resetPollStats();
1、读取发送出去的包数和接受到的包数
2、如果发送的数据包且没有收到应答包数n大于等于看门狗追踪的限定包数。
2.1、开始轮询pdp context list,尝试恢复网络连接
2.2、如果轮询24次后还没有联通网络则停止网络状态轮询,进行一次ping实验。
2.2.1、如果ping成功则,重新进行网络状态轮询,否则发送EVENT_START_RECOVERY事件。
// reset reconnect timer
nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
着重c++部分代码的角度分析
=>DataConnectionTracker.java
trySetupData(String reason)
setupData(reason);
=>PdpConnection.java
pdp.connect(apn, msg);
=>RIL.JAVA
phone.mCM.setupDefaultPDP(apn.apn, apn.user, apn.password,
obtainMessage(EVENT_SETUP_PDP_DONE));
send(rr);
//send socket to RIL

//enter c++ layer
=>ril.cpp
processCommandsCallback (int fd, short flags, void *param)
processCommandBuffer(p_record, recordlen);
status = p.readInt32(&request);
pRI->pCI = &(s_commands[request]);
pRI->pCI->dispatchFunction(p, pRI);
dispatchStrings();
s_callbacks.onRequest(pRI->pCI->requestNumber, pStrings, datalen, pRI);
=>reference-ril.c
onRequest();
requestSetupDefaultPDP(data, datalen, t);
err = write_at_to_data_channel("ATD*99***1#",1);

//after a while.get "connect" from data channel,so need to send socket message to java layer.
p.writeInt32 (RESPONSE_SOLICITED);
p.writeInt32 (pRI->token);//the serial No  in the request list.
errorOffset = p.dataPosition();
p.writeInt32 (e);
if (e == RIL_E_SUCCESS) {
/* process response on success */
ret = pRI->pCI->responseFunction(p, response, responselen);
/* if an error occurred, rewind and mark it */
if (ret != 0) {
p.setDataPosition(errorOffset);
p.writeInt32 (ret);
}
}
sendResponse(p);
sendResponseRaw(p.data(), p.dataSize());
ret = blockingWrite(fd, (void *)&header, sizeof(header));
blockingWrite(fd, data, dataSize);

=>RIL.JAVA
RILReceiver.run();
length = readRilMessage(is, buffer);
p = Parcel.obtain();
p.unmarshall(buffer, 0, length);
p.setDataPosition(0);
processResponse(p);
processSolicited (p);
serial = p.readInt();
error = p.readInt();
rr = findAndRemoveRequestFromList(serial);
ret =  responseStrings(p);
if (rr.mResult != null) {
AsyncResult.forMessage(rr.mResult, ret, null);
rr.mResult.sendToTarget();
}

=>pdpConnection.java
handleMessage()
case EVENT_SETUP_PDP_DONE:
...
dataLink.connect();
=>pppLink.java
SystemProperties.set(PROPERTY_PPPD_EXIT_CODE, "");
SystemService.start(SERVICE_PPPD_GPRS);//启动pppd_grps服务
poll.what = EVENT_POLL_DATA_CONNECTION;
sendMessageDelayed(poll, POLL_SYSFS_MILLIS);
dataConnection.state = State.CONNECTING;
handleMessage()
case EVENT_POLL_DATA_CONNECTION
checkPPP();
if (ArrayUtils.equals(mCheckPPPBuffer, UP_ASCII_STRING, UP_ASCII_STRING.length)
|| ArrayUtils.equals(mCheckPPPBuffer, UNKNOWN_ASCII_STRING,
UNKNOWN_ASCII_STRING.length)
&& dataConnection.state == State.CONNECTING)
if (mLinkChangeRegistrant != null) {
mLinkChangeRegistrant.notifyResult(LinkState.LINK_UP);
=>pdpConnection.java
handleMessage()
case EVENT_LINK_STATE_CHANGED:
DataLink.LinkState ls  = (DataLink.LinkState) ar.result;
onLinkStateChanged(ls);
case LINK_UP:
notifySuccess(onConnectCompleted);
AsyncResult.forMessage(onCompleted);
onCompleted.sendToTarget();

=>DataConnectionTracker.java
handleMessage()
case EVENT_DATA_SETUP_COMPLETE:
...
SystemProperties.set("gsm.defaultpdpcontext.active", "true");
notifyDefaultData(reason);
setupDnsProperties();//设置dns,gw,我们的实现方式是在pppd中设置的,不用pppd拨号的适用。
setState(State.CONNECTED);
phone.notifyDataConnection(reason);
mNotifier.notifyDataConnection(this, reason);
=>DefaultPhoneNotifier.java
//mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
"telephony.registry"));构造函数中初始化了mRegistry
mRegistry.notifyDataConnection(convertDataState(sender.getDataConnectionState()),
sender.isDataConnectivityPossible(), reason, sender.getActiveApn(),
sender.getInterfaceName(null));
startNetStatPoll(); 
}

第六部分:通话相关的语音通路切换原理、震动接口
6、语音通路
6.1、设置语音通路的路由
目前我们有两处处理:
a、CallTracker.java中
handlePollCalls()
检测到+clcc返回的电话列表中有状态为DriverCall.State.ALERTING(表示拨打电话后,对方已经振铃),此时需要设置语音通路为MODE_IN_CALL
b、PhoneUtils.java中setAudioMode()函数
c、调用通路分析
AudioManager audioManager = (AudioManager) context.getSystemService
(Context.AUDIO_SERVICE);
audioManager.setMode(mode);

AudioManager.setMode(mode);
AudioService.setMode(mode);
AudioSystem.setMode(mode);(native function)
android_media_AudioSystem.cpp==>android_media_AudioSystem_setMode()
AudioSystem.cpp==>setMode()
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
binder = sm->getService(String16("media.audio_flinger"));
...
gAudioFlinger = interface_cast<IAudioFlinger>(binder);
...
return gAudioFlinger;

通过查找“media.audio_flinger”发现AudioFlinger.cpp==>instantiate()//Main_mediaserver.cpp中被实例化。
defaultServiceManager()->addService(String16("media.audio_flinger"), new AudioFlinger())
mAudioHardware = AudioHardwareInterface::create();
LOGV("Creating Vendor Specific AudioHardware");
hw = createAudioHardware();
return new AudioHardwareMarvell();
return af->setMode(mode);
AudioHardwareLittle.cpp==>setMode(mode)
doRouting();
enable_incall_headphone()//or others...
system("alsactl -f /etc/alsactl/asound.state_none restore");
system("alsactl -f /etc/alsactl/asound.state_headset_r_s restore");
6.2、来电播放振铃,挂断或接听停止振铃。
==>Phone.app
onCreate()
ringer = new Ringer(phone);
Vibrator mVibrator = new Vibrator();
mService = IHardwareService.Stub.asInterface(ServiceManager.getService("hardware"));
notifier = new CallNotifier(this, phone, ringer, mBtHandsfree);
mPhone.registerForIncomingRing(this, PHONE_INCOMING_RING, null);
mPhone.registerForPhoneStateChanged(this, PHONE_STATE_CHANGED, null);
mPhone.registerForDisconnect(this, PHONE_DISCONNECT, null);
...
case PHONE_INCOMING_RING:
mRinger.ring();
mHardwareService.setAttentionLight(true);
mVibratorThread.start();
while (mContinueVibrating) {
mVibrator.vibrate(VIBRATE_LENGTH);
SystemClock.sleep(VIBRATE_LENGTH + PAUSE_LENGTH);
}
...
makeLooper();
mRingHandler.sendEmptyMessage(PLAY_RING_ONCE);
...
case PLAY_RING_ONCE:
PhoneUtils.setAudioMode(mContext, AudioManager.MODE_RINGTONE);
r.play();
...
case PHONE_DISCONNECT:
case PHONE_STATE_CHANGED:
...
mRinger.stopRing();
Message msg = mRingHandler.obtainMessage(STOP_RING);
msg.obj = mRingtone;
mRingHandler.sendMessage(msg);
case STOP_RING:
r.stop();
getLooper().quit();
...
mVibrator.cancel();
第七部分:通话相关的notification服务
7、通话相关的notification服务。
7.1、NotificationMgr
==>PhoneApp.java
onCreate()
NotificationMgr.init(this)//NotificationMgr.java//此类主要负责电话通知的具体表现(通知和取消通知),未接图标、通话中、蓝牙激活中、保持中,静音、免提等。封装了简单的瞬间显示文本消息的功能。提供漫游数据连接禁止的通知封装和漫游数据连接允许时取消通知
sMe = new NotificationMgr(context);
mNotificationMgr = (NotificationManager
context.getSystemService(Context.NOTIFICATION_SERVICE);
mStatusBar = (StatusBarManager) context.getSystemService(Context.STATUS_BAR_SERVICE); //主要用于显示静音和speaker状态的图表(在状态条右边显示)
sMe.updateNotifications();//主要功能是:
1、查询是否有未读的未接听电话,并显示到状态栏图标,和通知列表
2、根据是否是电话状态,更新状态栏图表和通知列表(可能是激活,蓝牙,保持等)
7.2、CallNotifier
==>PhoneApp.java
onCreate()
notifier = new CallNotifier(this, phone, ringer, mBtHandsfree);//此类主要是监听通话相关的事件,然后进行例如来电播放铃声,震动。挂断、接听停止振铃等(调用Ringer类实现此功能),根据不同的状态调用调用NotificationMgr进行具体的通知和取消通知。
第八部分: 通话相关的各种server
电话通信相关的服务:
(1)、从ServiceManager得到的:
a、wifiService
b、PhoneInterfaceManager
c、PhoneSubInfo
d、SimPhoneBookInterfaceManager
e、SimSmsInterfaceManager
f、TelephonyRegistry
g、NetStatService
h、ConnectivityService
(2)、从ApplicationContext得到的:
a、TelephonyManager

 

分享到:
评论

相关推荐

    android即时通话项目

    主要是为了学习android基础知识,所以做的比较简单,语音通话的降噪和回音消除都没有做,有兴趣的朋友可以继续做下去,建议用rtp实现语音传输,同时用一些开源库降噪如speex。解压后的两个文件夹分别是服务器项目和...

    Android+Speex+RTP实时语音对讲

    参考别人的代码,然后自己优化后的Android加Speex编码,然后利用RTP传输数据的实时语音DEMO,亲测在两台手机上可用,一个说的话效果还不错,如果2个人同时说回音还是有点大,有需要的可以参考下。

    Android VoIP语音及视频通话源代码.rar

     对于SipDroid实现视频通话的原理,目前的理解是:发送方是将是将视频数据传输到视频流媒体服务器,然后再传输给接收方的。具体细节目前不是很清楚,因为涉及到许多通信协议。  本项目共250 个目标文件,还有jni...

    新版Android开发教程.rar

    也有分析认为,谷歌并不想做一个简单的手机终端制造商或者软件平台开发商,而意在一统传统互联网和 移 动互联网。----------------------------------- Android 编程基础 4 Android Android Android Android 手机新...

    基于websocket+webrtc实现音视频通话demo,下载即可用

    基于Java WebSocket 做信令服务器,使用webrtc浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。从而实现音视频通话。下载启动 输入http://localhost 就可使用

    Android实现局域网视频聊天功能(不用框架)

    通过tcp进行连接控制,通过udp进行数据传输,能聊天,发语音,发图片。后续可开发更多功能。

    PanFone Data Transfer 数据传输工具 v1.2.1官方版

    为您提供PanFone Data Transfer 数据传输工具下载,PanFone Data Transfer是一款数据传输工具,既可以帮助用户从手机或者iOS系统备份和恢复数据,还支持将手机数据和文件备份到PC并恢复到新手机而不会降低质量。...

    基于SRS视频服务器实现简易音视频通话系统——Android客户端.zip

    网络与通信:数据传输、信号处理、网络协议、网络与通信硬件、网络安全网络与通信是一个非常广泛的领域,它涉及到计算机科学、电子工程、数学等多个学科的知识。 云计算与大数据:数据集、包括云计算平台、大数据...

    G.726编码语音传输Android端代码

    G.726编码语音传输Android端代码,原理就是Android手机采集语音的PCM编码,然后用NDK在底层编码成G.726码流,通过组播在局域网传播,PC端接收数据,通过G.726动态连接库解码成PCM流,通过SDL库的播放出来,当然通话...

    基于个推+华为push的一整套完善的android IM聊天系统。.zip

    网络与通信:数据传输、信号处理、网络协议、网络与通信硬件、网络安全网络与通信是一个非常广泛的领域,它涉及到计算机科学、电子工程、数学等多个学科的知识。 云计算与大数据:数据集、包括云计算平台、大数据...

    论文研究-一种融合GPS信息的手机流媒体通信和传输系统.pdf

    采用H.264格式和基于RTP/RTCP协议进行流媒体的压缩、分包和管理,把GPS定位等复合信息存储在RTP扩展包内与音频数据组包传输,智能终端既能完成视频通话也能同步传输和展示GPS定位信息。实践证明融合GPS信息对音视频...

    安卓课程设计-手机通讯录系统全解.doc

    经过多年的发展,第三代数字通信(3G)技术活动了广泛的接 受,它为移动终端用户带来了更快的数据传输速率。随着3G网络的使用,移动终端不再 仅是通讯网络的终端,还将成为互联网的终端。因此,移动终端的应用软件和...

    meshenger-android:通过本地网络与人们进行P2P AudioVideo通话。 无需服务器或Internet访问

    麦胜格 无需任何服务器或Internet访问的语音和视频通话。 只需扫描彼此的QR码并互相呼叫。... 交换的公共密钥用于对信令数据进行身份验证/加密,以建立可传输音频和视频的会话。 可以在或找到详细信息。

    php yii框架,javascript webrtc库 ,视频通话系统(14-15年毕业设计).zip

    网络与通信:数据传输、信号处理、网络协议、网络与通信硬件、网络安全网络与通信是一个非常广泛的领域,它涉及到计算机科学、电子工程、数学等多个学科的知识。 云计算与大数据:包括云计算平台、大数据分析、人工...

    手机数据拷贝工具(Wondershare MobileTrans) v5.7.0.228中文特别版.zip

    程序不仅仅可以传输短信、通话记录、照片、音乐、视频和应用程序,而且程序支持跨系统传输数据,可以基于在Android、Symbian和iOS的多部手机之间移动数据。 只需一次点击,你可以直接在两部手机之间传输数据, 无论...

    Apowersoft Phone Manager Pro手机助手2.0中文注册版.rar

    在手机和电脑之间传输数据,备份手机上的短信联系人电话号码及通话记录等,备份手机中保存的相片及视频。转换手机铃声,安装最新的应用到你的手机,管理手机中的文件,备份数据到电脑或者将数据恢复到手机。连接方式...

    基于Android的GPRS的车载通信终端设计方案

     采用Android操作系统和MD231GPRS模块,以S3C6410嵌入式处理器为,设计了一个基于车辆故障参数的GPRS远程传输的通信终端,能实现数据的处理、远程传输。通过通信终端能对车辆状态进行实时监控,出现故障时,可以...

    uh-oh-android

    哦哦 ...已经为Android和Iphone创建了本机应用程序,并创建了一个Web服务来安全地存储位置数据并传输文本消息 Android应用程序: : iOS应用程序 Webservice /网站 以下是该技术的状态,其中估计需要完

    AirDroid v3.6.4.0.zip

    文件:Android设备和计算机之间传输文件。拖放支持剪切,复制,粘贴,搜索,重命名或删除SD卡上的文件。 短信:接收,发送,转发或删除短信。 应用程序:安装,卸载,备份,搜索应用程序,做批量处理。 照片:...

Global site tag (gtag.js) - Google Analytics