1 /* 2 * Copyright (C) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef CELLULAR_CALL_CONTROL_BASE_H 17 #define CELLULAR_CALL_CONTROL_BASE_H 18 19 #include "call_manager_errors.h" 20 #include "event_handler.h" 21 #include "cellular_call_data_struct.h" 22 #include "telephony_log_wrapper.h" 23 #include "base_connection.h" 24 #include "hril_call_parcel.h" 25 #include "mmi_code_utils.h" 26 27 namespace OHOS { 28 namespace Telephony { 29 class ControlBase { 30 public: 31 /** 32 * constructor 33 */ 34 ControlBase() = default; 35 36 /** 37 * destructor 38 */ 39 virtual ~ControlBase() = default; 40 41 /** 42 * Dial 43 * 44 * 27007-430_2001 6.27 Informative examples 45 * 3GPP TS 22.030 [19] 46 * 47 * originate a voice call 48 * 49 * @param CellularCallInfo 50 * @return Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 51 */ 52 virtual int32_t Dial(const CellularCallInfo &callInfo) = 0; 53 54 /** 55 * HangUp 56 * 57 * 3GPP TS 27.007 V3.9.0 (2001-06) Call related supplementary services +CHLD 58 * 3GPP TS 27.007 V3.9.0 (2001-06) 7.22 Informative examples 59 * 3GPP TS 22.030 [19] 60 * 61 * release call 62 * 63 * @param CellularCallInfo 64 * @param CallSupplementType 65 * @return Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 66 */ 67 virtual int32_t HangUp(const CellularCallInfo &callInfo, CallSupplementType type) = 0; 68 69 /** 70 * Answer 71 * 72 * 27007-430_2001 6.6 Alternating mode call control method 73 * 3GPP TS 22.030 [19] 74 * 75 * Answer an incoming voice call. 76 * 77 * @param CellularCallInfo 78 * @return Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 79 */ 80 virtual int32_t Answer(const CellularCallInfo &callInfo) = 0; 81 82 /** 83 * Reject 84 * 85 * 27007-430_2001 6.6 Alternating mode call control method 86 * 3GPP TS 22.030 [19] 87 * 88 * Reject an incoming voice call 89 * 90 * @param CellularCallInfo 91 * @return Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 92 */ 93 virtual int32_t Reject(const CellularCallInfo &callInfo) = 0; 94 95 /** 96 * HoldCall 97 * 98 * 22083-400_2001 2 Call hold 99 * 3GPP TS 22.030 [3] 100 * 3GPP TS 23.083 V4.2.0 (2001-04) 2 Call hold (HOLD) 101 * 102 * The call hold service allows a served mobile subscriber 103 * 104 * @param slotId 105 * @return Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 106 */ 107 virtual int32_t HoldCall(int32_t slotId) = 0; 108 109 /** 110 * UnHoldCall 111 * 112 * 22083-400_2001 2 Call hold 113 * 3GPP TS 22.030 [3] 114 * 115 * Retrieve the held call. 116 * 117 * @param slotId 118 * @return Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 119 */ 120 virtual int32_t UnHoldCall(int32_t slotId) = 0; 121 122 /** 123 * SwitchCall 124 * 125 * 22083-400_2001 2 Call hold 126 * 3GPP TS 22.030 [3] 127 * 128 * Alternate from one call to the other 129 * 130 * @param slotId 131 * @return Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 132 */ 133 virtual int32_t SwitchCall(int32_t slotId) = 0; 134 135 /** 136 * CombineConference 137 * 138 * 22084-400_2001 1.3.8.2 Managing an active multiParty call 139 * 3GPP TS 22.030 140 * 141 * Add another remote party 142 * @param slotId 143 * @return Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 144 */ 145 virtual int32_t CombineConference(int32_t slotId) = 0; 146 147 /** 148 * HangUpAllConnection 149 * 150 * @param slotId 151 * @return Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 152 */ 153 virtual int32_t HangUpAllConnection(int32_t slotId) = 0; 154 155 /** 156 * ReportCallsData 157 * 158 * @param slotId 159 * @param CallInfoList 160 * @returns Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 161 */ 162 virtual int32_t ReportCallsData(int32_t slotId, const CallInfoList &callInfoList) = 0; 163 164 /** 165 * Dial PreJudgment 166 * 167 * @param CellularCallInfo 168 * @returns Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 169 */ 170 int32_t DialPreJudgment(const CellularCallInfo &callInfo); 171 172 /** 173 * Is Need Execute MMI 174 * 175 * @param slotId 176 * @param std::string phoneString 177 * @param CLIRMode 178 * @returns bool 179 */ 180 bool IsNeedExecuteMMI(int32_t slotId, std::string &phoneString, CLIRMode &clirMode); 181 182 /** 183 * Is Dtmf Key 184 * 185 * 23014-400_2001 6 Support of DTMF across the air interface 186 * 3GPP TS 22.030 187 * 188 * @param char 189 * @returns bool 190 */ 191 bool IsDtmfKey(char c) const; 192 193 /** 194 * Determine whether the call can be initiated currently 195 * 196 * @param std::map<std::string, BaseConnection> 197 * @return Returns true can to call 198 */ 199 template<typename T> CanCall(T && t)200 bool CanCall(T &&t) 201 { 202 unsigned int maximumCalls = 6; 203 return t.size() <= maximumCalls; 204 } 205 206 /** 207 * FindConnectionByState 208 * 209 * @param std::map<std::string, BaseConnection> 210 * @param TelCallState 211 * @return pointer 212 */ 213 template<typename T1, typename T2> FindConnectionByState(const T1 && t1,TelCallState state)214 T2 FindConnectionByState(const T1 &&t1, TelCallState state) const 215 { 216 for (auto &it : t1) { 217 T2 pConnection = &it.second; 218 if (pConnection != nullptr && pConnection->GetStatus() == state) { 219 return pConnection; 220 } 221 } 222 return nullptr; 223 } 224 225 /** 226 * FindConnectionByIndex 227 * 228 * @param std::map<std::string, BaseConnection> 229 * @param index 230 * @return pointer 231 */ 232 template<typename T1, typename T2> FindConnectionByIndex(const T1 && t1,int32_t index)233 T2 FindConnectionByIndex(const T1 &&t1, int32_t index) const 234 { 235 for (auto &it : t1) { 236 T2 pConnection = &it.second; 237 if (pConnection != nullptr && pConnection->GetIndex() == index) { 238 return pConnection; 239 } 240 } 241 return nullptr; 242 } 243 244 /** 245 * SetConnectionData 246 * 247 * @param std::map<std::string, BaseConnection> 248 * @param string phoneNum 249 * @param BaseConnection 250 * @return bool 251 */ 252 template<typename T1, typename T2> SetConnectionData(T1 && t1,const std::string & key,const T2 & con)253 bool SetConnectionData(T1 &&t1, const std::string &key, const T2 &con) 254 { 255 if (key.empty()) { 256 TELEPHONY_LOGE("SetConnectionData, key is empty."); 257 return false; 258 } 259 if (!t1.insert(std::make_pair(key, con)).second) { 260 TELEPHONY_LOGE("SetConnectionData, key already exists."); 261 return false; 262 } 263 return true; 264 } 265 266 /** 267 * GetConnectionData 268 * 269 * @param std::map<std::string, BaseConnection> 270 * @param string phoneNum 271 * @return pointer 272 */ 273 template<typename T1, typename T2> GetConnectionData(const T1 && t1,const std::string & key)274 T2 GetConnectionData(const T1 &&t1, const std::string &key) const 275 { 276 if (key.empty()) { 277 TELEPHONY_LOGE("GetConnectionData, key is empty."); 278 return nullptr; 279 } 280 281 auto p = t1.find(key); 282 if (p != t1.end()) { 283 return &p->second; 284 } 285 return nullptr; 286 } 287 288 /** 289 * Determines if a connection is currently in this state 290 * 291 * @param std::map<std::string, BaseConnection> 292 * @param TelCallState 293 * @return Returns true or false 294 */ 295 template<typename T1> IsInState(T1 && t,TelCallState state)296 bool IsInState(T1 &&t, TelCallState state) 297 { 298 for (const auto &it : t) { 299 auto pConnection = &it.second; 300 if (pConnection != nullptr && pConnection->GetStatus() == state) { 301 return true; 302 } 303 } 304 return false; 305 } 306 307 /** 308 * StartDtmf 309 * 310 * 23014-400_2001 6 Support of DTMF across the air interface 311 * 3GPP TS 22.030 312 * 313 * START DTMF : Containing the digit value (0-9,A,B,C,D,*,#) 314 * @param std::map<std::string, BaseConnection> 315 * @param Dtmf Code 316 * @param CellularCallInfo 317 * @return Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 318 */ 319 template<typename T> StartDtmf(T && t,char cDtmfCode,const CellularCallInfo & callInfo)320 int32_t StartDtmf(T &&t, char cDtmfCode, const CellularCallInfo &callInfo) const 321 { 322 /** 323 * The messages when sent across the air interface should contain the following information: 324 * a) START DTMF : Containing the digit value (0-9,A,B,C,D,*,#); 325 * b) START DTMF ACKNOWLEDGE: Containing the digit value (0-9,A,B,C,D,*,#) corresponding to the DTMF tone that 326 * the network applies towards the remote user; 327 * c) STOP DTMF : No further info; 328 * d) STOP DTMF ACKNOWLEDGE: No further info. 329 * Only a single digit will be passed in each START DTMF and START DTMF ACKNOWLEDGE message 330 */ 331 TELEPHONY_LOGI("ControlBase::StartDtmf start"); 332 auto pConnection = GetConnectionData<T &, decltype(&t.begin()->second)>(t, callInfo.phoneNum); 333 if (pConnection == nullptr) { 334 TELEPHONY_LOGI("StartDtmf: connection cannot be matched, use index directly"); 335 pConnection = FindConnectionByIndex<T &, decltype(&t.begin()->second)>(t, callInfo.index); 336 } 337 if (pConnection == nullptr) { 338 TELEPHONY_LOGE("StartDtmf, error type: connection is null"); 339 return CALL_ERR_CALL_CONNECTION_NOT_EXIST; 340 } 341 if (!IsDtmfKey(cDtmfCode)) { 342 TELEPHONY_LOGE("StartDtmf return, error type: cDtmfCode invalid."); 343 return CALL_ERR_PARAMETER_OUT_OF_RANGE; 344 } 345 return pConnection->StartDtmfRequest(callInfo.slotId, cDtmfCode, pConnection->GetIndex()); 346 } 347 348 /** 349 * StopDtmf 350 * 351 * 23014-400_2001 6 Support of DTMF across the air interface 352 * 3GPP TS 22.030 353 * 354 * STOP DTMF : No further info 355 * @param std::map<std::string, BaseConnection> 356 * @param CellularCallInfo 357 * @return Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 358 */ 359 template<typename T> StopDtmf(T && t,const CellularCallInfo & callInfo)360 int32_t StopDtmf(T &&t, const CellularCallInfo &callInfo) const 361 { 362 /** 363 * The messages when sent across the air interface should contain the following information: 364 * a) START DTMF : Containing the digit value (0-9,A,B,C,D,*,#); 365 * b) START DTMF ACKNOWLEDGE: Containing the digit value (0-9,A,B,C,D,*,#) corresponding to the DTMF tone that 366 * the network applies towards the remote user; 367 * c) STOP DTMF : No further info; 368 * d) STOP DTMF ACKNOWLEDGE: No further info. 369 * Only a single digit will be passed in each START DTMF and START DTMF ACKNOWLEDGE message 370 */ 371 TELEPHONY_LOGI("ControlBase::StopDtmf start"); 372 auto pConnection = GetConnectionData<T &, decltype(&t.begin()->second)>(t, callInfo.phoneNum); 373 if (pConnection == nullptr) { 374 TELEPHONY_LOGI("StopDtmf: connection cannot be matched, use index directly"); 375 pConnection = FindConnectionByIndex<T &, decltype(&t.begin()->second)>(t, callInfo.index); 376 } 377 if (pConnection == nullptr) { 378 TELEPHONY_LOGE("StopDtmf, error type: connection is null"); 379 return CALL_ERR_CALL_CONNECTION_NOT_EXIST; 380 } 381 return pConnection->StopDtmfRequest(callInfo.slotId, pConnection->GetIndex()); 382 } 383 384 /** 385 * SendDtmf 386 * 387 * 23014-400_2001 6 Support of DTMF across the air interface 388 * 3GPP TS 22.030 389 * 390 * @param std::map<std::string, BaseConnection> 391 * @param Dtmf Code 392 * @param CellularCallInfo 393 * @return Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 394 */ 395 template<typename T> SendDtmf(T && t,char cDtmfCode,const CellularCallInfo & callInfo)396 int32_t SendDtmf(T &&t, char cDtmfCode, const CellularCallInfo &callInfo) const 397 { 398 /** 399 * 3gpp 27007-430_2001 400 * 401 * C.2.11 DTMF and tone generation +VTS 402 * 403 * This command allows the transmission of DTMF tones and arbitrary tones (see note). 404 * These tones may be used (for example) when announcing the start of a recording period. 405 * The command is write only. 406 * In this profile of commands, this command does not operate in data or fax modes of operation (+FCLASS=0,1,2 407 7). NOTE 1: D is used only for dialling. 408 409 The string parameter of the command consists of combinations of the following separated by commas: 410 1. <DTMF>. A single ASCII character in the set 0 9, #,*,A D. 411 This is interpreted as a single ACSII character whose duration is set by the +VTD command. 412 NOTE 2: In GSM this operates only in voice mode. 413 2. [<tone1>,<tone2>,<duration>]. 414 This is interpreted as a dual tone of frequencies <tone1> and <tone2>, lasting for a time <duration> (in 10 415 ms multiples). NOTE 3: This does not operate in GSM. 416 3. {<DTMF>,<duration>}. This is interpreted as a DTMF tone of different duration from that mandated by the 417 +VTD command. NOTE 4: In GSM this operates only in voice mode. 418 */ 419 TELEPHONY_LOGI("ControlBase::SendDtmf start"); 420 auto pConnection = GetConnectionData<T &, decltype(&t.begin()->second)>(t, callInfo.phoneNum); 421 if (pConnection == nullptr) { 422 TELEPHONY_LOGI("SendDtmf: connection cannot be matched, use index directly"); 423 pConnection = FindConnectionByIndex<T &, decltype(&t.begin()->second)>(t, callInfo.index); 424 } 425 if (pConnection == nullptr) { 426 TELEPHONY_LOGE("SendDtmf, error type: connection is null"); 427 return CALL_ERR_CALL_CONNECTION_NOT_EXIST; 428 } 429 if (!IsDtmfKey(cDtmfCode)) { 430 TELEPHONY_LOGE("SendDtmf return, error type: cDtmfCode invalid."); 431 return CALL_ERR_PARAMETER_OUT_OF_RANGE; 432 } 433 return pConnection->SendDtmfRequest(callInfo.slotId, cDtmfCode, pConnection->GetIndex()); 434 } 435 436 /** 437 * GetCallFailReason 438 * 439 * 3GPP TS 24.008 V17.4.0 (2021-09) 10.5.4.11 Cause 440 * 441 * @return Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 442 */ 443 template<typename T> GetCallFailReason(int32_t slotId,T && t)444 int32_t GetCallFailReason(int32_t slotId, T &&t) const 445 { 446 decltype(t.begin()->second) connection; 447 return connection.GetCallFailReasonRequest(slotId); 448 } 449 450 private: 451 std::shared_ptr<AppExecFwk::EventRunner> eventLoop_; 452 }; 453 } // namespace Telephony 454 } // namespace OHOS 455 456 #endif // CELLULAR_CALL_CONTROL_BASE_H 457