153b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon/*
253b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon * Copyright (C) 2014 The Android Open Source Project
353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon *
453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon * Licensed under the Apache License, Version 2.0 (the "License");
553b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon * you may not use this file except in compliance with the License.
653b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon * You may obtain a copy of the License at
753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon *
853b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon *      http://www.apache.org/licenses/LICENSE-2.0
953b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon *
1053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon * Unless required by applicable law or agreed to in writing, software
1153b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon * distributed under the License is distributed on an "AS IS" BASIS,
1253b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon * See the License for the specific language governing permissions and
1453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon * limitations under the License.
1553b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon */
1653b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon
1753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordonpackage com.android.services.telephony;
1853b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon
194d45d1cf58a2003378fd35912d6d73a00001bf06Tyler Gunnimport android.telecom.PhoneCapabilities;
204d45d1cf58a2003378fd35912d6d73a00001bf06Tyler Gunnimport android.telecom.Conference;
214d45d1cf58a2003378fd35912d6d73a00001bf06Tyler Gunnimport android.telecom.Connection;
224d45d1cf58a2003378fd35912d6d73a00001bf06Tyler Gunnimport android.telecom.PhoneAccountHandle;
2353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon
2453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordonimport com.android.internal.telephony.Call;
2553b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordonimport com.android.internal.telephony.CallStateException;
263197ea821dcdee1c30549f850b99c2cfc7f668cbIhab Awadimport com.android.internal.telephony.Phone;
2753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon
2853b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordonimport java.util.List;
2953b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon
3053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon/**
3153b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon * GSM-based conference call.
3253b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon */
3353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordonpublic class GsmConference extends Conference {
3453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon
3553b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    public GsmConference(PhoneAccountHandle phoneAccount) {
3653b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon        super(phoneAccount);
3753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon        setCapabilities(
3853b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon                PhoneCapabilities.SUPPORT_HOLD |
3953b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon                PhoneCapabilities.HOLD |
4053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon                PhoneCapabilities.MUTE |
41a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                PhoneCapabilities.MANAGE_CONFERENCE);
4253b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon        setActive();
4353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    }
4453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon
4553b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    /**
4653b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon     * Invoked when the Conference and all it's {@link Connection}s should be disconnected.
4753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon     */
4853b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    @Override
4953b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    public void onDisconnect() {
5053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon        for (Connection connection : getConnections()) {
5153b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon            Call call = getMultipartyCallForConnection(connection, "onDisconnect");
5253b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon            if (call != null) {
531c25892dc5f0170441422f15242df8887b7903edSantos Cordon                Log.d(this, "Found multiparty call to hangup for conference.");
5453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon                try {
5553b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon                    call.hangup();
561c25892dc5f0170441422f15242df8887b7903edSantos Cordon                    break;
5753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon                } catch (CallStateException e) {
5853b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon                    Log.e(this, e, "Exception thrown trying to hangup conference");
5953b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon                }
6053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon            }
6153b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon        }
6253b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    }
6353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon
6453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    /**
6553b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon     * Invoked when the specified {@link Connection} should be separated from the conference call.
6653b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon     *
6753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon     * @param connection The connection to separate.
6853b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon     */
6953b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    @Override
7053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    public void onSeparate(Connection connection) {
7153b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon        com.android.internal.telephony.Connection radioConnection =
7253b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon                getOriginalConnection(connection, "onSeparate");
7353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon        try {
7453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon            radioConnection.separate();
7553b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon        } catch (CallStateException e) {
7653b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon            Log.e(this, e, "Exception thrown trying to separate a conference call");
7753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon        }
7853b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    }
793197ea821dcdee1c30549f850b99c2cfc7f668cbIhab Awad
803197ea821dcdee1c30549f850b99c2cfc7f668cbIhab Awad    @Override
813197ea821dcdee1c30549f850b99c2cfc7f668cbIhab Awad    public void onMerge(Connection connection) {
823197ea821dcdee1c30549f850b99c2cfc7f668cbIhab Awad        try {
833197ea821dcdee1c30549f850b99c2cfc7f668cbIhab Awad            Phone phone = ((TelephonyConnection) connection).getPhone();
843197ea821dcdee1c30549f850b99c2cfc7f668cbIhab Awad            if (phone != null) {
853197ea821dcdee1c30549f850b99c2cfc7f668cbIhab Awad                phone.conference();
863197ea821dcdee1c30549f850b99c2cfc7f668cbIhab Awad            }
873197ea821dcdee1c30549f850b99c2cfc7f668cbIhab Awad        } catch (CallStateException e) {
883197ea821dcdee1c30549f850b99c2cfc7f668cbIhab Awad            Log.e(this, e, "Exception thrown trying to merge call into a conference");
893197ea821dcdee1c30549f850b99c2cfc7f668cbIhab Awad        }
903197ea821dcdee1c30549f850b99c2cfc7f668cbIhab Awad    }
9153b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon
9253b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    /**
9353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon     * Invoked when the conference should be put on hold.
9453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon     */
9553b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    @Override
9653b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    public void onHold() {
97293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee        final GsmConnection connection = getFirstConnection();
98293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee        if (connection != null) {
99293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee            connection.performHold();
10053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon        }
10153b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    }
10253b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon
10353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    /**
10453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon     * Invoked when the conference should be moved from hold to active.
10553b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon     */
10653b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    @Override
10753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    public void onUnhold() {
108293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee        final GsmConnection connection = getFirstConnection();
109293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee        if (connection != null) {
110293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee            connection.performUnhold();
111293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee        }
112293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee    }
113293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee
114293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee    @Override
115293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee    public void onPlayDtmfTone(char c) {
116293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee        final GsmConnection connection = getFirstConnection();
117293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee        if (connection != null) {
118293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee            connection.onPlayDtmfTone(c);
119293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee        }
120293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee    }
121293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee
122293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee    @Override
123293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee    public void onStopDtmfTone() {
124293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee        final GsmConnection connection = getFirstConnection();
125293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee        if (connection != null) {
126293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee            connection.onStopDtmfTone();
12753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon        }
12853b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    }
12953b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon
13053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    private Call getMultipartyCallForConnection(Connection connection, String tag) {
13153b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon        com.android.internal.telephony.Connection radioConnection =
13253b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon                getOriginalConnection(connection, tag);
13353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon        if (radioConnection != null) {
13453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon            Call call = radioConnection.getCall();
13553b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon            if (call != null && call.isMultiparty()) {
13653b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon                return call;
13753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon            }
13853b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon        }
13953b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon        return null;
14053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    }
14153b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon
14253b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    private com.android.internal.telephony.Connection getOriginalConnection(
14353b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon            Connection connection, String tag) {
14453b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon
14553b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon        if (connection instanceof GsmConnection) {
14653b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon            return ((GsmConnection) connection).getOriginalConnection();
14753b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon        } else {
14853b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon            Log.e(this, null, "Non GSM connection found in a Gsm conference (%s)", tag);
14953b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon            return null;
15053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon        }
15153b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon    }
152293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee
153293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee    private GsmConnection getFirstConnection() {
154293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee        final List<Connection> connections = getConnections();
155293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee        if (connections.isEmpty()) {
156293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee            return null;
157293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee        }
158293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee        return (GsmConnection) connections.get(0);
159293b7bbbc7fb53fe62cd64a40324e11088153398Yorke Lee    }
16053b84fe2dc796ef172d7c0f4b9bdc177cdeb0c0fSantos Cordon}
161