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