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#include "sim_ability.h"
17
18#include "ability_context.h"
19#include "ability_loader.h"
20#include "abs_rdb_predicates.h"
21#include "abs_shared_result_set.h"
22#include "data_storage_errors.h"
23#include "data_storage_log_wrapper.h"
24#include "datashare_ext_ability.h"
25#include "datashare_predicates.h"
26#include "new"
27#include "permission_util.h"
28#include "rdb_errno.h"
29#include "rdb_utils.h"
30#include "sim_data.h"
31#include "telephony_datashare_stub_impl.h"
32#include "uri.h"
33#include "utility"
34#include "values_bucket.h"
35
36namespace OHOS {
37using AbilityRuntime::Extension;
38using AbilityRuntime::Runtime;
39using AppExecFwk::Ability;
40using AppExecFwk::AbilityLoader;
41namespace Telephony {
42const int32_t CHANGED_ROWS = 0;
43static const std::map<std::string, SimUriType> simUriMap_ = {
44    { "/sim/sim_info", SimUriType::SIM_INFO },
45    { "/sim/sim_info/set_card", SimUriType::SET_CARD },
46};
47
48SimAbility::SimAbility() : DataShareExtAbility() {}
49
50SimAbility::~SimAbility() {}
51
52SimAbility* SimAbility::Create()
53{
54    DATA_STORAGE_LOGD("SimAbility::Create begin.");
55    auto self =  new SimAbility();
56    self->DoInit();
57    return self;
58}
59
60static DataShare::DataShareExtAbility *TelephonyDataShareCreator(const std::unique_ptr<Runtime> &runtime)
61{
62    DATA_STORAGE_LOGD("sim TelephonyDataCreator::%{public}s begin.", __func__);
63    return SimAbility::Create();
64}
65
66__attribute__((constructor)) void RegisterDataShareCreator()
67{
68    DATA_STORAGE_LOGD("TelephonyDataCreator::%{public}s", __func__);
69    DataShare::DataShareExtAbility::SetCreator(TelephonyDataShareCreator);
70}
71
72void SimAbility::DoInit()
73{
74    if (initDatabaseDir && initRdbStore) {
75        DATA_STORAGE_LOGD("DoInit has done");
76        return;
77    }
78    auto abilityContext = AbilityRuntime::Context::GetApplicationContext();
79    if (abilityContext == nullptr) {
80        DATA_STORAGE_LOGE("DoInit GetAbilityContext is null");
81        return;
82    }
83    // switch database dir to el1 for init before unlock
84    abilityContext->SwitchArea(0);
85    std::string path = abilityContext->GetDatabaseDir();
86    if (!path.empty()) {
87        initDatabaseDir = true;
88        path.append("/");
89        helper_.UpdateDbPath(path);
90        if (helper_.Init() == NativeRdb::E_OK) {
91            initRdbStore = true;
92        } else {
93            DATA_STORAGE_LOGE("DoInit rdb init failed!");
94            initRdbStore = false;
95        }
96    } else {
97        DATA_STORAGE_LOGE("DoInit##databaseDir is empty!");
98        initDatabaseDir = false;
99    }
100}
101
102sptr<IRemoteObject> SimAbility::OnConnect(const AAFwk::Want &want)
103{
104    DATA_STORAGE_LOGD("SimAbility %{public}s begin.", __func__);
105    Extension::OnConnect(want);
106    sptr<DataShare::TelephonyDataShareStubImpl> remoteObject =
107        new (std::nothrow) DataShare::TelephonyDataShareStubImpl();
108    if (remoteObject == nullptr) {
109        DATA_STORAGE_LOGE("%{public}s No memory allocated for DataShareStubImpl", __func__);
110        return nullptr;
111    }
112    remoteObject->SetSimAbility(std::static_pointer_cast<SimAbility>(shared_from_this()));
113    DATA_STORAGE_LOGD("SimAbility %{public}s end.", __func__);
114    return remoteObject->AsObject();
115}
116
117void SimAbility::OnStart(const AppExecFwk::Want &want)
118{
119    DATA_STORAGE_LOGD("SimAbility::OnStart");
120    Extension::OnStart(want);
121    DoInit();
122}
123
124int SimAbility::Insert(const Uri &uri, const DataShare::DataShareValuesBucket &value)
125{
126    if (!PermissionUtil::CheckPermission(Permission::SET_TELEPHONY_STATE)) {
127        DATA_STORAGE_LOGE("Permission denied!");
128        return DATA_STORAGE_ERR_PERMISSION_ERR;
129    }
130    if (!IsInitOk()) {
131        return DATA_STORAGE_ERROR;
132    }
133    std::lock_guard<std::mutex> guard(lock_);
134    Uri tempUri = uri;
135    SimUriType simUriType = ParseUriType(tempUri);
136    int64_t id = DATA_STORAGE_ERROR;
137    if (simUriType == SimUriType::SIM_INFO) {
138        OHOS::NativeRdb::ValuesBucket values = RdbDataShareAdapter::RdbUtils::ToValuesBucket(value);
139        helper_.Insert(id, values, TABLE_SIM_INFO);
140    } else {
141        DATA_STORAGE_LOGI("SimAbility::Insert##uri = %{public}s", uri.ToString().c_str());
142    }
143    return id;
144}
145
146std::shared_ptr<DataShare::DataShareResultSet> SimAbility::Query(
147    const Uri &uri, const DataShare::DataSharePredicates &predicates, std::vector<std::string> &columns,
148    DataShare::DatashareBusinessError &businessError)
149{
150    if (!PermissionUtil::CheckPermission(Permission::GET_TELEPHONY_STATE)) {
151        DATA_STORAGE_LOGE("Permission denied!");
152        return nullptr;
153    }
154    std::shared_ptr<DataShare::DataShareResultSet> sharedPtrResult = nullptr;
155    if (!IsInitOk()) {
156        return nullptr;
157    }
158    Uri tempUri = uri;
159    SimUriType simUriType = ParseUriType(tempUri);
160    if (simUriType == SimUriType::SIM_INFO) {
161        NativeRdb::AbsRdbPredicates *absRdbPredicates = new NativeRdb::AbsRdbPredicates(TABLE_SIM_INFO);
162        if (absRdbPredicates != nullptr) {
163            NativeRdb::RdbPredicates rdbPredicates = ConvertPredicates(absRdbPredicates->GetTableName(), predicates);
164            auto resultSet = helper_.Query(rdbPredicates, columns);
165            if (resultSet == nullptr) {
166                DATA_STORAGE_LOGE("SimAbility::Query  NativeRdb::ResultSet is null!");
167                delete absRdbPredicates;
168                absRdbPredicates = nullptr;
169                return nullptr;
170            }
171            auto queryResultSet = RdbDataShareAdapter::RdbUtils::ToResultSetBridge(resultSet);
172            sharedPtrResult = std::make_shared<DataShare::DataShareResultSet>(queryResultSet);
173            delete absRdbPredicates;
174            absRdbPredicates = nullptr;
175        } else {
176            DATA_STORAGE_LOGE("SimAbility::Query  NativeRdb::AbsRdbPredicates is null!");
177        }
178    } else {
179        DATA_STORAGE_LOGI("SimAbility::Query failed##uri = %{public}s", uri.ToString().c_str());
180    }
181    return sharedPtrResult;
182}
183
184int SimAbility::Update(
185    const Uri &uri, const DataShare::DataSharePredicates &predicates,
186    const DataShare::DataShareValuesBucket &value)
187{
188    if (!PermissionUtil::CheckPermission(Permission::SET_TELEPHONY_STATE)) {
189        DATA_STORAGE_LOGE("Permission denied!");
190        return DATA_STORAGE_ERR_PERMISSION_ERR;
191    }
192    int result = DATA_STORAGE_ERROR;
193    if (!IsInitOk()) {
194        return result;
195    }
196    std::lock_guard<std::mutex> guard(lock_);
197    Uri tempUri = uri;
198    SimUriType simUriType = ParseUriType(tempUri);
199    switch (simUriType) {
200        case SimUriType::SIM_INFO: {
201            NativeRdb::AbsRdbPredicates *absRdbPredicates = new NativeRdb::AbsRdbPredicates(TABLE_SIM_INFO);
202            if (absRdbPredicates != nullptr) {
203                int changedRows = CHANGED_ROWS;
204                NativeRdb::RdbPredicates rdbPredicates =
205                    ConvertPredicates(absRdbPredicates->GetTableName(), predicates);
206                OHOS::NativeRdb::ValuesBucket values = RdbDataShareAdapter::RdbUtils::ToValuesBucket(value);
207                result = helper_.Update(changedRows, values, rdbPredicates);
208                delete absRdbPredicates;
209                absRdbPredicates = nullptr;
210            } else {
211                DATA_STORAGE_LOGE("SimAbility::Update  NativeRdb::AbsRdbPredicates is null!");
212            }
213            break;
214        }
215        case SimUriType::SET_CARD: {
216            result = SetCard(value);
217            if (result != NativeRdb::E_OK) {
218                DATA_STORAGE_LOGE("SimAbility::Update  SetCard failed!");
219                result = static_cast<int>(LoadProFileErrorType::SET_CARD_FAIL);
220            }
221            break;
222        }
223        default:
224            DATA_STORAGE_LOGI("SimAbility::Update##uri = %{public}s", uri.ToString().c_str());
225            break;
226    }
227    return result;
228}
229
230int SimAbility::SetCard(const DataShare::DataShareValuesBucket &sharedValue)
231{
232    if (!PermissionUtil::CheckPermission(Permission::SET_TELEPHONY_STATE)) {
233        DATA_STORAGE_LOGE("Permission denied!");
234        return DATA_STORAGE_ERR_PERMISSION_ERR;
235    }
236    OHOS::NativeRdb::ValuesBucket value = RdbDataShareAdapter::RdbUtils::ToValuesBucket(sharedValue);
237    int result = DATA_STORAGE_ERROR;
238    if (!value.HasColumn(SimData::SIM_ID)) {
239        DATA_STORAGE_LOGE("SimAbility::Update##the sim_id in valuesBucket does not exist!");
240        return result;
241    }
242    if (!value.HasColumn(SimData::CARD_TYPE)) {
243        DATA_STORAGE_LOGE("SimAbility::Update##the card_type in valuesBucket does not exist!");
244        return result;
245    }
246    NativeRdb::ValueObject valueObject;
247    bool isExistSimId = value.GetObject(SimData::SIM_ID, valueObject);
248    if (!isExistSimId) {
249        DATA_STORAGE_LOGE("SimAbility::Update##failed to get sim_id value in valuesBucket!");
250        return result;
251    }
252    int simId = 0;
253    valueObject.GetInt(simId);
254
255    bool isExistCardType = value.GetObject(SimData::CARD_TYPE, valueObject);
256    if (!isExistCardType) {
257        DATA_STORAGE_LOGE("SimAbility::Update##failed to get card_type value in valuesBucket!");
258        return result;
259    }
260    int cardType = 0;
261    valueObject.GetInt(cardType);
262    result = helper_.SetDefaultCardByType(simId, cardType);
263    return result;
264}
265
266int SimAbility::Delete(const Uri &uri, const DataShare::DataSharePredicates &predicates)
267{
268    if (!PermissionUtil::CheckPermission(Permission::SET_TELEPHONY_STATE)) {
269        DATA_STORAGE_LOGE("Permission denied!");
270        return DATA_STORAGE_ERR_PERMISSION_ERR;
271    }
272    int result = DATA_STORAGE_ERROR;
273    if (!IsInitOk()) {
274        return result;
275    }
276    std::lock_guard<std::mutex> guard(lock_);
277    Uri tempUri = uri;
278    SimUriType simUriType = ParseUriType(tempUri);
279    if (simUriType == SimUriType::SIM_INFO) {
280        NativeRdb::AbsRdbPredicates *absRdbPredicates = new NativeRdb::AbsRdbPredicates(TABLE_SIM_INFO);
281        if (absRdbPredicates != nullptr) {
282            NativeRdb::RdbPredicates rdbPredicates = ConvertPredicates(absRdbPredicates->GetTableName(), predicates);
283            int deletedRows = 0;
284            result = helper_.Delete(deletedRows, rdbPredicates);
285            delete absRdbPredicates;
286            absRdbPredicates = nullptr;
287        } else {
288            DATA_STORAGE_LOGE("SimAbility::Update  NativeRdb::AbsRdbPredicates is null!");
289        }
290    } else {
291        DATA_STORAGE_LOGI("SimAbility::Delete failed##uri = %{public}s", uri.ToString().c_str());
292    }
293    return result;
294}
295
296bool SimAbility::IsInitOk()
297{
298    if (!initDatabaseDir) {
299        DATA_STORAGE_LOGE("SimAbility::IsInitOk initDatabaseDir failed!");
300    } else if (!initRdbStore) {
301        DATA_STORAGE_LOGE("SimAbility::IsInitOk initRdbStore failed!");
302    }
303    return initDatabaseDir && initRdbStore;
304}
305
306std::string SimAbility::GetType(const Uri &uri)
307{
308    DATA_STORAGE_LOGI("SimAbility::GetType##uri = %{public}s", uri.ToString().c_str());
309    std::string retval(uri.ToString());
310    return retval;
311}
312
313int SimAbility::OpenFile(const Uri &uri, const std::string &mode)
314{
315    DATA_STORAGE_LOGI("SimAbility::OpenFile##uri = %{public}s", uri.ToString().c_str());
316    Uri tempUri = uri;
317    SimUriType simUriType = ParseUriType(tempUri);
318    return static_cast<int>(simUriType);
319}
320
321SimUriType SimAbility::ParseUriType(Uri &uri)
322{
323    DATA_STORAGE_LOGD("SimAbility::ParseUriType start");
324    SimUriType simUriType = SimUriType::UNKNOW;
325    std::string uriPath = uri.ToString();
326    if (!uriPath.empty()) {
327        helper_.ReplaceAllStr(uriPath, ":///", "://");
328        Uri tempUri(uriPath);
329        std::string path = tempUri.GetPath();
330        if (!path.empty() && !simUriMap_.empty()) {
331            auto it = simUriMap_.find(path);
332            if (it != simUriMap_.end()) {
333                simUriType = it->second;
334                DATA_STORAGE_LOGD("SimAbility::ParseUriType##simUriType = %{public}d", simUriType);
335            }
336        }
337    }
338    return simUriType;
339}
340
341OHOS::NativeRdb::RdbPredicates SimAbility::ConvertPredicates(
342    const std::string &tableName, const DataShare::DataSharePredicates &predicates)
343{
344    OHOS::NativeRdb::RdbPredicates res = RdbDataShareAdapter::RdbUtils::ToPredicates(predicates, tableName);
345    return res;
346}
347} // namespace Telephony
348} // namespace OHOS
349