1 /*
2 * Copyright (c) 2025 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 "apn_utils.h"
17
18 #include <algorithm>
19 #include "parameters.h"
20 #include "edm_errors.h"
21 #include "edm_log.h"
22 #include "pdp_profile_data.h"
23 #include "core_service_client.h"
24 #include "edm_sys_manager.h"
25 #include "system_ability_definition.h"
26
27 namespace OHOS {
28 namespace EDM {
29 using namespace Telephony;
30 namespace {
31 constexpr const char *PDP_PROFILE_BASE_URI = "datashare:///com.ohos.pdpprofileability";
32 constexpr const char *PDP_PROFILE_URI = "datashare:///com.ohos.pdpprofileability/net/pdp_profile";
33 constexpr const char *PDP_PROFILE_PREFER_URI = "datashare:///com.ohos.pdpprofileability/net/pdp_profile/preferapn";
34 constexpr const char *OPKEY_BASE_URI = "datashare:///com.ohos.opkeyability";
35 constexpr const char *OPKEY_URI = "datashare:///com.ohos.opkeyability/opkey/opkey_info";
36 constexpr int32_t SIM_SLOT_ZERO = 0;
37 constexpr int32_t SIM_SLOT_ONE = 1;
38 }
39
CreatePdpProfileAbilityHelper()40 std::shared_ptr<DataShare::DataShareHelper> ApnUtils::CreatePdpProfileAbilityHelper()
41 {
42 EDMLOGI("Create pdp profile ability helper");
43 sptr<IRemoteObject> remoteObject = EdmSysManager::GetRemoteObjectOfSystemAbility(ENTERPRISE_DEVICE_MANAGER_SA_ID);
44 return DataShare::DataShareHelper::Creator(remoteObject, PDP_PROFILE_BASE_URI);
45 }
46
CreateOpkeyAbilityHelper()47 std::shared_ptr<DataShare::DataShareHelper> ApnUtils::CreateOpkeyAbilityHelper()
48 {
49 EDMLOGI("Create opkey ability helper");
50 sptr<IRemoteObject> remoteObject = EdmSysManager::GetRemoteObjectOfSystemAbility(ENTERPRISE_DEVICE_MANAGER_SA_ID);
51 return DataShare::DataShareHelper::Creator(remoteObject, OPKEY_BASE_URI);
52 }
53
GetOpkey(const std::string & mccmnc,std::string & opkey)54 int32_t ApnUtils::GetOpkey(const std::string &mccmnc, std::string &opkey)
55 {
56 EDMLOGI("ApnUtils::GetOpkey start");
57 auto helper = CreateOpkeyAbilityHelper();
58 if (helper == nullptr) {
59 EDMLOGE("GetOpkey helper get failed");
60 return -1;
61 }
62 DataShare::DataSharePredicates predicates;
63 predicates.EqualTo(PdpProfileData::MCCMNC, mccmnc);
64 Uri uri((OPKEY_URI));
65 std::vector<std::string> columns;
66 std::shared_ptr<DataShare::DataShareResultSet> queryResult = helper->Query(uri, predicates, columns);
67 if (queryResult == nullptr) {
68 EDMLOGE("GetOpkey error");
69 return -1;
70 }
71
72 if (queryResult->GoToRow(0) != DataShare::E_OK) {
73 EDMLOGE("GetOpkey GoToRow error");
74 queryResult->Close();
75 return -1;
76 }
77
78 int32_t columnIndex = -1;
79 if (queryResult->GetColumnIndex("operator_key", columnIndex) != DataShare::E_OK ||
80 queryResult->GetString(columnIndex, opkey) != DataShare::E_OK) {
81 return -1;
82 }
83 EDMLOGI("ApnUtils::GetOpkey opkey=%{public}s", opkey.c_str());
84 return 0;
85 }
86
ApnInsert(const std::map<std::string,std::string> & apnInfo,const ApnUtilsPassword & apnUtilsPassword)87 int32_t ApnUtils::ApnInsert(const std::map<std::string, std::string> &apnInfo,
88 const ApnUtilsPassword &apnUtilsPassword)
89 {
90 EDMLOGI("ApnUtils::ApnInsert start");
91 auto helper = CreatePdpProfileAbilityHelper();
92 if (helper == nullptr) {
93 EDMLOGE("ApnInsert helper get failed");
94 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
95 }
96 DataShare::DataShareValuesBucket values;
97 for (const auto & [key, value] : apnInfo) {
98 values.Put(key, value);
99 }
100 if (apnUtilsPassword.password != nullptr) {
101 values.Put("auth_pwd", std::string(apnUtilsPassword.password, apnUtilsPassword.passwordSize));
102 }
103 std::string mccmnc = apnInfo.at(PdpProfileData::MCC) + apnInfo.at(PdpProfileData::MNC);
104 values.Put(PdpProfileData::MCCMNC, mccmnc);
105 std::string opkey;
106 if (GetOpkey(mccmnc, opkey) == ERR_OK && !opkey.empty()) {
107 values.Put(PdpProfileData::OPKEY, opkey);
108 } else {
109 values.Put(PdpProfileData::OPKEY, mccmnc);
110 }
111 Uri uri((PDP_PROFILE_URI));
112 return helper->Insert(uri, values) >= DataShare::E_OK ? ERR_OK : EdmReturnErrCode::SYSTEM_ABNORMALLY;
113 }
114
ApnDelete(const std::string & apnId)115 int32_t ApnUtils::ApnDelete(const std::string &apnId)
116 {
117 EDMLOGI("ApnUtils::ApnDelete start");
118 auto helper = CreatePdpProfileAbilityHelper();
119 if (helper == nullptr) {
120 EDMLOGE("ApnDelete helper get failed");
121 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
122 }
123 DataShare::DataSharePredicates predicates;
124 predicates.EqualTo(PdpProfileData::PROFILE_ID, apnId);
125 Uri uri((PDP_PROFILE_URI));
126 return helper->Delete(uri, predicates) == DataShare::E_OK ? ERR_OK : EdmReturnErrCode::SYSTEM_ABNORMALLY;
127 }
128
ApnUpdate(const std::map<std::string,std::string> & apnInfo,const std::string & apnId,const ApnUtilsPassword & apnUtilsPassword)129 int32_t ApnUtils::ApnUpdate(const std::map<std::string, std::string> &apnInfo, const std::string &apnId,
130 const ApnUtilsPassword &apnUtilsPassword)
131 {
132 EDMLOGI("ApnUtils::ApnUpdate start");
133 auto helper = CreatePdpProfileAbilityHelper();
134 if (helper == nullptr) {
135 EDMLOGE("ApnUpdate helper get failed");
136 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
137 }
138
139 DataShare::DataShareValuesBucket values;
140 for (const auto & [key, value] : apnInfo) {
141 values.Put(key, value);
142 }
143 if (apnUtilsPassword.password != nullptr) {
144 values.Put("auth_pwd", std::string(apnUtilsPassword.password, apnUtilsPassword.passwordSize));
145 }
146
147 std::string mccmnc;
148 if (apnInfo.find(PdpProfileData::MCC) != apnInfo.end() && apnInfo.find(PdpProfileData::MNC) != apnInfo.end()) {
149 mccmnc = apnInfo.at(PdpProfileData::MCC) + apnInfo.at(PdpProfileData::MNC);
150 } else if (apnInfo.find(PdpProfileData::MCC) != apnInfo.end()) {
151 mccmnc = apnInfo.at(PdpProfileData::MCC) + ApnQuery(apnId)[PdpProfileData::MNC];
152 } else if (apnInfo.find(PdpProfileData::MNC) != apnInfo.end()) {
153 mccmnc = ApnQuery(apnId)[PdpProfileData::MCC] + apnInfo.at(PdpProfileData::MNC);
154 }
155
156 if (apnInfo.find(PdpProfileData::MCC) != apnInfo.end() || apnInfo.find(PdpProfileData::MNC) != apnInfo.end()) {
157 values.Put(PdpProfileData::MCCMNC, mccmnc);
158 std::string opkey;
159 if (GetOpkey(mccmnc, opkey) == ERR_OK && !opkey.empty()) {
160 values.Put(PdpProfileData::OPKEY, opkey);
161 } else {
162 values.Put(PdpProfileData::OPKEY, mccmnc);
163 }
164 }
165 DataShare::DataSharePredicates predicates;
166 predicates.EqualTo(PdpProfileData::PROFILE_ID, apnId);
167 Uri uri((PDP_PROFILE_URI));
168 return helper->Update(uri, predicates, values) == DataShare::E_OK ? ERR_OK : EdmReturnErrCode::SYSTEM_ABNORMALLY;
169 }
170
ApnQuery(const std::map<std::string,std::string> & apnInfo)171 std::vector<std::string> ApnUtils::ApnQuery(const std::map<std::string, std::string> &apnInfo)
172 {
173 EDMLOGI("ApnUtils::ApnQueryId start");
174 auto helper = CreatePdpProfileAbilityHelper();
175 std::vector<std::string> result;
176 ApnQueryVector(helper, apnInfo, result);
177 return result;
178 }
179
ApnQueryVector(std::shared_ptr<DataShare::DataShareHelper> helper,const std::map<std::string,std::string> & apnInfo,std::vector<std::string> & result)180 void ApnUtils::ApnQueryVector(std::shared_ptr<DataShare::DataShareHelper> helper,
181 const std::map<std::string, std::string> &apnInfo, std::vector<std::string> &result)
182 {
183 if (helper == nullptr) {
184 EDMLOGE("ApnQueryVector helper get failed");
185 return;
186 }
187 std::vector<std::string> columns;
188 DataShare::DataSharePredicates predicates;
189 for (const auto & [key, value] : apnInfo) {
190 predicates.EqualTo(key, value);
191 }
192 Uri uri((PDP_PROFILE_URI));
193 std::shared_ptr<DataShare::DataShareResultSet> queryResult = helper->Query(uri, predicates, columns);
194 if (queryResult == nullptr) {
195 EDMLOGE("QueryApnId error");
196 return;
197 }
198 int32_t rowCnt = 0;
199 queryResult->GetRowCount(rowCnt);
200 for (int32_t rowIdx = 0; rowIdx < rowCnt; ++rowIdx) {
201 if (queryResult->GoToRow(rowIdx)) {
202 EDMLOGE("ApnQueryVector GoToRow error");
203 queryResult->Close();
204 return;
205 }
206 int32_t apnIdIdx = -1;
207 queryResult->GetColumnIndex(PdpProfileData::PROFILE_ID, apnIdIdx);
208 int32_t apnId = -1;
209 queryResult->GetInt(apnIdIdx, apnId);
210 bool needInsert = !std::any_of(result.begin(), result.end(), [apnId](const auto &ele) {
211 return ele == std::to_string(apnId);
212 });
213 if (needInsert) {
214 result.push_back(std::to_string(apnId));
215 }
216 }
217 queryResult->Close();
218 }
219
ApnQuery(const std::string & apnId)220 std::map<std::string, std::string> ApnUtils::ApnQuery(const std::string &apnId)
221 {
222 EDMLOGI("ApnUtils::ApnQueryInfo start");
223 auto helper = CreatePdpProfileAbilityHelper();
224
225 std::map<std::string, std::string> results;
226 int32_t queryResult = ApnQueryResultSet(helper, apnId, results);
227 if (queryResult < 0) {
228 EDMLOGE("QueryApnInfo error");
229 return {};
230 }
231
232 return results;
233 }
234
ApnQueryResultSet(std::shared_ptr<DataShare::DataShareHelper> helper,const std::string & apnId,std::map<std::string,std::string> & results)235 int32_t ApnUtils::ApnQueryResultSet(std::shared_ptr<DataShare::DataShareHelper> helper, const std::string &apnId,
236 std::map<std::string, std::string> &results)
237 {
238 if (helper == nullptr) {
239 EDMLOGE("ApnQueryResultSet helper get failed");
240 return -1;
241 }
242 std::vector<std::string> columns;
243 DataShare::DataSharePredicates predicates;
244 predicates.EqualTo(PdpProfileData::PROFILE_ID, apnId);
245 Uri uri((PDP_PROFILE_URI));
246 std::shared_ptr<DataShare::DataShareResultSet> queryResult = helper->Query(uri, predicates, columns);
247 if (queryResult == nullptr) {
248 EDMLOGE("QueryApnResultSet error");
249 return -1;
250 }
251
252 int32_t rowCnt = 0;
253 queryResult->GetRowCount(rowCnt);
254 EDMLOGI("ApnQuery rowCnt: %{public}d", rowCnt);
255 if (rowCnt <= 0) {
256 queryResult->Close();
257 return ERR_OK;
258 }
259
260 if (queryResult->GoToRow(0) != DataShare::E_OK) {
261 EDMLOGE("ApnQuery GoToRow error");
262 queryResult->Close();
263 return -1;
264 }
265 int32_t columnCnt = -1;
266 queryResult->GetColumnCount(columnCnt);
267 for (int32_t idx = 0; idx < columnCnt; ++idx) {
268 std::string columnName;
269 queryResult->GetColumnName(idx, columnName);
270 DataShare::DataType dataType;
271 queryResult->GetDataType(idx, dataType);
272 if (dataType == DataShare::DataType::TYPE_INTEGER) {
273 int32_t value;
274 queryResult->GetInt(idx, value);
275 results[columnName] = std::to_string(value);
276 } else if (dataType == DataShare::DataType::TYPE_STRING) {
277 queryResult->GetString(idx, results[columnName]);
278 }
279 }
280 queryResult->Close();
281 return ERR_OK;
282 }
283
MatchValidSimId(const std::string & opkey,int32_t slotId)284 int32_t ApnUtils::MatchValidSimId(const std::string &opkey, int32_t slotId)
285 {
286 std::string sysOpkey = system::GetParameter(std::string("telephony.sim.opkey") + std::to_string(slotId), "");
287 if (opkey != sysOpkey) {
288 return -1;
289 }
290 if (!Telephony::CoreServiceClient::GetInstance().IsSimActive(slotId)) {
291 return -1;
292 }
293 int32_t simId = Telephony::CoreServiceClient::GetInstance().GetSimId(slotId);
294 if (simId <= 0) {
295 return -1;
296 }
297 return simId;
298 }
299
GetValidSimId(const std::string & apnId)300 int32_t ApnUtils::GetValidSimId(const std::string &apnId)
301 {
302 std::string opkey;
303 if (GetOpkey(ApnQuery(apnId)[PdpProfileData::MCCMNC], opkey) != ERR_OK || opkey.empty()) {
304 return -1;
305 }
306
307 int32_t slotId = Telephony::CellularDataClient::GetInstance().GetDefaultCellularDataSlotId();
308 int32_t simId = MatchValidSimId(opkey, slotId);
309 if (simId > 0) {
310 return simId;
311 }
312
313 simId = MatchValidSimId(opkey, slotId == SIM_SLOT_ONE ? SIM_SLOT_ZERO : SIM_SLOT_ONE);
314 if (simId > 0) {
315 return simId;
316 }
317 return -1;
318 }
319
ApnSetPrefer(const std::string & apnId)320 int32_t ApnUtils::ApnSetPrefer(const std::string &apnId)
321 {
322 EDMLOGI("ApnUtils::ApnSetPrefer start");
323
324 auto helper = CreatePdpProfileAbilityHelper();
325 if (helper == nullptr) {
326 EDMLOGE("ApnSetPrefer helper get failed");
327 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
328 }
329
330 int32_t simId = GetValidSimId(apnId);
331 if (simId < 0) {
332 EDMLOGE("ApnUtils::ApnSetPrefer get failed");
333 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
334 }
335
336 char* pResult = nullptr;
337 const int32_t apnIdInt = static_cast<int32_t>(std::strtol(apnId.c_str(), &pResult, 10));
338 if (apnId.c_str() == pResult) {
339 EDMLOGE("ApnUtils::ApnSetPrefer failed to convert type");
340 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
341 }
342 DataShare::DataSharePredicates predicates;
343 DataShare::DataShareValuesBucket values;
344 double profileIdAsDouble = static_cast<double>(apnIdInt);
345 double simIdAsDouble = static_cast<double>(simId);
346 values.Put(PdpProfileData::PROFILE_ID, profileIdAsDouble);
347 values.Put(PdpProfileData::SIM_ID, simIdAsDouble);
348 Uri preferApnUri(PDP_PROFILE_PREFER_URI);
349 int32_t result = helper->Update(preferApnUri, predicates, values);
350 if (result < DataShare::E_OK) {
351 EDMLOGE("SetPreferApn fail! result:%{public}d", result);
352 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
353 }
354 EDMLOGI("SetPreferApn result:%{public}d", result);
355 return ERR_OK;
356 }
357 } // namespace EDM
358 } // namespace OHOS