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