ImsConference.java中会议成员更新处理详解
public class ConferenceParticipant implements Parcelable { //自定义数据结构
private static final String ANONYMOUS_INVALID_HOST
private final Uri mHandle;
private final String mDisplayName;
private final Uri mEndpoint;
private final int mState;
private long mConnectTime;
private long mConnectElapsedTime;
private int mCallDirection;}
public class DisconnectCause implements Parcelable { ...}
participant: ConferenceParticipantConnection.java
public void handleConferenceParticipantsUpdate(
TelephonyConnection parent, List<ConferenceParticipant> participants) {
//不支持会议管理,return
if (parent != null && !parent.isManageImsConferenceCallSupported()) {
Log.i(this, "handleConferenceParticipantsUpdate: manage conference is disallowed");
return;
}
Log.i(this, "handleConferenceParticipantsUpdate: size=%d", participants.size());
// 以同步方式执行更新。IMS framework可以快速连续地触发两次onConferenceParticipantsChanged callbacks。 // 第一次更新添加新的参与者,第二次更新其中一个参与者的状态。
synchronized (mUpdateSyncRoot) { //private final Object
int oldParticipantCount = mConferenceParticipantConnections.size();
boolean newParticipantsAdded = false;
boolean oldParticipantsRemoved = false;
ArrayList<ConferenceParticipant> newParticipants = new ArrayList<>(participants.size());
HashSet<Pair<Uri,Uri>> participantUserEntities = new HashSet<>(participants.size());
// Determine if the conference event package represents a single party conference.
// A single party conference :除了host外,只有1个会议成员. // Note: We consider 0 to still be a single party conference since some carriers will
// send a conference event package with JUST the host in it when the conference is
// disconnected. We don't want to change back to conference mode prior to disconnection
// or we will not log the call.
boolean isSinglePartyConference = participants.stream() //1.后面在解析
.filter(p -> {
Pair<Uri, Uri> pIdent = new Pair<>(p.getHandle(), p.getEndpoint());
return !Objects.equals(mHostParticipantIdentity, pIdent);
}).count() <= 1;
if ((mIsEmulatingSinglePartyCall && !isSinglePartyConference) ||
!mIsEmulatingSinglePartyCall) {
// Add any new participants and update existing.
for (ConferenceParticipant participant : participants) {
Pair<Uri, Uri> userEntity = new Pair<>(participant.getHandle(),participant.getEndpoint());
participantUserEntities.add(userEntity);
if (!mConferenceParticipantConnections.containsKey(userEntity)) { //不存在 userEntity
// Some carriers will also include the conference host in the CEP. We will filter that out here.
if (!isParticipantHost(mConferenceHostAddress, participant.getHandle())) {
createConferenceParticipantConnection(parent, participant);
newParticipants.add(participant);
newParticipantsAdded = true;
} else {
// Track the identity of the conference host; its useful to know when
// we look at the CEP in the future.
mHostParticipantIdentity = userEntity;
}
} else { //存在 userEntity
ConferenceParticipantConnection connection = mConferenceParticipantConnections.get(userEntity);
Log.i(this,"handleConferenceParticipantsUpdate: updateState, participant = %s",participant);
connection.updateState(participant.getState());
connection.setVideoState(parent.getVideoState());
}
}
// Set state of new participants.
if (newParticipantsAdded) {
// Set the state of the new participants at once and add to the conference
for (ConferenceParticipant newParticipant : newParticipants) {
ConferenceParticipantConnection connection =
mConferenceParticipantConnections.get(new Pair<>(
newParticipant.getHandle(),newParticipant.getEndpoint()));
connection.updateState(newParticipant.getState());
connection.setVideoState(parent.getVideoState());
}
}
//最后,从会议中删除不再存在于会议事件包数据中的任何参与者。
Iterator<Map.Entry<Pair<Uri, Uri>, ConferenceParticipantConnection>> entryIterator =
mConferenceParticipantConnections.entrySet().iterator();
while (entryIterator.hasNext()) {
Map.Entry<Pair<Uri, Uri>, ConferenceParticipantConnection> entry = entryIterator.next();
if (!participantUserEntities.contains(entry.getKey())) {
ConferenceParticipantConnection participant = entry.getValue();
participant.setDisconnected(new DisconnectCause(DisconnectCause.CANCELED));
participant.removeConnectionListener(mParticipantListener);
mTelephonyConnectionService.removeConnection(participant);
removeConnection(participant);
entryIterator.remove();
oldParticipantsRemoved = true;
}
}
}
int newParticipantCount = mConferenceParticipantConnections.size();
Log.v(this, "handleConferenceParticipantsUpdate: oldParticipantCount=%d, "
+ "newParticipantcount=%d", oldParticipantCount, newParticipantCount);
// If the single party call emulation fature flag is enabled, we can potentially treat
// the conference as a single party call when there is just one participant.
if (mFeatureFlagProxy.isUsingSinglePartyCallEmulation()) {
if (oldParticipantCount > 1 && newParticipantCount == 1) {
// If number of participants goes to 1, emulate a single party call.
startEmulatingSinglePartyCall();
} else if (mIsEmulatingSinglePartyCall && !isSinglePartyConference) {
// Number of participants increased, so stop emulating a single party call.
stopEmulatingSinglePartyCall();
}
}
// If new participants were added or old ones were removed, we need to ensure the state
// of the manage conference capability is updated.
if (newParticipantsAdded || oldParticipantsRemoved) {
updateManageConference();
}
}
}
handleConferenceParticipantsUpdate: 1.ImsConferenceCallSupported判断 2.isSinglePartyConference判断 3.不EmulatingSinglePartyCall或EmulatingSinglePartyCall且SinglePartyConference条件下,添加成员,更新成员信息 4.新成员被添加到ConferenceParticipant中,更新信息 5.remove,从会议中删除不再存在于会议事件包数据中的任何参与者 6.startEmulatingSinglePartyCall()或stopEmulatingSinglePartyCall() 7.新成员增加或就成员remove, updateManageConference()
/**
a single party call:会议电话成员只有1名与会者。 * 1. Set the name/address to that of the single participant.
* 2. Remove the participant from Telecom and from local tracking; when we get a new CEP in
* the future we'll just re-add the participant anyways.
* 3. Tell telecom we're not a conference.
* 4. Remove {@link Connection#CAPABILITY_MANAGE_CONFERENCE} capability.
*注意:如果会议是通过sim call manager进行的,单方呼叫模拟将被禁用。模拟单方呼叫需要更改会议的属性(连接时间、地址、会议状态), sim call manager 不能保证将这些属性正确地转发到Telecom。
*/
private void startEmulatingSinglePartyCall() {
if (mIsUsingSimCallManager) {
Log.i(this, "startEmulatingSinglePartyCall: using sim call manager; skip.");
return;
}
Log.i(this, "startEmulatingSinglePartyCall: conference has a single "
+ "participant; downgrade to single party call.");
mIsEmulatingSinglePartyCall = true;
Iterator<ConferenceParticipantConnection> valueIterator =
mConferenceParticipantConnections.values().iterator();
if (valueIterator.hasNext()) {
ConferenceParticipantConnection entry = valueIterator.next();
// Set the conference name/number to that of the remaining participant.
setAddress(entry.getAddress(), entry.getAddressPresentation());
setCallerDisplayName(entry.getCallerDisplayName(),entry.getCallerDisplayNamePresentation());
setConnectionStartElapsedRealTime(entry.getConnectElapsedTimeMillis());
setConnectionTime(entry.getConnectTimeMillis());
mLoneParticipantIdentity = new Pair<>(entry.getUserEntity(), entry.getEndpoint());
// Remove the participant from Telecom. It'll get picked up in a future CEP update again anyways.
entry.setDisconnected(new DisconnectCause(DisconnectCause.CANCELED,DisconnectCause.REASON_EMULATING_SINGLE_CALL));
entry.removeConnectionListener(mParticipantListener);
mTelephonyConnectionService.removeConnection(entry);
removeConnection(entry);
valueIterator.remove();
// Have Telecom pretend its not a conference.
setConferenceState(false);
//Remove manage conference capability.
mCouldManageConference = can(Connection.CAPABILITY_MANAGE_CONFERENCE);
int currentCapabilities = getConnectionCapabilities();
currentCapabilities &= ~Connection.CAPABILITY_MANAGE_CONFERENCE;
setConnectionCapabilities(currentCapabilities);
}
ImsConference.java中会议成员更新处理详解的更多相关文章
- Java 中的异常和处理详解
Java 中的异常和处理详解 原文出处: 代码钢琴家 简介 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常.异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误 ...
- Java中的IO流系统详解(转载)
摘要: Java 流在处理上分为字符流和字节流.字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符.字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组. Java ...
- Java中的IO流系统详解
Java 流在处理上分为字符流和字节流.字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符.字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组. Java 内用 U ...
- java中内存结构及堆栈详解
一. java内存结构 1. Heap(堆):实例分配的地方,通过-Xms与-Xmx来设置 2. MethodArea(方法区域):类的信息及静态变量. 对应是Permanet Generation, ...
- java中的final和volatile详解
相比synchronized,final和volatile也是经常使用的关键字,下面聊一聊这两个关键字的使用和实现 1.使用 final使用: 修饰类表示该类为终态类,无法被继承 修饰方法表示该方法无 ...
- Java中23种经典设计模式详解
Java中23种设计模式目录1. 设计模式 31.1 创建型模式 41.1.1 工厂方法 41.1.2 抽象工厂 61.1.3 建造者模式 101.1.4 单态模式 131.1.5 原型模式 151. ...
- JAVA中堆栈和内存分配详解(摘抄)
在Java中,有六个不同的地方可以存储数据: 1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存 ...
- 2018.8.1 Java中的反射和同步详解
为何要使用同步? java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他 ...
- Java中hashCode与equal方法详解
转载自http://blog.csdn.net/jiangwei0910410003/article/details/22739953 Java中的equals方法和hashCode方法是Object ...
随机推荐
- 转载! 一图读懂 SignalR
- JVM内存图
- JasperReports教程
JasperReports教程 Jasper报表是一个开源的Java报表引擎,是基于Java的,它没有自己的表达式语法. 由于JasperReports是一个Java类库,而不是针对最终用户,而是有针 ...
- 2019秋季学期第2周Java学习总结
本周在第一周接触认识Java后对该编程语言有了进一步了解,明白了Java的类型:包括Application程序,Applet程序.知道了一个Java程序的关键字(public class).主方法(p ...
- Spring Data JPA one to one 共享主键关联
/** * Created by xiezhiyan on 17-9-13. */@Entitypublic class Token { @Id @Column(name = "store_ ...
- C# winform 文件管理
1.FolderBrowserDialog 打开文件夹中默认路径下的excl文件 private void button7_Click(object sender, EventArgs e) { Fo ...
- 运维监控篇Zabbix简单的性能调优
Zabbix是一款高性能的分布式监控报警系统.比如现在常见的家用台式机配置处理器I5-3470.内存4GB1600MHz.硬盘7200rpm就能够监控1000台左右的HOST,是的没错Zabbix就是 ...
- 使用PL/SQL连接oracle数据库,并将数据进行导出备份和导入恢复
使用PL/SQL连接oracle数据库,并将数据进行导出备份和导入恢复 这种操作百度一搜一大片,今天整理以前做的项目时自己备份了一下数据库,试着将数据进行导出备份和导入恢复了一下:下面是操作过程: 1 ...
- KiCAD批量修改丝印大小
KiCAD批量修改丝印大小 1.编辑->编辑文本与图片属性 2.范围 选择封装参考,活动 首选选择 “设定为指定值”,然后选择要修改的层,输入想要修改的参数 注意:文本高度与文本宽度比例要适中, ...
- element-UI select 踩过的坑和解决办法
今天遇到了一个bug,就是在使用element-UI的select框时,当选中值,会触发@change事件,下拉框消失,但是这时候select框还是处于获取焦点状态.可以看到select框还是处于颜色 ...