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#include "activating.h"
17
18#include "cellular_data_event_code.h"
19#include "cellular_data_hisysevent.h"
20#include "tel_ril_data_parcel.h"
21#include "inactive.h"
22#include "radio_event.h"
23#include "telephony_log_wrapper.h"
24#include "apn_manager.h"
25
26namespace OHOS {
27namespace Telephony {
28void Activating::StateBegin()
29{
30    TELEPHONY_LOGI("Enter activating state");
31    std::shared_ptr<CellularDataStateMachine> stateMachine = stateMachine_.lock();
32    if (stateMachine == nullptr) {
33        TELEPHONY_LOGE("stateMachine is null");
34        return;
35    }
36    isActive_ = true;
37    stateMachine->SetCurrentState(sptr<State>(this));
38}
39
40void Activating::StateEnd()
41{
42    TELEPHONY_LOGI("Exit activating state");
43    isActive_ = false;
44}
45
46bool Activating::RilActivatePdpContextDone(const AppExecFwk::InnerEvent::Pointer &event)
47{
48    if (event == nullptr) {
49        TELEPHONY_LOGE("event is null");
50        return false;
51    }
52    std::shared_ptr<CellularDataStateMachine> stateMachine = stateMachine_.lock();
53    if (stateMachine == nullptr) {
54        TELEPHONY_LOGE("stateMachine is null");
55        return false;
56    }
57    std::shared_ptr<SetupDataCallResultInfo> resultInfo = event->GetSharedObject<SetupDataCallResultInfo>();
58    if (resultInfo == nullptr) {
59        TELEPHONY_LOGI("resultInfo null, goto RilErrorResponse");
60        return RilErrorResponse(event);
61    }
62    TELEPHONY_LOGI("callDone active: %{public}d flag: %{public}d, cid: %{public}d, reason: %{public}d",
63        resultInfo->active, resultInfo->flag, resultInfo->cid, resultInfo->reason);
64    if (stateMachine->connectId_ != resultInfo->flag) {
65        TELEPHONY_LOGE("connectId is %{public}d, flag is %{public}d", stateMachine->connectId_, resultInfo->flag);
66        return false;
67    }
68    Inactive *inActive = static_cast<Inactive *>(stateMachine->inActiveState_.GetRefPtr());
69    if (inActive == nullptr) {
70        TELEPHONY_LOGE("Inactive is null");
71        return false;
72    }
73    stateMachine->SetCid(resultInfo->cid);
74    if (resultInfo->reason != 0 || resultInfo->active == 0) {
75        resultInfo->retryScene = static_cast<int32_t>(RetryScene::RETRY_SCENE_SETUP_DATA);
76        inActive->SetDataCallResultInfo(resultInfo);
77        inActive->SetDeActiveApnTypeId(stateMachine->apnId_);
78        stateMachine->TransitionTo(stateMachine->inActiveState_);
79        return true;
80    }
81    if (stateMachine->cdConnectionManager_ != nullptr) {
82        stateMachine->cdConnectionManager_->AddActiveConnectionByCid(stateMachine_.lock());
83    } else {
84        TELEPHONY_LOGE("cdConnectionManager is null");
85    }
86    stateMachine->DeferEvent(std::move(event));
87    stateMachine->TransitionTo(stateMachine->activeState_);
88    return true;
89}
90
91bool Activating::RilErrorResponse(const AppExecFwk::InnerEvent::Pointer &event)
92{
93    std::shared_ptr<CellularDataStateMachine> stateMachine = stateMachine_.lock();
94    if (stateMachine == nullptr) {
95        TELEPHONY_LOGE("stateMachine is null");
96        return false;
97    }
98    std::shared_ptr<RadioResponseInfo> rilInfo = event->GetSharedObject<RadioResponseInfo>();
99    if (rilInfo == nullptr) {
100        TELEPHONY_LOGE("SetupDataCallResultInfo and RadioResponseInfo is null");
101        return false;
102    }
103    if (stateMachine->connectId_ != rilInfo->flag) {
104        TELEPHONY_LOGE("connectId is %{public}d, flag is %{public}d", stateMachine->connectId_, rilInfo->flag);
105        return false;
106    }
107    TELEPHONY_LOGI("RadioResponseInfo flag:%{public}d error:%{public}d", rilInfo->flag, rilInfo->error);
108    Inactive *inActive = static_cast<Inactive *>(stateMachine->inActiveState_.GetRefPtr());
109    if (inActive == nullptr) {
110        TELEPHONY_LOGE("Inactive is null");
111        return false;
112    }
113    switch (rilInfo->error) {
114        case ErrType::ERR_GENERIC_FAILURE:
115        case ErrType::ERR_CMD_SEND_FAILURE:
116        case ErrType::ERR_NULL_POINT: {
117            inActive->SetDataCallResultInfoToRetry();
118            CellularDataHiSysEvent::WriteDataActivateFaultEvent(INVALID_PARAMETER, SWITCH_ON,
119                CellularDataErrorCode::DATA_ERROR_RADIO_RESPONSEINFO_ERROR,
120                "ErrType " + std::to_string(static_cast<int32_t>(rilInfo->error)));
121            TELEPHONY_LOGD("Handle supported error responses and retry the connection.");
122            break;
123        }
124        case ErrType::ERR_INVALID_RESPONSE:
125        case ErrType::ERR_CMD_NO_CARRIER:
126        case ErrType::ERR_HDF_IPC_FAILURE:
127        default: {
128            inActive->SetDataCallResultInfoToClear();
129            TELEPHONY_LOGE("Handle error response to clear connection");
130            break;
131        }
132    }
133    inActive->SetDeActiveApnTypeId(stateMachine->apnId_);
134    stateMachine->TransitionTo(stateMachine->inActiveState_);
135    return true;
136}
137
138void Activating::ProcessConnectTimeout(const AppExecFwk::InnerEvent::Pointer &event)
139{
140    if (event == nullptr) {
141        TELEPHONY_LOGE("event is null");
142        return;
143    }
144    int32_t connectId = event->GetParam();
145    std::shared_ptr<CellularDataStateMachine> stateMachine = stateMachine_.lock();
146    if (stateMachine == nullptr) {
147        TELEPHONY_LOGE("stateMachine is null");
148        return;
149    }
150    if (connectId != stateMachine->connectId_) {
151        return;
152    }
153    Inactive *inActive = static_cast<Inactive *>(stateMachine->inActiveState_.GetRefPtr());
154    if (inActive == nullptr) {
155        TELEPHONY_LOGE("Inactive is null");
156        return;
157    }
158    inActive->SetDeActiveApnTypeId(stateMachine->apnId_);
159    inActive->SetDataCallResultInfoToRetry();
160    stateMachine->TransitionTo(stateMachine->inActiveState_);
161    std::string apnType = ApnManager::FindApnNameByApnId(stateMachine->apnId_);
162    CellularDataHiSysEvent::WriteDataActivateFaultEvent(stateMachine->GetSlotId(), SWITCH_ON,
163        CellularDataErrorCode::DATA_ERROR_DATA_ACTIVATE_TIME_OUT, apnType + " activate time out.");
164    TELEPHONY_LOGI("ProcessConnectTimeout");
165}
166
167bool Activating::StateProcess(const AppExecFwk::InnerEvent::Pointer &event)
168{
169    if (event == nullptr) {
170        TELEPHONY_LOGE("event is null");
171        return false;
172    }
173    std::shared_ptr<CellularDataStateMachine> stateMachine = stateMachine_.lock();
174    if (stateMachine == nullptr) {
175        TELEPHONY_LOGE("stateMachine is null");
176        return false;
177    }
178    bool retVal = false;
179    uint32_t eventCode = event->GetInnerEventId();
180    switch (eventCode) {
181        case CellularDataEventCode::MSG_SM_DRS_OR_RAT_CHANGED:
182            [[fallthrough]];
183        case CellularDataEventCode::MSG_SM_CONNECT:
184            TELEPHONY_LOGI("Activating::MSG_SM_CONNECT");
185            stateMachine->DeferEvent(std::move(event));
186            retVal = PROCESSED;
187            break;
188        case RadioEvent::RADIO_RIL_SETUP_DATA_CALL: {
189            retVal = RilActivatePdpContextDone(event);
190            break;
191        }
192        case CellularDataEventCode::MSG_SM_GET_LAST_FAIL_DONE:
193            stateMachine->TransitionTo(stateMachine->inActiveState_);
194            retVal = PROCESSED;
195            break;
196        case CellularDataEventCode::MSG_GET_RIL_BANDWIDTH:
197            stateMachine->DeferEvent(std::move(event));
198            break;
199        case CellularDataEventCode::MSG_CONNECT_TIMEOUT_CHECK:
200            ProcessConnectTimeout(event);
201            retVal = PROCESSED;
202            break;
203        default:
204            TELEPHONY_LOGE("eventCode:%{public}d goto default", eventCode);
205            break;
206    }
207    return retVal;
208}
209} // namespace Telephony
210} // namespace OHOS