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中会议成员更新处理详解的更多相关文章

  1. Java 中的异常和处理详解

    Java 中的异常和处理详解 原文出处: 代码钢琴家 简介 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常.异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误 ...

  2. Java中的IO流系统详解(转载)

    摘要: Java 流在处理上分为字符流和字节流.字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符.字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组. Java ...

  3. Java中的IO流系统详解

    Java 流在处理上分为字符流和字节流.字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符.字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组. Java 内用 U ...

  4. java中内存结构及堆栈详解

    一. java内存结构 1. Heap(堆):实例分配的地方,通过-Xms与-Xmx来设置 2. MethodArea(方法区域):类的信息及静态变量. 对应是Permanet Generation, ...

  5. java中的final和volatile详解

    相比synchronized,final和volatile也是经常使用的关键字,下面聊一聊这两个关键字的使用和实现 1.使用 final使用: 修饰类表示该类为终态类,无法被继承 修饰方法表示该方法无 ...

  6. Java中23种经典设计模式详解

    Java中23种设计模式目录1. 设计模式 31.1 创建型模式 41.1.1 工厂方法 41.1.2 抽象工厂 61.1.3 建造者模式 101.1.4 单态模式 131.1.5 原型模式 151. ...

  7. JAVA中堆栈和内存分配详解(摘抄)

    在Java中,有六个不同的地方可以存储数据: 1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存 ...

  8. 2018.8.1 Java中的反射和同步详解

    为何要使用同步? java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他 ...

  9. Java中hashCode与equal方法详解

    转载自http://blog.csdn.net/jiangwei0910410003/article/details/22739953 Java中的equals方法和hashCode方法是Object ...

随机推荐

  1. Windows10系统下,如何彻底删除卸载MySQL

    本文介绍,在Windows10系统下,如何彻底删除卸载MySQL... 1>停止MySQL服务开始->所有应用->Windows管理工具->服务,将MySQL服务停止.2> ...

  2. 2019 ACM-ICPC 南京 现场赛 K. Triangle (二分)

    题意 给定一个三角形和一个点 \(p\),如果该点不在三角形边上直接输出 \(-1\),否则在三角形上找一点 \(q\),使得线段 \(pq\) 平分三角形面积. 思路 看完题想都没想直接二分了. 就 ...

  3. Rust <10>:宏导出、导入

    源 crate 中使用 #[macro_export] 属性标记的宏,调用者可在导入此 crate 时添加 #[macro_use] 属性使用. 没有 #[macro_export] 的宏,外部不可见 ...

  4. [FW]CLONE_NEWUSER trickery: CVE-2013-1858

    CLONE_NEWUSER trickery: CVE-2013-1858   Recent kernels (3.8+ something) introduced a feature calledu ...

  5. 三、hibernate中持久化类的使用

    hibernate的持久化类 持久化:将内存中的一个对象持久化到数据库中的过程,hibernate就是一个用来进行持久化的框架 持久化类:一个Java对象与数据库中表建立了关系映射,那么这个类在hib ...

  6. ARM 汇编与C之间 的调用

    一. 汇编调用 C 1. 初始化栈 2. 初始化BSS段 (BSS 段是C语言存放未初始化的全局变量,或者初始化为0 的全局变量) 3 .使用 r0 ,r1, r2, r3 给函数传参,如果多于  4 ...

  7. 项目案例之Pipeline流水线及流水线发布PHP项目(二)

    项目案例之Pipeline流水线及流水线发布PHP项目(二) 链接:https://pan.baidu.com/s/1NZZbocZuNwtQS0eGkkglXQ 提取码:z7gj 复制这段内容后打开 ...

  8. 前端学习(十二)js数据类型(笔记)

    选项卡:        for循环 for(初始值,条件,自增){}    for(var i=0; i<9;i++){} 几个按钮对应相同个内容!!! -------------------- ...

  9. ubtuntu下虚拟环境搭建【python】

    为什么要搭建虚拟环境? 在开发过程中, 当需要使用python的某些工具包/框架时需要联网安装 比如联网安装Flask框架flask-0.10.1版本 sudo pip install flask== ...

  10. Atcoder arc093

    D-Grid Components 在一个100*100的网格图上染色,问黑格四连通块的个数为A,白格四连通块的个数为B的一种构造方案?(A,B<=500) 将整个平面分成50*100的两部分, ...