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 "call_data_base_helper.h"
17 
18 #include "ability_context.h"
19 #include "call_manager_errors.h"
20 #include "call_number_utils.h"
21 #include "iservice_registry.h"
22 #include "phonenumbers/phonenumber.pb.h"
23 #include "phonenumberutil.h"
24 #include "telephony_log_wrapper.h"
25 #include "os_account_manager.h"
26 #include "system_ability_definition.h"
27 
28 namespace OHOS {
29 namespace Telephony {
30 class AbsSharedResultSet;
31 static constexpr const char *CALLLOG_URI = "datashare:///com.ohos.calllogability";
32 static constexpr const char *CALL_SUBSECTION = "datashare:///com.ohos.calllogability/calls/calllog";
33 static const std::string CALL_SUBSECTION_SILENCE =
34     "datashareproxy://com.ohos.contactsdataability/calls/calllog?Proxy=true&user=";
35 static constexpr const char *CONTACT_URI = "datashare:///com.ohos.contactsdataability";
36 static constexpr const char *CALL_BLOCK = "datashare:///com.ohos.contactsdataability/contacts/contact_blocklist";
37 static constexpr const char *CONTACT_DATA = "datashare:///com.ohos.contactsdataability/contacts/contact_data";
38 static constexpr const char *ISO_COUNTRY_CODE = "CN";
39 static constexpr const char *SETTINGS_DATA_URI =
40     "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA?Proxy=true";
41 static constexpr const char *SETTINGS_DATA_EXT_URI = "datashare:///com.ohos.settingsdata.DataAbility";
42 static constexpr const char *SETTINGS_AIRPLANE_MODE_URI =
43     "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA?Proxy=true&key=airplane_mode";
44 static constexpr const char *SETTINGS_AIRPLANE_MODE = "settings.telephony.airplanemode";
45 static constexpr const int32_t MAX_WAITIME_TIME = 10;
46 constexpr int32_t E_OK = 0;
47 
CallDataRdbObserver(std::vector<std::string> * phones)48 CallDataRdbObserver::CallDataRdbObserver(std::vector<std::string> *phones)
49 {
50     this->phones = phones;
51 }
52 
~CallDataRdbObserver()53 CallDataRdbObserver::~CallDataRdbObserver() {}
54 
OnChange()55 void CallDataRdbObserver::OnChange()
56 {
57     std::shared_ptr<CallDataBaseHelper> callDataPtr = DelayedSingleton<CallDataBaseHelper>::GetInstance();
58     if (callDataPtr == nullptr) {
59         TELEPHONY_LOGE("callDataPtr is nullptr!");
60         return;
61     }
62 
63     DataShare::DataSharePredicates predicates;
64     predicates.NotEqualTo("phone_number", std::string(""));
65     this->phones->clear();
66     callDataPtr->Query(this->phones, predicates);
67 }
68 
CallDataBaseHelper()69 CallDataBaseHelper::CallDataBaseHelper() {}
70 
~CallDataBaseHelper()71 CallDataBaseHelper::~CallDataBaseHelper() {}
72 
CreateDataShareHelper(std::string uri)73 std::shared_ptr<DataShare::DataShareHelper> CallDataBaseHelper::CreateDataShareHelper(std::string uri)
74 {
75     auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
76     if (saManager == nullptr) {
77         TELEPHONY_LOGE("Get system ability mgr failed.");
78         return nullptr;
79     }
80     auto remoteObj = saManager->GetSystemAbility(TELEPHONY_CALL_MANAGER_SYS_ABILITY_ID);
81     if (remoteObj == nullptr) {
82         TELEPHONY_LOGE("GetSystemAbility Service Failed.");
83         return nullptr;
84     }
85     if (uri == SETTINGS_DATA_URI) {
86         return DataShare::DataShareHelper::Creator(remoteObj, uri, SETTINGS_DATA_EXT_URI);
87     }
88     return DataShare::DataShareHelper::Creator(remoteObj, uri, "", MAX_WAITIME_TIME);
89 }
90 
RegisterObserver(std::vector<std::string> * phones)91 void CallDataBaseHelper::RegisterObserver(std::vector<std::string> *phones)
92 {
93     callDataRdbObserverPtr_ = new (std::nothrow) CallDataRdbObserver(phones);
94     if (callDataRdbObserverPtr_ == nullptr) {
95         TELEPHONY_LOGE("callDataRdbObserverPtr_ is null");
96         return;
97     }
98     std::shared_ptr<DataShare::DataShareHelper> helper = CreateDataShareHelper(CONTACT_URI);
99     if (helper == nullptr) {
100         TELEPHONY_LOGE("helper is null");
101         return;
102     }
103     Uri uri(CALL_BLOCK);
104     helper->RegisterObserver(uri, callDataRdbObserverPtr_);
105     helper->Release();
106 }
107 
UnRegisterObserver()108 void CallDataBaseHelper::UnRegisterObserver()
109 {
110     if (callDataRdbObserverPtr_ == nullptr) {
111         TELEPHONY_LOGE("callDataRdbObserverPtr_ is null");
112         return;
113     }
114     std::shared_ptr<DataShare::DataShareHelper> helper = CreateDataShareHelper(CONTACT_URI);
115     if (helper == nullptr) {
116         TELEPHONY_LOGE("helper_ is null");
117         return;
118     }
119     Uri uri(CALL_BLOCK);
120     helper->UnregisterObserver(uri, callDataRdbObserverPtr_);
121     helper->Release();
122 }
123 
Insert(DataShare::DataShareValuesBucket & values)124 bool CallDataBaseHelper::Insert(DataShare::DataShareValuesBucket &values)
125 {
126     std::shared_ptr<DataShare::DataShareHelper> helper = nullptr;
127     std::string url;
128     bool result = GetHelperAndUrl(helper, url);
129     if (!result) {
130         TELEPHONY_LOGE("GetHelperAndUrl fail!");
131         return false;
132     }
133 
134     Uri uri(url);
135     result = (helper->Insert(uri, values) > 0);
136     helper->Release();
137     return result;
138 }
139 
Query(std::vector<std::string> * phones,DataShare::DataSharePredicates & predicates)140 bool CallDataBaseHelper::Query(std::vector<std::string> *phones, DataShare::DataSharePredicates &predicates)
141 {
142     std::shared_ptr<DataShare::DataShareHelper> helper = CreateDataShareHelper(CONTACT_URI);
143     if (helper == nullptr) {
144         TELEPHONY_LOGE("helper is nullptr");
145         return false;
146     }
147     Uri uri(CALL_BLOCK);
148     std::vector<std::string> columns;
149     columns.push_back("phone_number");
150     auto resultSet = helper->Query(uri, predicates, columns);
151     if (resultSet == nullptr) {
152         helper->Release();
153         return false;
154     }
155     int32_t resultSetNum = resultSet->GoToFirstRow();
156     while (resultSetNum == 0) {
157         std::string phone;
158         int32_t columnIndex;
159         resultSet->GetColumnIndex("phone_number", columnIndex);
160         int32_t ret = resultSet->GetString(columnIndex, phone);
161         if (ret == 0 && (!phone.empty())) {
162             phones->push_back(phone);
163         }
164         resultSetNum = resultSet->GoToNextRow();
165     }
166     resultSet->Close();
167     helper->Release();
168     TELEPHONY_LOGI("Query end");
169     return true;
170 }
171 
Query(ContactInfo & contactInfo,DataShare::DataSharePredicates & predicates)172 bool CallDataBaseHelper::Query(ContactInfo &contactInfo, DataShare::DataSharePredicates &predicates)
173 {
174     std::shared_ptr<DataShare::DataShareHelper> helper = CreateDataShareHelper(CONTACT_URI);
175     if (helper == nullptr) {
176         TELEPHONY_LOGE("helper is nullptr");
177         return false;
178     }
179     Uri uri(CONTACT_DATA);
180     std::vector<std::string> columns;
181     auto resultSet = helper->Query(uri, predicates, columns);
182     if (resultSet == nullptr) {
183         TELEPHONY_LOGE("resultSet is nullptr");
184         helper->Release();
185         return false;
186     }
187     int32_t resultSetNum = resultSet->GoToFirstRow();
188     while (resultSetNum == 0) {
189         int32_t columnIndex;
190         resultSet->GetColumnIndex(CALL_DISPLAY_NAME, columnIndex);
191         int32_t ret = resultSet->GetString(columnIndex, contactInfo.name);
192         resultSetNum = resultSet->GoToNextRow();
193     }
194     resultSet->Close();
195     helper->Release();
196     TELEPHONY_LOGI("Query end");
197     return true;
198 }
199 
GetHelperAndUrl(std::shared_ptr<DataShare::DataShareHelper> & helper,std::string & url)200 bool CallDataBaseHelper::GetHelperAndUrl(std::shared_ptr<DataShare::DataShareHelper> &helper, std::string &url)
201 {
202     int32_t userId = 0;
203     bool isUserUnlocked = false;
204     AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(userId);
205     AccountSA::OsAccountManager::IsOsAccountVerified(userId, isUserUnlocked);
206     TELEPHONY_LOGI("isUserUnlocked: %{public}d", isUserUnlocked);
207     if (!isUserUnlocked) {
208         helper = CreateDataShareHelper(CALL_SUBSECTION_SILENCE + std::to_string(userId));
209         url = CALL_SUBSECTION_SILENCE + std::to_string(userId);
210     } else {
211         helper = CreateDataShareHelper(CALLLOG_URI);
212         url = CALL_SUBSECTION;
213     }
214     if (helper == nullptr) {
215         TELEPHONY_LOGE("helper is nullptr!");
216         return false;
217     }
218     return true;
219 }
220 
QueryCallLog(std::map<std::string,int32_t> & phoneNumAndUnreadCountMap,DataShare::DataSharePredicates & predicates)221 bool CallDataBaseHelper::QueryCallLog(
222     std::map<std::string, int32_t> &phoneNumAndUnreadCountMap, DataShare::DataSharePredicates &predicates)
223 {
224     std::shared_ptr<DataShare::DataShareHelper> helper = nullptr;
225     std::string url;
226     bool result = GetHelperAndUrl(helper, url);
227     if (!result) {
228         TELEPHONY_LOGE("GetHelperAndUrl fail!");
229         return false;
230     }
231 
232     Uri uri(url);
233     std::vector<std::string> columns;
234     columns.push_back(CALL_PHONE_NUMBER);
235     auto resultSet = helper->Query(uri, predicates, columns);
236     if (resultSet == nullptr) {
237         TELEPHONY_LOGE("resultSet is nullptr!");
238         helper->Release();
239         return false;
240     }
241     int32_t operationResult = resultSet->GoToFirstRow();
242     while (operationResult == TELEPHONY_SUCCESS) {
243         std::string phoneNumber = "";
244         int32_t columnIndex = 0;
245         resultSet->GetColumnIndex(CALL_PHONE_NUMBER, columnIndex);
246         operationResult = resultSet->GetString(columnIndex, phoneNumber);
247         if (operationResult == TELEPHONY_SUCCESS && (!phoneNumber.empty())) {
248             auto iter = phoneNumAndUnreadCountMap.find(phoneNumber);
249             if (iter != phoneNumAndUnreadCountMap.end()) {
250                 iter->second++;
251             } else {
252                 phoneNumAndUnreadCountMap.insert(
253                     std::map<std::string, int32_t>::value_type(phoneNumber, CALL_LOG_DEFAULT_COUNT));
254             }
255         }
256         operationResult = resultSet->GoToNextRow();
257     }
258     resultSet->Close();
259     helper->Release();
260     TELEPHONY_LOGI("QueryCallLog end");
261     return true;
262 }
263 
QueryAndDeleteLimitedIds(DataShare::DataSharePredicates & predicates)264 bool CallDataBaseHelper::QueryAndDeleteLimitedIds(DataShare::DataSharePredicates &predicates)
265 {
266     std::shared_ptr<DataShare::DataShareHelper> helper = nullptr;
267     std::string url;
268     bool result = GetHelperAndUrl(helper, url);
269     if (!result) {
270         TELEPHONY_LOGE("GetHelperAndUrl fail!");
271         return false;
272     }
273 
274     Uri uri(url);
275     std::vector<std::string> columns;
276     columns.push_back(CALL_ID);
277     auto resultSet = helper->Query(uri, predicates, columns);
278     if (resultSet == nullptr) {
279         TELEPHONY_LOGE("resultSet is nullptr!");
280         helper->Release();
281         return false;
282     }
283     int32_t operationResult = resultSet->GoToFirstRow();
284     while (operationResult == TELEPHONY_SUCCESS) {
285         int32_t id = 0;
286         int32_t columnIndex = 0;
287         resultSet->GetColumnIndex(CALL_ID, columnIndex);
288         operationResult = resultSet->GetInt(columnIndex, id);
289         if (operationResult == TELEPHONY_SUCCESS) {
290             TELEPHONY_LOGI("need delete call log id: %{public}d", id);
291             DataShare::DataSharePredicates deletePredicates;
292             deletePredicates.EqualTo(CALL_ID, id);
293             result = (helper->Delete(uri, deletePredicates) > 0);
294             TELEPHONY_LOGI("delete result: %{public}d", result);
295         }
296         operationResult = resultSet->GoToNextRow();
297     }
298     resultSet->Close();
299     helper->Release();
300     TELEPHONY_LOGI("QueryAndDeleteLimitedIds end");
301     return true;
302 }
303 
Update(DataShare::DataSharePredicates & predicates,DataShare::DataShareValuesBucket & values)304 bool CallDataBaseHelper::Update(DataShare::DataSharePredicates &predicates, DataShare::DataShareValuesBucket &values)
305 {
306     std::shared_ptr<DataShare::DataShareHelper> helper = CreateDataShareHelper(CALLLOG_URI);
307     if (helper == nullptr) {
308         TELEPHONY_LOGE("helper is nullptr");
309         return true;
310     }
311     Uri uri(CALL_SUBSECTION);
312     bool result = (helper->Update(uri, predicates, values) > 0);
313     helper->Release();
314     return result;
315 }
316 
Delete(DataShare::DataSharePredicates & predicates)317 bool CallDataBaseHelper::Delete(DataShare::DataSharePredicates &predicates)
318 {
319     std::shared_ptr<DataShare::DataShareHelper> helper = CreateDataShareHelper(CALLLOG_URI);
320     if (helper == nullptr) {
321         TELEPHONY_LOGE("helper is nullptr!");
322         return false;
323     }
324     Uri uri(CALL_SUBSECTION);
325     bool result = (helper->Delete(uri, predicates) > 0);
326     TELEPHONY_LOGI("delete result: %{public}d", result);
327     helper->Release();
328     return result;
329 }
330 
QueryIsBlockPhoneNumber(const std::string & phoneNum,bool & result)331 int32_t CallDataBaseHelper::QueryIsBlockPhoneNumber(const std::string &phoneNum, bool &result)
332 {
333     result = false;
334     std::shared_ptr<DataShare::DataShareHelper> callDataHelper = CreateDataShareHelper(CALLLOG_URI);
335     if (callDataHelper == nullptr) {
336         TELEPHONY_LOGE("callDataHelper is nullptr!");
337         return TELEPHONY_ERR_LOCAL_PTR_NULL;
338     }
339     Uri uri(CALL_BLOCK);
340     DataShare::DataSharePredicates predicates;
341     std::vector<std::string> columns;
342     std::string internationalNumber;
343     std::string nationalNumber;
344     int32_t ret = DelayedSingleton<CallNumberUtils>::GetInstance()->FormatPhoneNumberToNational(
345         phoneNum, ISO_COUNTRY_CODE, nationalNumber);
346     if (ret != TELEPHONY_SUCCESS) {
347         TELEPHONY_LOGE("Format phone number failed.");
348         nationalNumber = phoneNum;
349     }
350     ret = DelayedSingleton<CallNumberUtils>::GetInstance()->FormatPhoneNumberToInternational(
351         phoneNum, ISO_COUNTRY_CODE, internationalNumber);
352     if (ret != TELEPHONY_SUCCESS) {
353         TELEPHONY_LOGE("Format phone number failed.");
354         internationalNumber = phoneNum;
355     }
356     predicates.EqualTo(CALL_PHONE_NUMBER, nationalNumber)->Or()->EqualTo(CALL_PHONE_NUMBER, internationalNumber);
357     auto resultSet = callDataHelper->Query(uri, predicates, columns);
358     if (resultSet == nullptr) {
359         TELEPHONY_LOGE("Query Result Set nullptr Failed.");
360         callDataHelper->Release();
361         return TELEPHONY_ERR_LOCAL_PTR_NULL;
362     }
363     int32_t count = 0;
364     if (resultSet->GetRowCount(count) == E_OK && count != 0) {
365         result = true;
366     }
367     TELEPHONY_LOGI("count: %{public}d", count);
368     resultSet->Close();
369     callDataHelper->Release();
370     return TELEPHONY_SUCCESS;
371 }
372 
GetAirplaneMode(bool & isAirplaneModeOn)373 int32_t CallDataBaseHelper::GetAirplaneMode(bool &isAirplaneModeOn)
374 {
375     std::shared_ptr<DataShare::DataShareHelper> callDataHelper = CreateDataShareHelper(SETTINGS_DATA_URI);
376     if (callDataHelper == nullptr) {
377         TELEPHONY_LOGE("callDataHelper is null");
378         return TELEPHONY_ERR_LOCAL_PTR_NULL;
379     }
380     Uri uri(SETTINGS_AIRPLANE_MODE_URI);
381     std::vector<std::string> columns;
382     DataShare::DataSharePredicates predicates;
383     predicates.EqualTo(SETTING_KEY, SETTINGS_AIRPLANE_MODE);
384     auto result = callDataHelper->Query(uri, predicates, columns);
385     if (result == nullptr) {
386         TELEPHONY_LOGE("CallDataBaseHelper: query error, result is null");
387         callDataHelper->Release();
388         return TELEPHONY_ERR_LOCAL_PTR_NULL;
389     }
390     if (result->GoToFirstRow() != DataShare::E_OK) {
391         TELEPHONY_LOGE("CallDataBaseHelper: query error, go to first row error");
392         result->Close();
393         callDataHelper->Release();
394         return TELEPHONY_ERR_DATABASE_READ_FAIL;
395     }
396     int32_t columnindex = 0;
397     std::string value = "";
398     result->GetColumnIndex(SETTING_VALUE, columnindex);
399     result->GetString(columnindex, value);
400     result->Close();
401     callDataHelper->Release();
402     isAirplaneModeOn = value == "1";
403     TELEPHONY_LOGI("Get airplane mode:%{public}d", isAirplaneModeOn);
404     return TELEPHONY_SUCCESS;
405 }
406 } // namespace Telephony
407 } // namespace OHOS
408