1 /* 2 * Copyright (C) 2021-2022 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 * Ignore the hangup report when the hangup is caused by CallManager crash. 195 * 196 * @param ignored which decides whether to ignore the hangup report 197 */ 198 void SetHangupReportIgnoredFlag(bool ignored); 199 200 /** 201 * Determine whether the call can be initiated currently 202 * 203 * @param std::map<std::string, BaseConnection> 204 * @return Returns true can to call 205 */ 206 template<typename T> CanCall(T && t)207 bool CanCall(T &&t) 208 { 209 unsigned int maximumCalls = 6; 210 return t.size() <= maximumCalls; 211 } 212 213 /** 214 * FindConnectionByState 215 * 216 * @param std::map<std::string, BaseConnection> 217 * @param TelCallState 218 * @return pointer 219 */ 220 template<typename T1, typename T2> FindConnectionByState(const T1 && t1,TelCallState state)221 T2 FindConnectionByState(const T1 &&t1, TelCallState state) const 222 { 223 for (auto &it : t1) { 224 T2 pConnection = &it.second; 225 if (pConnection != nullptr && pConnection->GetStatus() == state) { 226 return pConnection; 227 } 228 } 229 return nullptr; 230 } 231 232 /** 233 * FindConnectionByIndex 234 * 235 * @param std::map<std::string, BaseConnection> 236 * @param index 237 * @return pointer 238 */ 239 template<typename T1, typename T2> FindConnectionByIndex(const T1 && t1,int32_t index)240 T2 FindConnectionByIndex(const T1 &&t1, int32_t index) const 241 { 242 for (auto &it : t1) { 243 T2 pConnection = &it.second; 244 if (pConnection != nullptr && pConnection->GetIndex() == index) { 245 return pConnection; 246 } 247 } 248 return nullptr; 249 } 250 251 /** 252 * SetConnectionData 253 * 254 * @param std::map<std::string, BaseConnection> 255 * @param string phoneNum 256 * @param BaseConnection 257 * @return bool 258 */ 259 template<typename T1, typename T2> SetConnectionData(T1 && t1,const std::string & key,const T2 & con)260 bool SetConnectionData(T1 &&t1, const std::string &key, const T2 &con) 261 { 262 if (key.empty()) { 263 TELEPHONY_LOGE("SetConnectionData, key is empty."); 264 return false; 265 } 266 if (!t1.insert(std::make_pair(key, con)).second) { 267 TELEPHONY_LOGE("SetConnectionData, key already exists."); 268 return false; 269 } 270 return true; 271 } 272 273 /** 274 * GetConnectionData 275 * 276 * @param std::map<std::string, BaseConnection> 277 * @param string phoneNum 278 * @return pointer 279 */ 280 template<typename T1, typename T2> GetConnectionData(const T1 && t1,const std::string & key)281 T2 GetConnectionData(const T1 &&t1, const std::string &key) const 282 { 283 if (key.empty()) { 284 TELEPHONY_LOGE("GetConnectionData, key is empty."); 285 return nullptr; 286 } 287 288 auto p = t1.find(key); 289 if (p != t1.end()) { 290 return &p->second; 291 } 292 return nullptr; 293 } 294 295 /** 296 * Determines if a connection is currently in this state 297 * 298 * @param std::map<std::string, BaseConnection> 299 * @param TelCallState 300 * @return Returns true or false 301 */ 302 template<typename T1> IsInState(T1 && t,TelCallState state)303 bool IsInState(T1 &&t, TelCallState state) 304 { 305 for (const auto &it : t) { 306 auto pConnection = &it.second; 307 if (pConnection != nullptr && pConnection->GetStatus() == state) { 308 return true; 309 } 310 } 311 return false; 312 } 313 314 /** 315 * StartDtmf 316 * 317 * 23014-400_2001 6 Support of DTMF across the air interface 318 * 3GPP TS 22.030 319 * 320 * START DTMF : Containing the digit value (0-9,A,B,C,D,*,#) 321 * @param std::map<std::string, BaseConnection> 322 * @param Dtmf Code 323 * @param CellularCallInfo 324 * @return Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 325 */ 326 template<typename T> StartDtmf(T && t,char cDtmfCode,const CellularCallInfo & callInfo)327 int32_t StartDtmf(T &&t, char cDtmfCode, const CellularCallInfo &callInfo) const 328 { 329 /** 330 * The messages when sent across the air interface should contain the following information: 331 * a) START DTMF : Containing the digit value (0-9,A,B,C,D,*,#); 332 * b) START DTMF ACKNOWLEDGE: Containing the digit value (0-9,A,B,C,D,*,#) corresponding to the DTMF tone that 333 * the network applies towards the remote user; 334 * c) STOP DTMF : No further info; 335 * d) STOP DTMF ACKNOWLEDGE: No further info. 336 * Only a single digit will be passed in each START DTMF and START DTMF ACKNOWLEDGE message 337 */ 338 TELEPHONY_LOGI("ControlBase::StartDtmf start"); 339 auto pConnection = GetConnectionData<T &, decltype(&t.begin()->second)>(t, callInfo.phoneNum); 340 if (pConnection == nullptr) { 341 TELEPHONY_LOGI("StartDtmf: connection cannot be matched, use index directly"); 342 pConnection = FindConnectionByIndex<T &, decltype(&t.begin()->second)>(t, callInfo.index); 343 } 344 if (pConnection == nullptr) { 345 TELEPHONY_LOGE("StartDtmf, error type: connection is null"); 346 return CALL_ERR_CALL_CONNECTION_NOT_EXIST; 347 } 348 if (!IsDtmfKey(cDtmfCode)) { 349 TELEPHONY_LOGE("StartDtmf return, error type: cDtmfCode invalid."); 350 return CALL_ERR_PARAMETER_OUT_OF_RANGE; 351 } 352 return pConnection->StartDtmfRequest(callInfo.slotId, cDtmfCode, pConnection->GetIndex()); 353 } 354 355 /** 356 * StopDtmf 357 * 358 * 23014-400_2001 6 Support of DTMF across the air interface 359 * 3GPP TS 22.030 360 * 361 * STOP DTMF : No further info 362 * @param std::map<std::string, BaseConnection> 363 * @param CellularCallInfo 364 * @return Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 365 */ 366 template<typename T> StopDtmf(T && t,const CellularCallInfo & callInfo)367 int32_t StopDtmf(T &&t, const CellularCallInfo &callInfo) const 368 { 369 /** 370 * The messages when sent across the air interface should contain the following information: 371 * a) START DTMF : Containing the digit value (0-9,A,B,C,D,*,#); 372 * b) START DTMF ACKNOWLEDGE: Containing the digit value (0-9,A,B,C,D,*,#) corresponding to the DTMF tone that 373 * the network applies towards the remote user; 374 * c) STOP DTMF : No further info; 375 * d) STOP DTMF ACKNOWLEDGE: No further info. 376 * Only a single digit will be passed in each START DTMF and START DTMF ACKNOWLEDGE message 377 */ 378 TELEPHONY_LOGI("ControlBase::StopDtmf start"); 379 auto pConnection = GetConnectionData<T &, decltype(&t.begin()->second)>(t, callInfo.phoneNum); 380 if (pConnection == nullptr) { 381 TELEPHONY_LOGI("StopDtmf: connection cannot be matched, use index directly"); 382 pConnection = FindConnectionByIndex<T &, decltype(&t.begin()->second)>(t, callInfo.index); 383 } 384 if (pConnection == nullptr) { 385 TELEPHONY_LOGE("StopDtmf, error type: connection is null"); 386 return CALL_ERR_CALL_CONNECTION_NOT_EXIST; 387 } 388 return pConnection->StopDtmfRequest(callInfo.slotId, pConnection->GetIndex()); 389 } 390 391 /** 392 * SendDtmf 393 * 394 * 23014-400_2001 6 Support of DTMF across the air interface 395 * 3GPP TS 22.030 396 * 397 * @param std::map<std::string, BaseConnection> 398 * @param Dtmf Code 399 * @param CellularCallInfo 400 * @return Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 401 */ 402 template<typename T> SendDtmf(T && t,char cDtmfCode,const CellularCallInfo & callInfo)403 int32_t SendDtmf(T &&t, char cDtmfCode, const CellularCallInfo &callInfo) const 404 { 405 /** 406 * 3gpp 27007-430_2001 407 * 408 * C.2.11 DTMF and tone generation +VTS 409 * 410 * This command allows the transmission of DTMF tones and arbitrary tones (see note). 411 * These tones may be used (for example) when announcing the start of a recording period. 412 * The command is write only. 413 * In this profile of commands, this command does not operate in data or fax modes of operation (+FCLASS=0,1,2 414 7). NOTE 1: D is used only for dialling. 415 416 The string parameter of the command consists of combinations of the following separated by commas: 417 1. <DTMF>. A single ASCII character in the set 0 9, #,*,A D. 418 This is interpreted as a single ACSII character whose duration is set by the +VTD command. 419 NOTE 2: In GSM this operates only in voice mode. 420 2. [<tone1>,<tone2>,<duration>]. 421 This is interpreted as a dual tone of frequencies <tone1> and <tone2>, lasting for a time <duration> (in 10 422 ms multiples). NOTE 3: This does not operate in GSM. 423 3. {<DTMF>,<duration>}. This is interpreted as a DTMF tone of different duration from that mandated by the 424 +VTD command. NOTE 4: In GSM this operates only in voice mode. 425 */ 426 TELEPHONY_LOGI("ControlBase::SendDtmf start"); 427 auto pConnection = GetConnectionData<T &, decltype(&t.begin()->second)>(t, callInfo.phoneNum); 428 if (pConnection == nullptr) { 429 TELEPHONY_LOGI("SendDtmf: connection cannot be matched, use index directly"); 430 pConnection = FindConnectionByIndex<T &, decltype(&t.begin()->second)>(t, callInfo.index); 431 } 432 if (pConnection == nullptr) { 433 TELEPHONY_LOGE("SendDtmf, error type: connection is null"); 434 return CALL_ERR_CALL_CONNECTION_NOT_EXIST; 435 } 436 if (!IsDtmfKey(cDtmfCode)) { 437 TELEPHONY_LOGE("SendDtmf return, error type: cDtmfCode invalid."); 438 return CALL_ERR_PARAMETER_OUT_OF_RANGE; 439 } 440 return pConnection->SendDtmfRequest(callInfo.slotId, cDtmfCode, pConnection->GetIndex()); 441 } 442 443 /** 444 * GetCallFailReason 445 * 446 * 3GPP TS 24.008 V17.4.0 (2021-09) 10.5.4.11 Cause 447 * 448 * @return Error Code: Returns TELEPHONY_SUCCESS on success, others on failure. 449 */ 450 template<typename T> GetCallFailReason(int32_t slotId,T && t)451 int32_t GetCallFailReason(int32_t slotId, T &&t) const 452 { 453 decltype(t.begin()->second) connection; 454 return connection.GetCallFailReasonRequest(slotId); 455 } 456 457 protected: 458 bool isIgnoredHangupReport_ = false; 459 bool isIgnoredIncomingCall_ = false; 460 461 private: 462 std::shared_ptr<AppExecFwk::EventRunner> eventLoop_; 463 }; 464 } // namespace Telephony 465 } // namespace OHOS 466 467 #endif // CELLULAR_CALL_CONTROL_BASE_H 468