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 
25 namespace OHOS {
26 namespace Telephony {
StateBegin()27 void Activating::StateBegin()
28 {
29     TELEPHONY_LOGI("Enter activating state");
30     std::shared_ptr<CellularDataStateMachine> stateMachine = stateMachine_.lock();
31     if (stateMachine == nullptr) {
32         TELEPHONY_LOGE("stateMachine is null");
33         return;
34     }
35     isActive_ = true;
36     stateMachine->SetCurrentState(sptr<State>(this));
37 }
38 
StateEnd()39 void Activating::StateEnd()
40 {
41     TELEPHONY_LOGI("Exit activating state");
42     isActive_ = false;
43 }
44 
RilActivatePdpContextDone(const AppExecFwk::InnerEvent::Pointer & event)45 bool Activating::RilActivatePdpContextDone(const AppExecFwk::InnerEvent::Pointer &event)
46 {
47     if (event == nullptr) {
48         TELEPHONY_LOGE("event is null");
49         return false;
50     }
51     std::shared_ptr<CellularDataStateMachine> stateMachine = stateMachine_.lock();
52     if (stateMachine == nullptr) {
53         TELEPHONY_LOGE("stateMachine is null");
54         return false;
55     }
56     std::shared_ptr<SetupDataCallResultInfo> resultInfo = event->GetSharedObject<SetupDataCallResultInfo>();
57     if (resultInfo == nullptr) {
58         return RilErrorResponse(event);
59     }
60     TELEPHONY_LOGI("callDone active: %{public}d flag: %{public}d, cid: %{public}d, reason: %{public}d",
61         resultInfo->active, resultInfo->flag, resultInfo->cid, resultInfo->reason);
62     if (stateMachine->connectId_ != resultInfo->flag) {
63         TELEPHONY_LOGE("connectId is %{public}d, flag is %{public}d", stateMachine->connectId_, resultInfo->flag);
64         return false;
65     }
66     Inactive *inActive = static_cast<Inactive *>(stateMachine->inActiveState_.GetRefPtr());
67     if (inActive == nullptr) {
68         TELEPHONY_LOGE("Inactive is null");
69         return false;
70     }
71     if (resultInfo->reason != 0) {
72         DisConnectionReason disReason = DataCallPdpError(resultInfo->reason);
73         inActive->SetReason(disReason);
74         inActive->SetDeActiveApnTypeId(stateMachine->apnId_);
75         stateMachine->TransitionTo(stateMachine->inActiveState_);
76         return true;
77     }
78     if (resultInfo->active == 0) {
79         inActive->SetDeActiveApnTypeId(stateMachine->apnId_);
80         inActive->SetReason(DisConnectionReason::REASON_RETRY_CONNECTION);
81         stateMachine->TransitionTo(stateMachine->inActiveState_);
82         return true;
83     }
84     stateMachine->SetCid(resultInfo->cid);
85     if (stateMachine->cdConnectionManager_ != nullptr) {
86         stateMachine->cdConnectionManager_->AddActiveConnectionByCid(stateMachine_.lock());
87     } else {
88         TELEPHONY_LOGE("cdConnectionManager is null");
89     }
90     stateMachine->DeferEvent(std::move(event));
91     stateMachine->TransitionTo(stateMachine->activeState_);
92     return true;
93 }
94 
DataCallPdpError(int32_t reason)95 DisConnectionReason Activating::DataCallPdpError(int32_t reason)
96 {
97     switch (reason) {
98         case PdpErrorReason::PDP_ERR_RETRY:
99         case PdpErrorReason::PDP_ERR_UNKNOWN:
100         case PdpErrorReason::PDP_ERR_SHORTAGE_RESOURCES:
101         case PdpErrorReason::PDP_ERR_ACTIVATION_REJECTED_UNSPECIFIED:
102         case PdpErrorReason::PDP_ERR_SERVICE_OPTION_TEMPORARILY_OUT_OF_ORDER:
103         case PdpErrorReason::PDP_ERR_APN_NOT_SUPPORTED_IN_CURRENT_RAT_PLMN:
104         case PdpErrorReason::PDP_ERR_APN_RESTRICTION_VALUE_INCOMPATIBLE: {
105             TELEPHONY_LOGE("DataCall: The connection failed, try again");
106             return DisConnectionReason::REASON_RETRY_CONNECTION;
107         }
108         case PdpErrorReason::PDP_ERR_MULT_ACCESSES_PDN_NOT_ALLOWED:
109         case PdpErrorReason::PDP_ERR_OPERATOR_DETERMINED_BARRING:
110         case PdpErrorReason::PDP_ERR_MISSING_OR_UNKNOWN_APN:
111         case PdpErrorReason::PDP_ERR_UNKNOWN_PDP_ADDR_OR_TYPE:
112         case PdpErrorReason::PDP_ERR_USER_VERIFICATION:
113         case PdpErrorReason::PDP_ERR_ACTIVATION_REJECTED_GGSN:
114         case PdpErrorReason::PDP_ERR_SERVICE_OPTION_NOT_SUPPORTED:
115         case PdpErrorReason::PDP_ERR_REQUESTED_SERVICE_OPTION_NOT_SUBSCRIBED:
116         case PdpErrorReason::PDP_ERR_NSAPI_ALREADY_USED:
117         case PdpErrorReason::PDP_ERR_IPV4_ONLY_ALLOWED:
118         case PdpErrorReason::PDP_ERR_IPV6_ONLY_ALLOWED:
119         case PdpErrorReason::PDP_ERR_IPV4V6_ONLY_ALLOWED:
120         case PdpErrorReason::PDP_ERR_NON_IP_ONLY_ALLOWED:
121         case PdpErrorReason::PDP_ERR_MAX_NUM_OF_PDP_CONTEXTS:
122         case PdpErrorReason::PDP_ERR_PROTOCOL_ERRORS: {
123             TELEPHONY_LOGE("DataCall: The connection failed, not try again");
124             return DisConnectionReason::REASON_CLEAR_CONNECTION;
125         }
126         default: {
127             if (reason > PDP_ERR_PROTOCOL_ERRORS && reason < PDP_ERR_APN_RESTRICTION_VALUE_INCOMPATIBLE) {
128                 TELEPHONY_LOGE("DataCall: The protocol error, not try again");
129                 return DisConnectionReason::REASON_CLEAR_CONNECTION;
130             }
131             break;
132         }
133     }
134     TELEPHONY_LOGE("DataCall: Connection failed for an unsupported reason, not try again");
135     return DisConnectionReason::REASON_CLEAR_CONNECTION;
136 }
137 
RilErrorResponse(const AppExecFwk::InnerEvent::Pointer & event)138 bool Activating::RilErrorResponse(const AppExecFwk::InnerEvent::Pointer &event)
139 {
140     std::shared_ptr<CellularDataStateMachine> stateMachine = stateMachine_.lock();
141     if (stateMachine == nullptr) {
142         TELEPHONY_LOGE("stateMachine is null");
143         return false;
144     }
145     std::shared_ptr<RadioResponseInfo> rilInfo = event->GetSharedObject<RadioResponseInfo>();
146     if (rilInfo == nullptr) {
147         TELEPHONY_LOGE("SetupDataCallResultInfo and RadioResponseInfo is null");
148         return false;
149     }
150     if (stateMachine->connectId_ != rilInfo->flag) {
151         TELEPHONY_LOGE("connectId is %{public}d, flag is %{public}d", stateMachine->connectId_, rilInfo->flag);
152         return false;
153     }
154     TELEPHONY_LOGI("RadioResponseInfo flag:%{public}d error:%{public}d", rilInfo->flag, rilInfo->error);
155     Inactive *inActive = static_cast<Inactive *>(stateMachine->inActiveState_.GetRefPtr());
156     if (inActive == nullptr) {
157         TELEPHONY_LOGE("Inactive is null");
158         return false;
159     }
160     switch (rilInfo->error) {
161         case ErrType::ERR_GENERIC_FAILURE:
162         case ErrType::ERR_CMD_SEND_FAILURE:
163         case ErrType::ERR_NULL_POINT: {
164             inActive->SetReason(DisConnectionReason::REASON_RETRY_CONNECTION);
165             CellularDataHiSysEvent::WriteDataActivateFaultEvent(INVALID_PARAMETER, SWITCH_ON,
166                 CellularDataErrorCode::DATA_ERROR_RADIO_RESPONSEINFO_ERROR,
167                 "ErrType " + std::to_string(static_cast<int32_t>(rilInfo->error)));
168             TELEPHONY_LOGD("Handle supported error responses and retry the connection.");
169             break;
170         }
171         case ErrType::ERR_INVALID_RESPONSE:
172         case ErrType::ERR_CMD_NO_CARRIER:
173         case ErrType::ERR_HDF_IPC_FAILURE:
174             inActive->SetReason(DisConnectionReason::REASON_CLEAR_CONNECTION);
175             TELEPHONY_LOGI("Handle the supported error response and clear the connection.");
176             break;
177         default: {
178             inActive->SetReason(DisConnectionReason::REASON_CLEAR_CONNECTION);
179             TELEPHONY_LOGE("Handle the unsupported error response");
180             break;
181         }
182     }
183     inActive->SetDeActiveApnTypeId(stateMachine->apnId_);
184     stateMachine->TransitionTo(stateMachine->inActiveState_);
185     return true;
186 }
187 
ProcessConnectTimeout(const AppExecFwk::InnerEvent::Pointer & event)188 void Activating::ProcessConnectTimeout(const AppExecFwk::InnerEvent::Pointer &event)
189 {
190     if (event == nullptr) {
191         TELEPHONY_LOGE("event is null");
192         return;
193     }
194     int32_t connectId = event->GetParam();
195     std::shared_ptr<CellularDataStateMachine> stateMachine = stateMachine_.lock();
196     if (stateMachine == nullptr) {
197         TELEPHONY_LOGE("stateMachine is null");
198         return;
199     }
200     if (connectId != stateMachine->connectId_) {
201         return;
202     }
203     int64_t currentTime =
204         std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch())
205             .count();
206     if ((currentTime - stateMachine->startTimeConnectTimeoutTask_) < CONNECTION_TASK_TIME) {
207         TELEPHONY_LOGE("ProcessConnectTimeout error, delay: %{public}lld",
208             static_cast<long long>(currentTime - stateMachine->startTimeConnectTimeoutTask_));
209         return;
210     }
211     Inactive *inActive = static_cast<Inactive *>(stateMachine->inActiveState_.GetRefPtr());
212     if (inActive == nullptr) {
213         TELEPHONY_LOGE("Inactive is null");
214         return;
215     }
216     inActive->SetDeActiveApnTypeId(stateMachine->apnId_);
217     inActive->SetReason(DisConnectionReason::REASON_RETRY_CONNECTION);
218     stateMachine->TransitionTo(stateMachine->inActiveState_);
219     TELEPHONY_LOGI("ProcessConnectTimeout");
220 }
221 
StateProcess(const AppExecFwk::InnerEvent::Pointer & event)222 bool Activating::StateProcess(const AppExecFwk::InnerEvent::Pointer &event)
223 {
224     if (event == nullptr) {
225         TELEPHONY_LOGE("event is null");
226         return false;
227     }
228     std::shared_ptr<CellularDataStateMachine> stateMachine = stateMachine_.lock();
229     if (stateMachine == nullptr) {
230         TELEPHONY_LOGE("stateMachine is null");
231         return false;
232     }
233     bool retVal = false;
234     uint32_t eventCode = event->GetInnerEventId();
235     switch (eventCode) {
236         case CellularDataEventCode::MSG_SM_DRS_OR_RAT_CHANGED:
237             [[fallthrough]];
238         case CellularDataEventCode::MSG_SM_CONNECT:
239             TELEPHONY_LOGI("Activating::MSG_SM_CONNECT");
240             stateMachine->DeferEvent(std::move(event));
241             retVal = PROCESSED;
242             break;
243         case RadioEvent::RADIO_RIL_SETUP_DATA_CALL: {
244             retVal = RilActivatePdpContextDone(event);
245             break;
246         }
247         case CellularDataEventCode::MSG_SM_GET_LAST_FAIL_DONE:
248             stateMachine->TransitionTo(stateMachine->inActiveState_);
249             retVal = PROCESSED;
250             break;
251         case CellularDataEventCode::MSG_GET_RIL_BANDWIDTH:
252             stateMachine->DeferEvent(std::move(event));
253             break;
254         case CellularDataEventCode::MSG_CONNECT_TIMEOUT_CHECK:
255             ProcessConnectTimeout(event);
256             retVal = PROCESSED;
257             break;
258         default:
259             TELEPHONY_LOGE("eventCode:%{public}d goto default", eventCode);
260             break;
261     }
262     return retVal;
263 }
264 } // namespace Telephony
265 } // namespace OHOS