Home | History | Annotate | Download | only in ims
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License
     15  */
     16 
     17 package android.telephony.ims;
     18 
     19 import java.util.HashMap;
     20 import java.util.Iterator;
     21 import java.util.Map.Entry;
     22 import java.util.Set;
     23 
     24 import android.annotation.SystemApi;
     25 import android.os.Bundle;
     26 import android.os.Parcel;
     27 import android.os.Parcelable;
     28 import android.telecom.Call;
     29 import android.telecom.Connection;
     30 
     31 /**
     32  * Provides the conference information (defined in RFC 4575) for IMS conference call.
     33  *
     34  * @hide
     35  */
     36 @SystemApi
     37 public final class ImsConferenceState implements Parcelable {
     38     /**
     39      * conference-info : user
     40      */
     41     // user (String) : Tel or SIP URI
     42     public static final String USER = "user";
     43     // user > display text (String)
     44     public static final String DISPLAY_TEXT = "display-text";
     45     // user > endpoint (String) : URI or GRUU or Phone number
     46     public static final String ENDPOINT = "endpoint";
     47     // user > endpoint > status
     48     public static final String STATUS = "status";
     49 
     50     /**
     51      * status-type (String) :
     52      * "pending" : Endpoint is not yet in the session, but it is anticipated that he/she will
     53      *      join in the near future.
     54      * "dialing-out" : Focus has dialed out to connect the endpoint to the conference,
     55      *      but the endpoint is not yet in the roster (probably being authenticated).
     56      * "dialing-in" : Endpoint is dialing into the conference, not yet in the roster
     57      *      (probably being authenticated).
     58      * "alerting" : PSTN alerting or SIP 180 Ringing was returned for the outbound call;
     59      *      endpoint is being alerted.
     60      * "on-hold" : Active signaling dialog exists between an endpoint and a focus,
     61      *      but endpoint is "on-hold" for this conference, i.e., he/she is neither "hearing"
     62      *      the conference mix nor is his/her media being mixed in the conference.
     63      * "connected" : Endpoint is a participant in the conference. Depending on the media policies,
     64      *      he/she can send and receive media to and from other participants.
     65      * "disconnecting" : Focus is in the process of disconnecting the endpoint
     66      *      (e.g. in SIP a DISCONNECT or BYE was sent to the endpoint).
     67      * "disconnected" : Endpoint is not a participant in the conference, and no active dialog
     68      *      exists between the endpoint and the focus.
     69      * "muted-via-focus" : Active signaling dialog exists beween an endpoint and a focus and
     70      *      the endpoint can "listen" to the conference, but the endpoint's media is not being
     71      *      mixed into the conference.
     72      * "connect-fail" : Endpoint fails to join the conference by rejecting the conference call.
     73      */
     74     public static final String STATUS_PENDING = "pending";
     75     public static final String STATUS_DIALING_OUT = "dialing-out";
     76     public static final String STATUS_DIALING_IN = "dialing-in";
     77     public static final String STATUS_ALERTING = "alerting";
     78     public static final String STATUS_ON_HOLD = "on-hold";
     79     public static final String STATUS_CONNECTED = "connected";
     80     public static final String STATUS_DISCONNECTING = "disconnecting";
     81     public static final String STATUS_DISCONNECTED = "disconnected";
     82     public static final String STATUS_MUTED_VIA_FOCUS = "muted-via-focus";
     83     public static final String STATUS_CONNECT_FAIL = "connect-fail";
     84     public static final String STATUS_SEND_ONLY = "sendonly";
     85     public static final String STATUS_SEND_RECV = "sendrecv";
     86 
     87     /**
     88      * conference-info : SIP status code (integer)
     89      */
     90     public static final String SIP_STATUS_CODE = "sipstatuscode";
     91 
     92     public final HashMap<String, Bundle> mParticipants = new HashMap<String, Bundle>();
     93 
     94     /** @hide */
     95     public ImsConferenceState() {
     96     }
     97 
     98     private ImsConferenceState(Parcel in) {
     99         readFromParcel(in);
    100     }
    101 
    102     @Override
    103     public int describeContents() {
    104         return 0;
    105     }
    106 
    107     @Override
    108     public void writeToParcel(Parcel out, int flags) {
    109         out.writeInt(mParticipants.size());
    110 
    111         if (mParticipants.size() > 0) {
    112             Set<Entry<String, Bundle>> entries = mParticipants.entrySet();
    113 
    114             if (entries != null) {
    115                 Iterator<Entry<String, Bundle>> iterator = entries.iterator();
    116 
    117                 while (iterator.hasNext()) {
    118                     Entry<String, Bundle> entry = iterator.next();
    119 
    120                     out.writeString(entry.getKey());
    121                     out.writeParcelable(entry.getValue(), 0);
    122                 }
    123             }
    124         }
    125     }
    126 
    127     private void readFromParcel(Parcel in) {
    128         int size = in.readInt();
    129 
    130         for (int i = 0; i < size; ++i) {
    131             String user = in.readString();
    132             Bundle state = in.readParcelable(null);
    133             mParticipants.put(user, state);
    134         }
    135     }
    136 
    137     public static final Creator<ImsConferenceState> CREATOR =
    138             new Creator<ImsConferenceState>() {
    139         @Override
    140         public ImsConferenceState createFromParcel(Parcel in) {
    141             return new ImsConferenceState(in);
    142         }
    143 
    144         @Override
    145         public ImsConferenceState[] newArray(int size) {
    146             return new ImsConferenceState[size];
    147         }
    148     };
    149 
    150     /**
    151      * Translates an {@code ImsConferenceState} status type to a telecom connection state.
    152      *
    153      * @param status The status type.
    154      * @return The corresponding {@link android.telecom.Connection} state.
    155      */
    156     public static int getConnectionStateForStatus(String status) {
    157         if (status.equals(STATUS_PENDING)) {
    158             return Connection.STATE_INITIALIZING;
    159         } else if (status.equals(STATUS_DIALING_IN)) {
    160             return Connection.STATE_RINGING;
    161         } else if (status.equals(STATUS_ALERTING) ||
    162                 status.equals(STATUS_DIALING_OUT)) {
    163             return Connection.STATE_DIALING;
    164         } else if (status.equals(STATUS_ON_HOLD) ||
    165                 status.equals(STATUS_SEND_ONLY)) {
    166             return Connection.STATE_HOLDING;
    167         } else if (status.equals(STATUS_CONNECTED) ||
    168                 status.equals(STATUS_MUTED_VIA_FOCUS) ||
    169                 status.equals(STATUS_DISCONNECTING) ||
    170                 status.equals(STATUS_SEND_RECV)) {
    171             return Connection.STATE_ACTIVE;
    172         } else if (status.equals(STATUS_DISCONNECTED)) {
    173             return Connection.STATE_DISCONNECTED;
    174         }
    175         return Call.STATE_ACTIVE;
    176     }
    177 
    178     @Override
    179     public String toString() {
    180         StringBuilder sb = new StringBuilder();
    181         sb.append("[");
    182         sb.append(ImsConferenceState.class.getSimpleName());
    183         sb.append(" ");
    184         if (mParticipants.size() > 0) {
    185             Set<Entry<String, Bundle>> entries = mParticipants.entrySet();
    186 
    187             if (entries != null) {
    188                 Iterator<Entry<String, Bundle>> iterator = entries.iterator();
    189                 sb.append("<");
    190                 while (iterator.hasNext()) {
    191                     Entry<String, Bundle> entry = iterator.next();
    192                     sb.append(entry.getKey());
    193                     sb.append(": ");
    194                     Bundle participantData = entry.getValue();
    195 
    196                     for (String key : participantData.keySet()) {
    197                         sb.append(key);
    198                         sb.append("=");
    199                         if (ENDPOINT.equals(key) || USER.equals(key)) {
    200                             sb.append(android.telecom.Log.pii(participantData.get(key)));
    201                         } else {
    202                             sb.append(participantData.get(key));
    203                         }
    204                         sb.append(", ");
    205                     }
    206                 }
    207                 sb.append(">");
    208             }
    209         }
    210         sb.append("]");
    211         return sb.toString();
    212     }
    213 }
    214