GsmConferenceController.java revision aef7a4bc4f85149de427d7506ebe97753b2ca6c2
1aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad/* 2aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad * Copyright (C) 2014 The Android Open Source Project 3aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad * 4aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad * Licensed under the Apache License, Version 2.0 (the "License"); 5aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad * you may not use this file except in compliance with the License. 6aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad * You may obtain a copy of the License at 7aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad * 8aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad * http://www.apache.org/licenses/LICENSE-2.0 9aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad * 10aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad * Unless required by applicable law or agreed to in writing, software 11aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad * distributed under the License is distributed on an "AS IS" BASIS, 12aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad * See the License for the specific language governing permissions and 14aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad * limitations under the License. 15aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad */ 16aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad 17aa7340388473c1676495a60e30dc6a48d318a489Ihab Awadpackage com.android.services.telephony; 18aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad 19aa7340388473c1676495a60e30dc6a48d318a489Ihab Awadimport java.util.ArrayList; 206059c9310c85986f38c22940470e5a0ff280806fSantos Cordonimport java.util.Collections; 2153b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordonimport java.util.HashSet; 22aa7340388473c1676495a60e30dc6a48d318a489Ihab Awadimport java.util.List; 2353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordonimport java.util.Set; 24aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad 254d45d1cf58a2003378fd35912d6d73a00001bf06Tyler Gunnimport android.telecom.Conference; 264d45d1cf58a2003378fd35912d6d73a00001bf06Tyler Gunnimport android.telecom.Connection; 27aef7a4bc4f85149de427d7506ebe97753b2ca6c2Andrew Leeimport android.telecom.DisconnectCause; 28aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad 2953b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordonimport com.android.internal.telephony.Call; 3053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon 31aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad/** 32aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad * Maintains a list of all the known GSM connections and implements GSM-specific conference 33aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad * call functionality. 34aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad */ 353199aa7f8bcb48569eb8289abc055ba0f8496ba8Sailesh Nepalfinal class GsmConferenceController { 362093a451b17c26f4341e9565b65dcaa0e20bbd7dSailesh Nepal private final Connection.Listener mConnectionListener = new Connection.Listener() { 37af4b3fd88b5412fbd644b1a4b9d1909c25681d4cNancy Chen @Override 38af4b3fd88b5412fbd644b1a4b9d1909c25681d4cNancy Chen public void onStateChanged(Connection c, int state) { 39af4b3fd88b5412fbd644b1a4b9d1909c25681d4cNancy Chen recalculate(); 40af4b3fd88b5412fbd644b1a4b9d1909c25681d4cNancy Chen } 41aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad 42af4b3fd88b5412fbd644b1a4b9d1909c25681d4cNancy Chen /** ${inheritDoc} */ 43af4b3fd88b5412fbd644b1a4b9d1909c25681d4cNancy Chen @Override 44aef7a4bc4f85149de427d7506ebe97753b2ca6c2Andrew Lee public void onDisconnected(Connection c, DisconnectCause disconnectCause) { 45af4b3fd88b5412fbd644b1a4b9d1909c25681d4cNancy Chen recalculate(); 46af4b3fd88b5412fbd644b1a4b9d1909c25681d4cNancy Chen } 47af4b3fd88b5412fbd644b1a4b9d1909c25681d4cNancy Chen 48af4b3fd88b5412fbd644b1a4b9d1909c25681d4cNancy Chen @Override 49af4b3fd88b5412fbd644b1a4b9d1909c25681d4cNancy Chen public void onDestroyed(Connection connection) { 50af4b3fd88b5412fbd644b1a4b9d1909c25681d4cNancy Chen remove((GsmConnection) connection); 51af4b3fd88b5412fbd644b1a4b9d1909c25681d4cNancy Chen } 52af4b3fd88b5412fbd644b1a4b9d1909c25681d4cNancy Chen }; 53aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad 54aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad /** The known GSM connections. */ 55aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad private final List<GsmConnection> mGsmConnections = new ArrayList<>(); 56aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad 5753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon private final TelephonyConnectionService mConnectionService; 58aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad 5953b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon public GsmConferenceController(TelephonyConnectionService connectionService) { 6053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon mConnectionService = connectionService; 61aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad } 62aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad 6353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon /** The GSM conference connection object. */ 6453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon private Conference mGsmConference; 65aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad 6653b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon void add(GsmConnection connection) { 6753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon mGsmConnections.add(connection); 6853b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon connection.addConnectionListener(mConnectionListener); 6953b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon recalculate(); 703199aa7f8bcb48569eb8289abc055ba0f8496ba8Sailesh Nepal } 713199aa7f8bcb48569eb8289abc055ba0f8496ba8Sailesh Nepal 7253b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon void remove(GsmConnection connection) { 7353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon connection.removeConnectionListener(mConnectionListener); 7453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon mGsmConnections.remove(connection); 7553b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon recalculate(); 76aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad } 77aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad 786059c9310c85986f38c22940470e5a0ff280806fSantos Cordon private void recalculate() { 796059c9310c85986f38c22940470e5a0ff280806fSantos Cordon recalculateConferenceable(); 8053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon recalculateConference(); 816059c9310c85986f38c22940470e5a0ff280806fSantos Cordon } 826059c9310c85986f38c22940470e5a0ff280806fSantos Cordon 83aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad /** 84aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad * Calculates the conference-capable state of all GSM connections in this connection service. 85aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad */ 866059c9310c85986f38c22940470e5a0ff280806fSantos Cordon private void recalculateConferenceable() { 876059c9310c85986f38c22940470e5a0ff280806fSantos Cordon Log.v(this, "recalculateConferenceable : %d", mGsmConnections.size()); 886059c9310c85986f38c22940470e5a0ff280806fSantos Cordon 896059c9310c85986f38c22940470e5a0ff280806fSantos Cordon List<Connection> activeConnections = new ArrayList<>(mGsmConnections.size()); 906059c9310c85986f38c22940470e5a0ff280806fSantos Cordon List<Connection> backgroundConnections = new ArrayList<>(mGsmConnections.size()); 916059c9310c85986f38c22940470e5a0ff280806fSantos Cordon 926059c9310c85986f38c22940470e5a0ff280806fSantos Cordon // Loop through and collect all calls which are active or holding 93aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad for (GsmConnection connection : mGsmConnections) { 94aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad com.android.internal.telephony.Connection radioConnection = 95aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad connection.getOriginalConnection(); 966059c9310c85986f38c22940470e5a0ff280806fSantos Cordon Log.d(this, "recalc - %s %s", 976059c9310c85986f38c22940470e5a0ff280806fSantos Cordon radioConnection == null ? null : radioConnection.getState(), connection); 98aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad 996059c9310c85986f38c22940470e5a0ff280806fSantos Cordon if (radioConnection != null) { 1006059c9310c85986f38c22940470e5a0ff280806fSantos Cordon switch(radioConnection.getState()) { 1016059c9310c85986f38c22940470e5a0ff280806fSantos Cordon case ACTIVE: 1026059c9310c85986f38c22940470e5a0ff280806fSantos Cordon activeConnections.add(connection); 1036059c9310c85986f38c22940470e5a0ff280806fSantos Cordon break; 1046059c9310c85986f38c22940470e5a0ff280806fSantos Cordon case HOLDING: 1056059c9310c85986f38c22940470e5a0ff280806fSantos Cordon backgroundConnections.add(connection); 1066059c9310c85986f38c22940470e5a0ff280806fSantos Cordon break; 1076059c9310c85986f38c22940470e5a0ff280806fSantos Cordon default: 1086059c9310c85986f38c22940470e5a0ff280806fSantos Cordon connection.setConferenceableConnections( 1096059c9310c85986f38c22940470e5a0ff280806fSantos Cordon Collections.<Connection>emptyList()); 1106059c9310c85986f38c22940470e5a0ff280806fSantos Cordon break; 111aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad } 112aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad } 1136059c9310c85986f38c22940470e5a0ff280806fSantos Cordon } 1146059c9310c85986f38c22940470e5a0ff280806fSantos Cordon 1156059c9310c85986f38c22940470e5a0ff280806fSantos Cordon Log.v(this, "active: %d, holding: %d", 1166059c9310c85986f38c22940470e5a0ff280806fSantos Cordon activeConnections.size(), backgroundConnections.size()); 1176059c9310c85986f38c22940470e5a0ff280806fSantos Cordon 1186059c9310c85986f38c22940470e5a0ff280806fSantos Cordon // Go through all the active connections and set the background connections as 1196059c9310c85986f38c22940470e5a0ff280806fSantos Cordon // conferenceable. 1206059c9310c85986f38c22940470e5a0ff280806fSantos Cordon for (Connection connection : activeConnections) { 1216059c9310c85986f38c22940470e5a0ff280806fSantos Cordon connection.setConferenceableConnections(backgroundConnections); 1226059c9310c85986f38c22940470e5a0ff280806fSantos Cordon } 123aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad 1246059c9310c85986f38c22940470e5a0ff280806fSantos Cordon // Go through all the background connections and set the active connections as 1256059c9310c85986f38c22940470e5a0ff280806fSantos Cordon // conferenceable. 1266059c9310c85986f38c22940470e5a0ff280806fSantos Cordon for (Connection connection : backgroundConnections) { 1276059c9310c85986f38c22940470e5a0ff280806fSantos Cordon connection.setConferenceableConnections(activeConnections); 128aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad } 12953b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon // TODO: Do not allow conferencing of already conferenced connections. 13053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon } 13153b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon 13253b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon private void recalculateConference() { 13353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon Set<GsmConnection> conferencedConnections = new HashSet<>(); 13453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon 13553b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon for (GsmConnection connection : mGsmConnections) { 13653b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon com.android.internal.telephony.Connection radioConnection = 13753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon connection.getOriginalConnection(); 13853b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon 13953b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon if (radioConnection != null) { 14053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon Call.State state = radioConnection.getState(); 14153b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon Call call = radioConnection.getCall(); 14253b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon if ((state == Call.State.ACTIVE || state == Call.State.HOLDING) && 14353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon (call != null && call.isMultiparty())) { 14453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon conferencedConnections.add(connection); 14553b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon } 14653b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon } 14753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon } 14853b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon 14953b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon Log.d(this, "Recalculate conference calls %s %s.", 15053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon mGsmConference, conferencedConnections); 15153b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon 15253b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon if (conferencedConnections.size() < 2) { 15353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon Log.d(this, "less than two conference calls!"); 15453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon // No more connections are conferenced, destroy any existing conference. 15553b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon if (mGsmConference != null) { 15653b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon Log.d(this, "with a conference to destroy!"); 15753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon mGsmConference.destroy(); 15853b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon mGsmConference = null; 15953b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon } 16053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon } else { 16153b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon if (mGsmConference != null) { 16253b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon List<Connection> existingConnections = mGsmConference.getConnections(); 16353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon // Remove any that no longer exist 16453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon for (Connection connection : existingConnections) { 16553b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon if (!conferencedConnections.contains(connection)) { 16653b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon mGsmConference.removeConnection(connection); 16753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon } 16853b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon } 16953b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon 17053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon // Add any new ones 17153b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon for (Connection connection : conferencedConnections) { 17253b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon if (!existingConnections.contains(connection)) { 17353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon mGsmConference.addConnection(connection); 17453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon } 17553b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon } 17653b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon } else { 17753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon mGsmConference = new GsmConference(null); 17853b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon for (Connection connection : conferencedConnections) { 1791c25892dc5f0170441422f15242df8887b7903edSantos Cordon Log.d(this, "Adding a connection to a conference call: %s %s", 1801c25892dc5f0170441422f15242df8887b7903edSantos Cordon mGsmConference, connection); 18153b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon mGsmConference.addConnection(connection); 18253b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon } 18353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon mConnectionService.addConference(mGsmConference); 18453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon } 1858a76b6b8715188f00fff4c0e52d579f10cc53de3Andrew Lee 1868a76b6b8715188f00fff4c0e52d579f10cc53de3Andrew Lee // Set the conference state to the same state as its child connections. 1878a76b6b8715188f00fff4c0e52d579f10cc53de3Andrew Lee Connection conferencedConnection = mGsmConference.getConnections().get(0); 1888a76b6b8715188f00fff4c0e52d579f10cc53de3Andrew Lee switch (conferencedConnection.getState()) { 1898a76b6b8715188f00fff4c0e52d579f10cc53de3Andrew Lee case Connection.STATE_ACTIVE: 1908a76b6b8715188f00fff4c0e52d579f10cc53de3Andrew Lee mGsmConference.setActive(); 1918a76b6b8715188f00fff4c0e52d579f10cc53de3Andrew Lee break; 1928a76b6b8715188f00fff4c0e52d579f10cc53de3Andrew Lee case Connection.STATE_HOLDING: 1938a76b6b8715188f00fff4c0e52d579f10cc53de3Andrew Lee mGsmConference.setOnHold(); 1948a76b6b8715188f00fff4c0e52d579f10cc53de3Andrew Lee break; 1958a76b6b8715188f00fff4c0e52d579f10cc53de3Andrew Lee } 19653b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon } 197aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad } 198aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad} 199