• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #define MLOG_TAG "ringtone_Extension"
16 
17 #include "ringtone_datashare_extension.h"
18 
19 #include "app_mgr_client.h"
20 #include "datashare_ext_ability_context.h"
21 #include "dfx_manager.h"
22 #include "dfx_const.h"
23 #include "os_account_manager.h"
24 #include "parameter.h"
25 #include "permission_utils.h"
26 #include "preferences_helper.h"
27 #include "ipc_skeleton.h"
28 #include "result_set_utils.h"
29 #include "ringtone_data_manager.h"
30 #include "ringtone_datashare_stub_impl.h"
31 #include "ringtone_file_utils.h"
32 #include "ringtone_language_manager.h"
33 #include "ringtone_log.h"
34 #include "ringtone_rdbstore.h"
35 #include "ringtone_scanner_manager.h"
36 #include "ringtone_tracer.h"
37 #include "runtime.h"
38 #include "singleton.h"
39 #include "ringtone_proxy_uri.h"
40 #include "ringtone_fetch_result.h"
41 
42 namespace OHOS {
43 namespace AbilityRuntime {
44 using namespace std;
45 using namespace OHOS::AppExecFwk;
46 using namespace OHOS::NativeRdb;
47 using namespace OHOS::Media;
48 using namespace OHOS::DataShare;
49 
50 const char RINGTONE_PARAMETER_SCANNER_FIRST_KEY[] = "ringtone.scanner.first";
51 const char RINGTONE_PARAMETER_SCANNER_FIRST_TRUE[] = "true";
52 const char RINGTONE_PARAMETER_SCANNER_FIRST_FALSE[] = "false";
53 const char RINGTONE_PARAMETER_SCANNER_USERID_KEY[] = "ringtone.scanner.userId";
54 const int32_t RINGTONEPARA_SIZE = 64;
55 const std::string OLD_RINGTONE_CUSTOMIZED_BASE_RINGTONE_PATH = "/storage/media/local/files/Ringtone";
56 const std::vector<std::string> RINGTONE_OPEN_WRITE_MODE_VECTOR = {
57     { RINGTONE_FILEMODE_WRITEONLY },
58     { RINGTONE_FILEMODE_READWRITE },
59     { RINGTONE_FILEMODE_WRITETRUNCATE },
60     { RINGTONE_FILEMODE_WRITEAPPEND },
61     { RINGTONE_FILEMODE_READWRITETRUNCATE },
62     { RINGTONE_FILEMODE_READWRITEAPPEND },
63 };
64 
65 std::map<std::string, std::string> VALID_URI_TO_TABLE {
66     {SIMCARD_SETTING_PATH_URI, SIMCARD_SETTING_TABLE},
67     {RINGTONE_PATH_URI, RINGTONE_TABLE},
68     {VIBRATE_PATH_URI, VIBRATE_TABLE}
69 };
70 
71 static const char RINGTONE_RDB_SCANNER_FLAG_KEY[] = "RDBInitScanner";
72 static const int RINGTONE_RDB_SCANNER_FLAG_KEY_TRUE = 1;
73 static const int RINGTONE_RDB_SCANNER_FLAG_KEY_FALSE = 0;
74 const std::string PRELOAD_RINGTONE_TYPE = "1";
75 
Create(const unique_ptr<Runtime> & runtime)76 RingtoneDataShareExtension *RingtoneDataShareExtension::Create(const unique_ptr<Runtime> &runtime)
77 {
78     return new RingtoneDataShareExtension(static_cast<Runtime&>(*runtime));
79 }
80 
RingtoneDataShareExtension(Runtime & runtime)81 RingtoneDataShareExtension::RingtoneDataShareExtension(Runtime &runtime) : DataShareExtAbility(), runtime_(runtime) {}
82 
~RingtoneDataShareExtension()83 RingtoneDataShareExtension::~RingtoneDataShareExtension()
84 {
85 }
86 
Init(const shared_ptr<AbilityLocalRecord> & record,const shared_ptr<OHOSApplication> & application,shared_ptr<AbilityHandler> & handler,const sptr<IRemoteObject> & token)87 void RingtoneDataShareExtension::Init(const shared_ptr<AbilityLocalRecord> &record,
88     const shared_ptr<OHOSApplication> &application, shared_ptr<AbilityHandler> &handler,
89     const sptr<IRemoteObject> &token)
90 {
91     if ((record == nullptr) || (application == nullptr) || (handler == nullptr) || (token == nullptr)) {
92         RINGTONE_ERR_LOG("RingtoneDataShareExtension::init failed, some object is nullptr");
93         DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->KillApplicationSelf();
94         return;
95     }
96     DataShareExtAbility::Init(record, application, handler, token);
97 }
98 
CheckRingtoneDbDefaultSettings()99 void RingtoneDataShareExtension::CheckRingtoneDbDefaultSettings()
100 {
101     int errCode = 0;
102     shared_ptr<NativePreferences::Preferences> prefs =
103         NativePreferences::PreferencesHelper::GetPreferences(COMMON_XML_EL1, errCode);
104     if (!prefs) {
105         RINGTONE_ERR_LOG("get preferences error: %{public}d", errCode);
106         return;
107     }
108     int isScanner = prefs->GetInt(RINGTONE_RDB_SCANNER_FLAG_KEY, RINGTONE_RDB_SCANNER_FLAG_KEY_FALSE);
109     if (isScanner == RINGTONE_RDB_SCANNER_FLAG_KEY_TRUE) {
110         return;
111     }
112     auto rdbStore = RingtoneRdbStore::GetInstance();
113     CHECK_AND_RETURN_LOG(rdbStore != nullptr, "rdbstore is nullptr");
114     auto rawRdb = rdbStore->GetRaw();
115     CHECK_AND_RETURN_LOG(rawRdb != nullptr, "rawRdb is nullptr");
116     string sql = "SELECT " + PRELOAD_CONFIG_COLUMN_DISPLAY_NAME + " FROM " +
117         PRELOAD_CONFIG_TABLE + " WHERE " + PRELOAD_CONFIG_COLUMN_RING_TONE_TYPE + " = " + PRELOAD_RINGTONE_TYPE;
118     auto resultSet = rawRdb->QuerySql(sql);
119     CHECK_AND_RETURN_LOG(resultSet != nullptr, "resultSet is nullptr");
120     if (resultSet->GoToFirstRow() != NativeRdb::E_OK) {
121         resultSet->Close();
122         RINGTONE_INFO_LOG("Query operation failed, no resultSet");
123         return;
124     }
125     string displayName = GetStringVal(PRELOAD_CONFIG_COLUMN_DISPLAY_NAME, resultSet);
126     if (!displayName.empty()) {
127         RINGTONE_INFO_LOG("The default ringtone has been set. ringtone=%{public}s", displayName.c_str());
128         prefs->PutInt(RINGTONE_RDB_SCANNER_FLAG_KEY, RINGTONE_RDB_SCANNER_FLAG_KEY_TRUE);
129         prefs->FlushSync();
130     }
131     resultSet->Close();
132     return;
133 }
134 
OnStart(const AAFwk::Want & want)135 void RingtoneDataShareExtension::OnStart(const AAFwk::Want &want)
136 {
137     RINGTONE_DEBUG_LOG("begin.");
138     Extension::OnStart(want);
139     auto context = AbilityRuntime::Context::GetApplicationContext();
140     if (context == nullptr) {
141         RINGTONE_ERR_LOG("Failed to get context");
142         DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->KillApplicationSelf();
143         return;
144     }
145     RINGTONE_INFO_LOG("runtime language %{public}d", runtime_.GetLanguage());
146 
147     auto dataManager = RingtoneDataManager::GetInstance();
148     if (dataManager == nullptr) {
149         RINGTONE_ERR_LOG("Failed to get dataManager");
150         DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->KillApplicationSelf();
151         return;
152     }
153     int32_t ret = dataManager->Init(context);
154     if (ret != Media::E_OK) {
155         RINGTONE_ERR_LOG("Failed to init RingtoneData Mgr");
156         DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->KillApplicationSelf();
157         return;
158     }
159     dataManager->SetOwner(static_pointer_cast<RingtoneDataShareExtension>(shared_from_this()));
160     auto dfxMgr = DfxManager::GetInstance();
161     dfxMgr->Init(context);
162 
163     CheckRingtoneDbDefaultSettings();
164     RingtoneScanner();
165 
166     if (RingtoneFileUtils::IsFileExists(OLD_RINGTONE_CUSTOMIZED_BASE_RINGTONE_PATH)) {
167         UpdataRdbPathData();
168     }
169 
170     RingtoneLanguageManager::GetInstance()->SyncAssetLanguage();
171     RINGTONE_DEBUG_LOG("end.");
172 }
173 
OnStop()174 void RingtoneDataShareExtension::OnStop()
175 {
176     RINGTONE_DEBUG_LOG("begin.");
177     auto scannerManager = RingtoneScannerManager::GetInstance();
178     if (scannerManager != nullptr) {
179         scannerManager->Stop();
180     }
181     RingtoneDataManager::GetInstance()->ClearRingtoneDataMgr();
182     RINGTONE_DEBUG_LOG("end.");
183 }
184 
OnConnect(const AAFwk::Want & want)185 sptr<IRemoteObject> RingtoneDataShareExtension::OnConnect(const AAFwk::Want &want)
186 {
187     RINGTONE_DEBUG_LOG("begin.");
188     Extension::OnConnect(want);
189     sptr<RingtoneDataShareStubImpl> remoteObject = new (nothrow) RingtoneDataShareStubImpl(
190         static_pointer_cast<RingtoneDataShareExtension>(shared_from_this()),
191         nullptr);
192     if (remoteObject == nullptr) {
193         RINGTONE_ERR_LOG("No memory allocated for DataShareStubImpl");
194         return nullptr;
195     }
196     RINGTONE_DEBUG_LOG("end.");
197     return remoteObject->AsObject();
198 }
199 
CheckRingtonePerm(RingtoneDataCommand & cmd,bool isWrite)200 static int32_t CheckRingtonePerm(RingtoneDataCommand &cmd, bool isWrite)
201 {
202     auto err = E_SUCCESS;
203     if (!RingtonePermissionUtils::IsSystemApp() && IPCSkeleton::GetCallingUid() != 0
204         && !RingtonePermissionUtils::IsNativeSAApp()) {
205         RINGTONE_ERR_LOG("RingtoneLibrary should only be called by system applications!");
206         return E_PERMISSION_DENIED;
207     }
208 
209     if (isWrite) {
210         err = (RingtonePermissionUtils::CheckCallerPermission(PERM_WRITE_RINGTONE)||
211             (RingtonePermissionUtils::CheckCallerPermission(PERM_ACCESS_CUSTOM_RINGTONE)) ?
212             E_SUCCESS : E_PERMISSION_DENIED);
213     }
214 
215     return err;
216 }
217 
GetValidUriTab(const Uri & uri,string & tab)218 static int32_t GetValidUriTab(const Uri &uri, string &tab)
219 {
220     string uriStr = uri.ToString();
221 
222     auto proxyStringPos = uriStr.find(RINGTONE_URI_PROXY_STRING);
223     auto lastSlash = uriStr.find_last_of('/');
224     if (lastSlash != std::string::npos &&
225         proxyStringPos != std::string::npos) {
226         auto tablePos = lastSlash + 1;
227         tab = uriStr.substr(tablePos, proxyStringPos - tablePos);
228         return Media::E_OK;
229     }
230 
231     for (const auto &pair : VALID_URI_TO_TABLE) {
232         if (uriStr.find(pair.first) != std::string::npos) {
233             tab = pair.second;
234             return Media::E_OK;
235         }
236     }
237 
238     RINGTONE_INFO_LOG("INVALID uri=%{public}s", uriStr.c_str());
239     return E_INVALID_URI;
240 }
241 
242 static const std::vector<string> g_ringToneTableFields = {
243     { RINGTONE_COLUMN_TONE_ID },
244     { RINGTONE_COLUMN_DATA },
245     { RINGTONE_COLUMN_SIZE },
246     { RINGTONE_COLUMN_DISPLAY_NAME },
247     { RINGTONE_COLUMN_TITLE },
248     { RINGTONE_COLUMN_MEDIA_TYPE },
249     { RINGTONE_COLUMN_TONE_TYPE },
250     { RINGTONE_COLUMN_MIME_TYPE },
251     { RINGTONE_COLUMN_SOURCE_TYPE },
252     { RINGTONE_COLUMN_DATE_ADDED },
253     { RINGTONE_COLUMN_DATE_MODIFIED },
254     { RINGTONE_COLUMN_DATE_TAKEN },
255     { RINGTONE_COLUMN_DURATION },
256     { RINGTONE_COLUMN_SHOT_TONE_TYPE },
257     { RINGTONE_COLUMN_SHOT_TONE_SOURCE_TYPE },
258     { RINGTONE_COLUMN_NOTIFICATION_TONE_TYPE },
259     { RINGTONE_COLUMN_NOTIFICATION_TONE_SOURCE_TYPE },
260     { RINGTONE_COLUMN_RING_TONE_TYPE },
261     { RINGTONE_COLUMN_RING_TONE_SOURCE_TYPE },
262     { RINGTONE_COLUMN_ALARM_TONE_TYPE },
263     { RINGTONE_COLUMN_ALARM_TONE_SOURCE_TYPE },
264     { RINGTONE_COLUMN_SCANNER_FLAG },
265 };
266 
DumpDataShareValueBucket(const std::vector<string> & tabFields,const DataShareValuesBucket & value)267 void RingtoneDataShareExtension::DumpDataShareValueBucket(const std::vector<string> &tabFields,
268     const DataShareValuesBucket &value)
269 {
270     bool isValid = false;
271     for (auto tab : tabFields) {
272         auto valueObject = value.Get(tab, isValid);
273         if (!isValid) {
274             RINGTONE_INFO_LOG("not set field: %{public}s", tab.c_str());
275             continue;
276         }
277 
278         if (std::get_if<std::vector<uint8_t>>(&(valueObject.value))) {
279             auto value = static_cast<std::vector<uint8_t>>(valueObject);
280             RINGTONE_INFO_LOG("field: %{public}s, value=%{public}s",
281                 tab.c_str(), value.data());
282         } else if (std::get_if<int64_t>(&(valueObject.value))) {
283             auto value = static_cast<int64_t>(valueObject);
284             RINGTONE_INFO_LOG("field: %{public}s, value=%{public}" PRId64,
285                 tab.c_str(), value);
286         } else if (std::get_if<std::string>(&(valueObject.value))) {
287             auto value = static_cast<std::string>(valueObject);
288             RINGTONE_INFO_LOG("field: %{public}s, value=%{public}s",
289                 tab.c_str(), value.c_str());
290         } else if (std::get_if<bool>(&(valueObject.value))) {
291             auto value = static_cast<bool>(valueObject);
292             RINGTONE_INFO_LOG("field: %{public}s, value=%{public}d",
293                 tab.c_str(), value);
294         } else if (std::get_if<double>(&(valueObject.value))) {
295             auto value = static_cast<double>(valueObject);
296             RINGTONE_INFO_LOG("field: %{public}s, value=%{public}lf",
297                 tab.c_str(), value);
298         } else {
299             RINGTONE_INFO_LOG("unkown field: %{public}s type", tab.c_str());
300         }
301     }
302 }
303 
UpdataRdbPathData()304 void RingtoneDataShareExtension::UpdataRdbPathData()
305 {
306     auto result = RingtoneFileUtils::MoveRingtoneFolder();
307     CHECK_AND_RETURN_LOG(result, "MoveRingtoneFolder failed");
308 
309     Uri uri(RINGTONE_LIBRARY_PROXY_DATA_URI_TONE_FILES);
310 
311     DataSharePredicates predicates;
312     const std::string selection = RINGTONE_COLUMN_DATA + " LIKE ? ";
313     std::vector<std::string> selectionArgs = {"%/storage/media/local/files/%"};
314     predicates.SetWhereClause(selection);
315     predicates.SetWhereArgs(selectionArgs);
316 
317     vector<string> columns { RINGTONE_COLUMN_DATA, RINGTONE_COLUMN_TONE_ID };
318     DatashareBusinessError businessError;
319     auto resultSet = Query(uri, predicates, columns, businessError);
320     CHECK_AND_RETURN_LOG(resultSet != nullptr, "query is nullptr");
321 
322     auto results = make_unique<RingtoneFetchResult<RingtoneAsset>>(move(resultSet));
323     unique_ptr<RingtoneAsset> ringtoneAsset = results->GetFirstObject();
324     CHECK_AND_RETURN_LOG(ringtoneAsset != nullptr, "ringtoneAsset is nullptr");
325 
326     while (ringtoneAsset != nullptr) {
327         int toneId = ringtoneAsset->GetId();
328         std::string oldPath = ringtoneAsset->GetPath();
329         std::string newPath = oldPath;
330         size_t start_pos = 0;
331         if ((start_pos = newPath.find("/storage/media/local/files/Ringtone/")) != std::string::npos) {
332             newPath.replace(start_pos, std::string("/storage/media/local/files/Ringtone").length(),
333                 "/data/storage/el2/base/files/Ringtone");
334         }
335         if (!RingtoneFileUtils::IsFileExists(newPath)) {
336             RINGTONE_ERR_LOG("the file is not exists, path: %{public}s", newPath.c_str());
337             ringtoneAsset = results->GetNextObject();
338             continue;
339         }
340         DataSharePredicates predicates;
341         const std::string selection = RINGTONE_COLUMN_TONE_ID + " = ? ";
342         predicates.SetWhereClause(selection);
343         predicates.SetWhereArgs({to_string(toneId)});
344         DataShare::DataShareValuesBucket valuesBucket;
345         valuesBucket.Put(RINGTONE_COLUMN_DATA, newPath);
346         Update(uri, predicates, valuesBucket);
347         ringtoneAsset = results->GetNextObject();
348     }
349     RingtoneFileUtils::RemoveRingtoneFolder(OLD_RINGTONE_CUSTOMIZED_BASE_RINGTONE_PATH);
350     return;
351 }
352 
Insert(const Uri & uri,const DataShareValuesBucket & value)353 int RingtoneDataShareExtension::Insert(const Uri &uri, const DataShareValuesBucket &value)
354 {
355     RINGTONE_DEBUG_LOG("entry, uri=%{public}s", uri.ToString().c_str());
356 
357     DumpDataShareValueBucket(g_ringToneTableFields, value);
358 
359     string tab("");
360     int err = GetValidUriTab(uri, tab);
361     if (err != Media::E_OK) {
362         return err;
363     }
364 
365     RingtoneDataCommand cmd(uri, tab, RingtoneOperationType::INSERT);
366     err = CheckRingtonePerm(cmd, true);
367     if (err < 0) {
368         RINGTONE_ERR_LOG("Check Insert-permission failed, errCode: %{public}d", err);
369         return err;
370     }
371 
372     auto ret = RingtoneDataManager::GetInstance()->Insert(cmd, value);
373     return ret;
374 }
375 
Update(const Uri & uri,const DataSharePredicates & predicates,const DataShareValuesBucket & value)376 int RingtoneDataShareExtension::Update(const Uri &uri, const DataSharePredicates &predicates,
377     const DataShareValuesBucket &value)
378 {
379     RINGTONE_DEBUG_LOG("entry, uri=%{public}s", uri.ToString().c_str());
380     RINGTONE_DEBUG_LOG("WhereClause=%{public}s", predicates.GetWhereClause().c_str());
381 
382     string tab("");
383     int err = GetValidUriTab(uri, tab);
384     if (err != Media::E_OK) {
385         return err;
386     }
387 
388     RingtoneDataCommand cmd(uri, tab, RingtoneOperationType::UPDATE);
389     err = CheckRingtonePerm(cmd, false);
390     if (err < 0) {
391         RINGTONE_ERR_LOG("Check Update-permission failed, errCode: %{public}d", err);
392         return err;
393     }
394 
395     return RingtoneDataManager::GetInstance()->Update(cmd, value, predicates);
396 }
397 
Delete(const Uri & uri,const DataSharePredicates & predicates)398 int RingtoneDataShareExtension::Delete(const Uri &uri, const DataSharePredicates &predicates)
399 {
400     RINGTONE_DEBUG_LOG("entry, uri=%{public}s", uri.ToString().c_str());
401 
402     string tab("");
403     int err = GetValidUriTab(uri, tab);
404     if (err != Media::E_OK) {
405         return err;
406     }
407 
408     RingtoneDataCommand cmd(uri, tab, RingtoneOperationType::DELETE);
409     err = CheckRingtonePerm(cmd, true);
410     if (err < 0) {
411         RINGTONE_ERR_LOG("Check Delete-permission failed, errCode: %{public}d", err);
412         return err;
413     }
414 
415     return RingtoneDataManager::GetInstance()->Delete(cmd, predicates);
416 }
417 
Query(const Uri & uri,const DataSharePredicates & predicates,vector<string> & columns,DatashareBusinessError & businessError)418 shared_ptr<DataShareResultSet> RingtoneDataShareExtension::Query(const Uri &uri,
419     const DataSharePredicates &predicates, vector<string> &columns, DatashareBusinessError &businessError)
420 {
421     RINGTONE_DEBUG_LOG("entry, uri=%{public}s", uri.ToString().c_str());
422 
423     string tab("");
424     int err = GetValidUriTab(uri, tab);
425     if (err != Media::E_OK) {
426         return nullptr;
427     }
428 
429     RingtoneDataCommand cmd(uri, tab, RingtoneOperationType::QUERY);
430     err = CheckRingtonePerm(cmd, false);
431     if (err < 0) {
432         businessError.SetCode(err);
433         RINGTONE_ERR_LOG("Check Query-permission failed, errCode: %{public}d", err);
434         return nullptr;
435     }
436 
437     int errCode = businessError.GetCode();
438     auto queryResultSet = RingtoneDataManager::GetInstance()->Query(cmd, columns, predicates, errCode);
439     businessError.SetCode(to_string(errCode));
440     if (queryResultSet == nullptr) {
441         RINGTONE_ERR_LOG("queryResultSet is nullptr! errCode: %{public}d", errCode);
442         return nullptr;
443     }
444     shared_ptr<DataShareResultSet> resultSet = make_shared<DataShareResultSet>(queryResultSet);
445     return resultSet;
446 }
447 
OpenFile(const Uri & uri,const string & mode)448 int RingtoneDataShareExtension::OpenFile(const Uri &uri, const string &mode)
449 {
450     RINGTONE_DEBUG_LOG("entry, uri=%{public}s, mode=%{public}s",
451         uri.ToString().c_str(), mode.c_str());
452 
453     string tab("");
454     int err = GetValidUriTab(uri, tab);
455     if (err != Media::E_OK) {
456         return err;
457     }
458 
459     RingtoneDataCommand cmd(uri, tab, RingtoneOperationType::OPEN);
460     string unifyMode = mode;
461     transform(unifyMode.begin(), unifyMode.end(), unifyMode.begin(), ::tolower);
462 
463     bool isWrite = false;
464     auto iter = find(RINGTONE_OPEN_WRITE_MODE_VECTOR.begin(), RINGTONE_OPEN_WRITE_MODE_VECTOR.end(), unifyMode);
465     if (iter != RINGTONE_OPEN_WRITE_MODE_VECTOR.end()) {
466         isWrite = true;
467     }
468     err = CheckRingtonePerm(cmd, isWrite);
469     if (err == E_PERMISSION_DENIED) {
470         RINGTONE_ERR_LOG("OpenFile denied, errCode: %{public}d", err);
471         return err;
472     }
473     return RingtoneDataManager::GetInstance()->OpenFile(cmd, unifyMode);
474 }
475 
GetUserId()476 int32_t RingtoneDataShareExtension::GetUserId()
477 {
478     RINGTONE_INFO_LOG("GetUserID Start.");
479     int32_t userId = 0;
480     std::vector<int> activeIds;
481     int ret = AccountSA::OsAccountManager::QueryActiveOsAccountIds(activeIds);
482     if (ret != 0) {
483         RINGTONE_ERR_LOG("QueryActiveOsAccountIds failed ret:%{public}d", ret);
484         return userId;
485     }
486     if (activeIds.empty()) {
487         RINGTONE_ERR_LOG("QueryActiveOsAccountIds activeIds empty");
488         return userId;
489     }
490     userId = activeIds[0];
491     RINGTONE_INFO_LOG("GetUserID End, userId: %{private}d", userId);
492     return userId;
493 }
494 
IdExists(const std::string & ids,int32_t id)495 bool RingtoneDataShareExtension::IdExists(const std::string &ids, int32_t id)
496 {
497     RINGTONE_INFO_LOG("IdExists Start.");
498     if (ids.empty()) {
499         return false;
500     }
501 
502     size_t pos = 0;
503     std::string idStr = std::to_string(id);
504 
505     while ((pos = ids.find(idStr, pos)) != std::string::npos) {
506         bool startPos = (pos == 0) || (ids[pos - 1] == ' ');
507         bool endPos = (pos + idStr.length() == ids.length()) || (ids[pos + idStr.length()] == ' ');
508         if (startPos && endPos) {
509             return true;
510         }
511         pos += idStr.length();
512     }
513     RINGTONE_INFO_LOG("IdExists End.");
514     return false;
515 }
516 
CheckCurrentUser()517 bool RingtoneDataShareExtension::CheckCurrentUser()
518 {
519     RINGTONE_INFO_LOG("CheckCurrentUser Start.");
520     char paramValue[RINGTONEPARA_SIZE] = {0};
521     GetParameter(RINGTONE_PARAMETER_SCANNER_USERID_KEY, "", paramValue, RINGTONEPARA_SIZE);
522     std::string ids(paramValue);
523     RINGTONE_INFO_LOG("GetParameter end, paramValue: %{private}s .", ids.c_str());
524     int32_t currentUserId = GetUserId();
525     if (IdExists(ids, currentUserId)) {
526         return true;
527     }
528     if (!ids.empty() && ids.back() != ' ') {
529         ids += " ";
530     }
531     ids += std::to_string(currentUserId);
532     RINGTONE_INFO_LOG("CurrentUserIds: %{private}s .", ids.c_str());
533     const char* cstr = ids.c_str();
534     int result = SetParameter(RINGTONE_PARAMETER_SCANNER_USERID_KEY, cstr);
535     RINGTONE_INFO_LOG("CheckCurrentUser End. SetParameter end, result: %{public}d", result);
536     return false;
537 }
538 
RingtoneScanner()539 void RingtoneDataShareExtension::RingtoneScanner()
540 {
541     RingtoneTracer tracer;
542     tracer.Start("Ringtone Scanner");
543     RINGTONE_INFO_LOG("Ringtone Scanner Start.");
544     RingtoneFileUtils::AccessRingtoneDir();
545     // ringtone scan
546     char paramValue[RINGTONEPARA_SIZE] = {0};
547     bool currentFlag = CheckCurrentUser();
548     GetParameter(RINGTONE_PARAMETER_SCANNER_FIRST_KEY, "", paramValue, RINGTONEPARA_SIZE);
549     if (!currentFlag && strcmp(paramValue, RINGTONE_PARAMETER_SCANNER_FIRST_TRUE) == 0) {
550         int result = SetParameter(RINGTONE_PARAMETER_SCANNER_FIRST_KEY, RINGTONE_PARAMETER_SCANNER_FIRST_FALSE);
551         RINGTONE_INFO_LOG("CheckCurrentUser SetParameter end, result: %{public}d", result);
552     }
553     GetParameter(RINGTONE_PARAMETER_SCANNER_FIRST_KEY, "", paramValue, RINGTONEPARA_SIZE);
554     std::string parameter(paramValue);
555     RINGTONE_INFO_LOG("GetParameter end, paramValue: %{public}s .", parameter.c_str());
556     if (strcmp(paramValue, RINGTONE_PARAMETER_SCANNER_FIRST_FALSE) == 0) {
557         RingtoneScannerManager::GetInstance()->Start(false);
558     }
559     RINGTONE_INFO_LOG("Ringtone Scanner End.");
560 }
561 
RingtoneDataShareCreator(const unique_ptr<Runtime> & runtime)562 static DataShare::DataShareExtAbility *RingtoneDataShareCreator(const unique_ptr<Runtime> &runtime)
563 {
564     RINGTONE_DEBUG_LOG("entry");
565     return  RingtoneDataShareExtension::Create(runtime);
566 }
567 
RegisterDataShareCreator()568 __attribute__((constructor)) void RegisterDataShareCreator()
569 {
570     RINGTONE_DEBUG_LOG("entry");
571     DataShare::DataShareExtAbility::SetCreator(RingtoneDataShareCreator);
572 
573     RINGTONE_DEBUG_LOG("End");
574 }
575 } // namespace AbilityRuntime
576 } // namespace OHOS
577