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