1/*
2 * Copyright (C) 2014 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
17package com.android.services.telephony;
18
19import android.content.Context;
20import android.os.PersistableBundle;
21import android.telecom.Conference;
22import android.telecom.Connection;
23import android.telecom.PhoneAccountHandle;
24import android.telephony.CarrierConfigManager;
25
26import com.android.internal.telephony.Call;
27import com.android.internal.telephony.CallStateException;
28import com.android.phone.PhoneGlobals;
29import com.android.phone.common.R;
30
31import java.util.List;
32
33/**
34 * CDMA-based conference call.
35 */
36public class CdmaConference extends Conference {
37    private int mCapabilities;
38    private int mProperties;
39
40    public CdmaConference(PhoneAccountHandle phoneAccount) {
41        super(phoneAccount);
42        setActive();
43
44        mProperties = Connection.PROPERTY_GENERIC_CONFERENCE;
45        setConnectionProperties(mProperties);
46    }
47
48    public void updateCapabilities(int capabilities) {
49        capabilities |= Connection.CAPABILITY_MUTE;
50        setConnectionCapabilities(capabilities);
51    }
52
53    /**
54     * Invoked when the Conference and all it's {@link Connection}s should be disconnected.
55     */
56    @Override
57    public void onDisconnect() {
58        Call call = getOriginalCall();
59        if (call != null) {
60            Log.d(this, "Found multiparty call to hangup for conference.");
61            try {
62                call.hangup();
63            } catch (CallStateException e) {
64                Log.e(this, e, "Exception thrown trying to hangup conference");
65            }
66        }
67    }
68
69    @Override
70    public void onSeparate(Connection connection) {
71        Log.e(this, new Exception(), "Separate not supported for CDMA conference call.");
72    }
73
74    @Override
75    public void onHold() {
76        Log.e(this, new Exception(), "Hold not supported for CDMA conference call.");
77    }
78
79    /**
80     * Invoked when the conference should be moved from hold to active.
81     */
82    @Override
83    public void onUnhold() {
84        Log.e(this, new Exception(), "Unhold not supported for CDMA conference call.");
85    }
86
87    @Override
88    public void onMerge() {
89        Log.i(this, "Merging CDMA conference call.");
90        // Can only merge once
91        mCapabilities &= ~Connection.CAPABILITY_MERGE_CONFERENCE;
92        // Once merged, swap is enabled.
93        if (isSwapSupportedAfterMerge()){
94            mCapabilities |= Connection.CAPABILITY_SWAP_CONFERENCE;
95        }
96        updateCapabilities(mCapabilities);
97        sendFlash();
98    }
99
100    @Override
101    public void onPlayDtmfTone(char c) {
102        final CdmaConnection connection = getFirstConnection();
103        if (connection != null) {
104            connection.onPlayDtmfTone(c);
105        } else {
106            Log.w(this, "No CDMA connection found while trying to play dtmf tone.");
107        }
108    }
109
110    @Override
111    public void onStopDtmfTone() {
112        final CdmaConnection connection = getFirstConnection();
113        if (connection != null) {
114            connection.onStopDtmfTone();
115        } else {
116            Log.w(this, "No CDMA connection found while trying to stop dtmf tone.");
117        }
118    }
119
120    @Override
121    public void onSwap() {
122        Log.i(this, "Swapping CDMA conference call.");
123        sendFlash();
124    }
125
126    private void sendFlash() {
127        Call call = getOriginalCall();
128        if (call != null) {
129            try {
130                // For CDMA calls, this just sends a flash command.
131                call.getPhone().switchHoldingAndActive();
132            } catch (CallStateException e) {
133                Log.e(this, e, "Error while trying to send flash command.");
134            }
135        }
136    }
137
138    private Call getMultipartyCallForConnection(Connection connection) {
139        com.android.internal.telephony.Connection radioConnection =
140                getOriginalConnection(connection);
141        if (radioConnection != null) {
142            Call call = radioConnection.getCall();
143            if (call != null && call.isMultiparty()) {
144                return call;
145            }
146        }
147        return null;
148    }
149
150    private Call getOriginalCall() {
151        List<Connection> connections = getConnections();
152        if (!connections.isEmpty()) {
153            com.android.internal.telephony.Connection originalConnection =
154                    getOriginalConnection(connections.get(0));
155            if (originalConnection != null) {
156                return originalConnection.getCall();
157            }
158        }
159        return null;
160    }
161
162    /**
163     * Return whether network support swap after merge conference call.
164     *
165     * @return true to support, false not support.
166     */
167    private final boolean isSwapSupportedAfterMerge()
168    {
169        boolean supportSwapAfterMerge = true;
170        Context context = PhoneGlobals.getInstance();
171
172        if (context != null) {
173            CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(
174                    Context.CARRIER_CONFIG_SERVICE);
175            PersistableBundle b = configManager.getConfig();
176            if (b != null) {
177                supportSwapAfterMerge =
178                        b.getBoolean(CarrierConfigManager.KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL);
179                Log.d(this, "Current network support swap after call merged capability is "
180                        + supportSwapAfterMerge);
181            }
182        }
183        return supportSwapAfterMerge;
184    }
185
186    private com.android.internal.telephony.Connection getOriginalConnection(Connection connection) {
187        if (connection instanceof CdmaConnection) {
188            return ((CdmaConnection) connection).getOriginalConnection();
189        } else {
190            Log.e(this, null, "Non CDMA connection found in a CDMA conference");
191            return null;
192        }
193    }
194
195    private CdmaConnection getFirstConnection() {
196        final List<Connection> connections = getConnections();
197        if (connections.isEmpty()) {
198            return null;
199        }
200        return (CdmaConnection) connections.get(0);
201    }
202}
203