• 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 "parameter.h"
24 #include "permission_utils.h"
25 #include "preferences_helper.h"
26 #include "ipc_skeleton.h"
27 #include "ringtone_data_manager.h"
28 #include "ringtone_datashare_stub_impl.h"
29 #include "ringtone_file_utils.h"
30 #include "ringtone_language_manager.h"
31 #include "ringtone_log.h"
32 #include "ringtone_scanner_manager.h"
33 #include "runtime.h"
34 #include "singleton.h"
35 
36 namespace OHOS {
37 namespace AbilityRuntime {
38 using namespace std;
39 using namespace OHOS::AppExecFwk;
40 using namespace OHOS::NativeRdb;
41 using namespace OHOS::Media;
42 using namespace OHOS::DataShare;
43 
44 const char RINGTONE_PARAMETER_SCANNER_COMPLETED_KEY[] = "ringtone.scanner.completed";
45 const int RINGTONE_PARAMETER_SCANNER_COMPLETED_TRUE = 1;
46 const int RINGTONE_PARAMETER_SCANNER_COMPLETED_FALSE = 0;
47 const std::vector<std::string> RINGTONE_OPEN_WRITE_MODE_VECTOR = {
48     { RINGTONE_FILEMODE_WRITEONLY },
49     { RINGTONE_FILEMODE_READWRITE },
50     { RINGTONE_FILEMODE_WRITETRUNCATE },
51     { RINGTONE_FILEMODE_WRITEAPPEND },
52     { RINGTONE_FILEMODE_READWRITETRUNCATE },
53     { RINGTONE_FILEMODE_READWRITEAPPEND },
54 };
55 
Create(const unique_ptr<Runtime> & runtime)56 RingtoneDataShareExtension *RingtoneDataShareExtension::Create(const unique_ptr<Runtime> &runtime)
57 {
58     return new RingtoneDataShareExtension(static_cast<Runtime&>(*runtime));
59 }
60 
RingtoneDataShareExtension(Runtime & runtime)61 RingtoneDataShareExtension::RingtoneDataShareExtension(Runtime &runtime) : DataShareExtAbility(), runtime_(runtime) {}
62 
~RingtoneDataShareExtension()63 RingtoneDataShareExtension::~RingtoneDataShareExtension()
64 {
65 }
66 
Init(const shared_ptr<AbilityLocalRecord> & record,const shared_ptr<OHOSApplication> & application,shared_ptr<AbilityHandler> & handler,const sptr<IRemoteObject> & token)67 void RingtoneDataShareExtension::Init(const shared_ptr<AbilityLocalRecord> &record,
68     const shared_ptr<OHOSApplication> &application, shared_ptr<AbilityHandler> &handler,
69     const sptr<IRemoteObject> &token)
70 {
71     if ((record == nullptr) || (application == nullptr) || (handler == nullptr) || (token == nullptr)) {
72         RINGTONE_ERR_LOG("RingtoneDataShareExtension::init failed, some object is nullptr");
73         DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->KillApplicationSelf();
74         return;
75     }
76     DataShareExtAbility::Init(record, application, handler, token);
77 }
78 
OnStart(const AAFwk::Want & want)79 void RingtoneDataShareExtension::OnStart(const AAFwk::Want &want)
80 {
81     RINGTONE_DEBUG_LOG("begin.");
82     Extension::OnStart(want);
83     auto context = AbilityRuntime::Context::GetApplicationContext();
84     if (context == nullptr) {
85         RINGTONE_ERR_LOG("Failed to get context");
86         DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->KillApplicationSelf();
87         return;
88     }
89     RINGTONE_INFO_LOG("runtime language %{public}d", runtime_.GetLanguage());
90     auto dataManager = RingtoneDataManager::GetInstance();
91     if (dataManager == nullptr) {
92         RINGTONE_ERR_LOG("Failed to get dataManager");
93         DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->KillApplicationSelf();
94         return;
95     }
96     int32_t ret = dataManager->Init(context);
97     if (ret != Media::E_OK) {
98         RINGTONE_ERR_LOG("Failed to init RingtoneData Mgr");
99         DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->KillApplicationSelf();
100         return;
101     }
102     dataManager->SetOwner(static_pointer_cast<RingtoneDataShareExtension>(shared_from_this()));
103     auto dfxMgr = DfxManager::GetInstance();
104     dfxMgr->Init(context);
105 
106     RingtoneScanner();
107     RingtoneLanguageManager::GetInstance()->SyncAssetLanguage();
108     RINGTONE_DEBUG_LOG("end.");
109 }
110 
OnStop()111 void RingtoneDataShareExtension::OnStop()
112 {
113     RINGTONE_DEBUG_LOG("begin.");
114     auto scannerManager = RingtoneScannerManager::GetInstance();
115     if (scannerManager != nullptr) {
116         scannerManager->Stop();
117     }
118     RingtoneDataManager::GetInstance()->ClearRingtoneDataMgr();
119     RINGTONE_DEBUG_LOG("end.");
120 }
121 
OnConnect(const AAFwk::Want & want)122 sptr<IRemoteObject> RingtoneDataShareExtension::OnConnect(const AAFwk::Want &want)
123 {
124     RINGTONE_DEBUG_LOG("begin.");
125     Extension::OnConnect(want);
126     sptr<RingtoneDataShareStubImpl> remoteObject = new (nothrow) RingtoneDataShareStubImpl(
127         static_pointer_cast<RingtoneDataShareExtension>(shared_from_this()),
128         nullptr);
129     if (remoteObject == nullptr) {
130         RINGTONE_ERR_LOG("No memory allocated for DataShareStubImpl");
131         return nullptr;
132     }
133     RINGTONE_DEBUG_LOG("end.");
134     return remoteObject->AsObject();
135 }
136 
CheckRingtonePerm(RingtoneDataCommand & cmd,bool isWrite)137 static int32_t CheckRingtonePerm(RingtoneDataCommand &cmd, bool isWrite)
138 {
139     auto err = E_SUCCESS;
140     if (!RingtonePermissionUtils::IsSystemApp() && IPCSkeleton::GetCallingUid() != 0
141         && !RingtonePermissionUtils::IsNativeSAApp()) {
142         RINGTONE_ERR_LOG("RingtoneLibrary should only be called by system applications!");
143         return E_PERMISSION_DENIED;
144     }
145 
146     if (isWrite) {
147         err = (RingtonePermissionUtils::CheckCallerPermission(PERM_WRITE_RINGTONE) ? E_SUCCESS : E_PERMISSION_DENIED);
148     }
149 
150     return err;
151 }
152 
UriValidCheck(const Uri & uri)153 static int32_t UriValidCheck(const Uri &uri)
154 {
155     string uriStr = uri.ToString();
156     if (uriStr.compare(0, RINGTONE_PATH_URI.size(), RINGTONE_PATH_URI)) {
157         RINGTONE_ERR_LOG("error: invalid uri!");
158         return E_INVALID_URI;
159     }
160     return Media::E_OK;
161 }
162 
163 static const std::vector<string> g_ringToneTableFields = {
164     { RINGTONE_COLUMN_TONE_ID },
165     { RINGTONE_COLUMN_DATA },
166     { RINGTONE_COLUMN_SIZE },
167     { RINGTONE_COLUMN_DISPLAY_NAME },
168     { RINGTONE_COLUMN_TITLE },
169     { RINGTONE_COLUMN_MEDIA_TYPE },
170     { RINGTONE_COLUMN_TONE_TYPE },
171     { RINGTONE_COLUMN_MIME_TYPE },
172     { RINGTONE_COLUMN_SOURCE_TYPE },
173     { RINGTONE_COLUMN_DATE_ADDED },
174     { RINGTONE_COLUMN_DATE_MODIFIED },
175     { RINGTONE_COLUMN_DATE_TAKEN },
176     { RINGTONE_COLUMN_DURATION },
177     { RINGTONE_COLUMN_SHOT_TONE_TYPE },
178     { RINGTONE_COLUMN_SHOT_TONE_SOURCE_TYPE },
179     { RINGTONE_COLUMN_NOTIFICATION_TONE_TYPE },
180     { RINGTONE_COLUMN_NOTIFICATION_TONE_SOURCE_TYPE },
181     { RINGTONE_COLUMN_RING_TONE_TYPE },
182     { RINGTONE_COLUMN_RING_TONE_SOURCE_TYPE },
183     { RINGTONE_COLUMN_ALARM_TONE_TYPE },
184     { RINGTONE_COLUMN_ALARM_TONE_SOURCE_TYPE },
185 };
186 
DumpDataShareValueBucket(const std::vector<string> & tabFields,const DataShareValuesBucket & value)187 void RingtoneDataShareExtension::DumpDataShareValueBucket(const std::vector<string> &tabFields,
188     const DataShareValuesBucket &value)
189 {
190     bool isValid = false;
191     for (auto tab : tabFields) {
192         auto valueObject = value.Get(tab, isValid);
193         if (!isValid) {
194             RINGTONE_INFO_LOG("not set field: %{public}s", tab.c_str());
195             continue;
196         }
197 
198         if (std::get_if<std::vector<uint8_t>>(&(valueObject.value))) {
199             auto value = static_cast<std::vector<uint8_t>>(valueObject);
200             RINGTONE_INFO_LOG("field: %{public}s, value=%{public}s",
201                 tab.c_str(), value.data());
202         } else if (std::get_if<int64_t>(&(valueObject.value))) {
203             auto value = static_cast<int64_t>(valueObject);
204             RINGTONE_INFO_LOG("field: %{public}s, value=%{public}" PRId64,
205                 tab.c_str(), value);
206         } else if (std::get_if<std::string>(&(valueObject.value))) {
207             auto value = static_cast<std::string>(valueObject);
208             RINGTONE_INFO_LOG("field: %{public}s, value=%{public}s",
209                 tab.c_str(), value.c_str());
210         } else if (std::get_if<bool>(&(valueObject.value))) {
211             auto value = static_cast<bool>(valueObject);
212             RINGTONE_INFO_LOG("field: %{public}s, value=%{public}d",
213                 tab.c_str(), value);
214         } else if (std::get_if<double>(&(valueObject.value))) {
215             auto value = static_cast<double>(valueObject);
216             RINGTONE_INFO_LOG("field: %{public}s, value=%{public}lf",
217                 tab.c_str(), value);
218         } else {
219             RINGTONE_INFO_LOG("unkown field: %{public}s type", tab.c_str());
220         }
221     }
222 }
223 
Insert(const Uri & uri,const DataShareValuesBucket & value)224 int RingtoneDataShareExtension::Insert(const Uri &uri, const DataShareValuesBucket &value)
225 {
226     RINGTONE_DEBUG_LOG("entry, uri=%{public}s", uri.ToString().c_str());
227 
228     DumpDataShareValueBucket(g_ringToneTableFields, value);
229 
230     int err = UriValidCheck(uri);
231     if (err != Media::E_OK) {
232         return err;
233     }
234     RingtoneDataCommand cmd(uri, RINGTONE_TABLE, RingtoneOperationType::INSERT);
235     err = CheckRingtonePerm(cmd, true);
236     if (err < 0) {
237         RINGTONE_ERR_LOG("Check Insert-permission failed, errCode: %{public}d", err);
238         return err;
239     }
240 
241     auto ret = RingtoneDataManager::GetInstance()->Insert(cmd, value);
242     return ret;
243 }
244 
Update(const Uri & uri,const DataSharePredicates & predicates,const DataShareValuesBucket & value)245 int RingtoneDataShareExtension::Update(const Uri &uri, const DataSharePredicates &predicates,
246     const DataShareValuesBucket &value)
247 {
248     RINGTONE_DEBUG_LOG("entry, uri=%{public}s", uri.ToString().c_str());
249     RINGTONE_DEBUG_LOG("WhereClause=%{public}s", predicates.GetWhereClause().c_str());
250 
251     int err = UriValidCheck(uri);
252     if (err != Media::E_OK) {
253         return err;
254     }
255     RingtoneDataCommand cmd(uri, RINGTONE_TABLE, RingtoneOperationType::UPDATE);
256     err = CheckRingtonePerm(cmd, false);
257     if (err < 0) {
258         RINGTONE_ERR_LOG("Check Update-permission failed, errCode: %{public}d", err);
259         return err;
260     }
261 
262     return RingtoneDataManager::GetInstance()->Update(cmd, value, predicates);
263 }
264 
Delete(const Uri & uri,const DataSharePredicates & predicates)265 int RingtoneDataShareExtension::Delete(const Uri &uri, const DataSharePredicates &predicates)
266 {
267     RINGTONE_DEBUG_LOG("entry, uri=%{public}s", uri.ToString().c_str());
268 
269     int err = UriValidCheck(uri);
270     if (err != Media::E_OK) {
271         return err;
272     }
273     RingtoneDataCommand cmd(uri, RINGTONE_TABLE, RingtoneOperationType::DELETE);
274     err = CheckRingtonePerm(cmd, true);
275     if (err < 0) {
276         RINGTONE_ERR_LOG("Check Delete-permission failed, errCode: %{public}d", err);
277         return err;
278     }
279 
280     return RingtoneDataManager::GetInstance()->Delete(cmd, predicates);
281 }
282 
Query(const Uri & uri,const DataSharePredicates & predicates,vector<string> & columns,DatashareBusinessError & businessError)283 shared_ptr<DataShareResultSet> RingtoneDataShareExtension::Query(const Uri &uri,
284     const DataSharePredicates &predicates, vector<string> &columns, DatashareBusinessError &businessError)
285 {
286     RINGTONE_DEBUG_LOG("entry, uri=%{public}s", uri.ToString().c_str());
287     int err = UriValidCheck(uri);
288     if (err != Media::E_OK) {
289         return nullptr;
290     }
291     RingtoneDataCommand cmd(uri, RINGTONE_TABLE, RingtoneOperationType::QUERY);
292     err = CheckRingtonePerm(cmd, false);
293     if (err < 0) {
294         businessError.SetCode(err);
295         RINGTONE_ERR_LOG("Check Query-permission failed, errCode: %{public}d", err);
296         return nullptr;
297     }
298 
299     int errCode = businessError.GetCode();
300     auto queryResultSet = RingtoneDataManager::GetInstance()->Query(cmd, columns, predicates, errCode);
301     businessError.SetCode(to_string(errCode));
302     if (queryResultSet == nullptr) {
303         RINGTONE_ERR_LOG("queryResultSet is nullptr! errCode: %{public}d", errCode);
304         return nullptr;
305     }
306     shared_ptr<DataShareResultSet> resultSet = make_shared<DataShareResultSet>(queryResultSet);
307     return resultSet;
308 }
309 
OpenFile(const Uri & uri,const string & mode)310 int RingtoneDataShareExtension::OpenFile(const Uri &uri, const string &mode)
311 {
312     RINGTONE_DEBUG_LOG("entry, uri=%{public}s, mode=%{public}s",
313         uri.ToString().c_str(), mode.c_str());
314 
315     int err = UriValidCheck(uri);
316     if (err != Media::E_OK) {
317         return err;
318     }
319     RingtoneDataCommand cmd(uri, RINGTONE_TABLE, RingtoneOperationType::OPEN);
320 
321     string unifyMode = mode;
322     transform(unifyMode.begin(), unifyMode.end(), unifyMode.begin(), ::tolower);
323 
324     bool isWrite = false;
325     auto iter = find(RINGTONE_OPEN_WRITE_MODE_VECTOR.begin(), RINGTONE_OPEN_WRITE_MODE_VECTOR.end(), unifyMode);
326     if (iter != RINGTONE_OPEN_WRITE_MODE_VECTOR.end()) {
327         isWrite = true;
328     }
329     err = CheckRingtonePerm(cmd, isWrite);
330     if (err == E_PERMISSION_DENIED) {
331         RINGTONE_ERR_LOG("OpenFile denied, errCode: %{public}d", err);
332         return err;
333     }
334     return RingtoneDataManager::GetInstance()->OpenFile(cmd, unifyMode);
335 }
336 
RingtoneScanner()337 void RingtoneDataShareExtension::RingtoneScanner()
338 {
339     RingtoneFileUtils::AccessRingtoneDir();
340     // ringtone scan
341     int32_t errCode;
342     shared_ptr<NativePreferences::Preferences> prefs =
343         NativePreferences::PreferencesHelper::GetPreferences(DFX_COMMON_XML, errCode);
344     if (!prefs) {
345         RINGTONE_ERR_LOG("get preferences error: %{public}d", errCode);
346         return;
347     }
348     int isCompleted = prefs->GetInt(RINGTONE_PARAMETER_SCANNER_COMPLETED_KEY,
349         RINGTONE_PARAMETER_SCANNER_COMPLETED_FALSE);
350     if (!isCompleted) {
351         RingtoneScannerManager::GetInstance()->Start(false);
352         prefs->PutInt(RINGTONE_PARAMETER_SCANNER_COMPLETED_KEY, RINGTONE_PARAMETER_SCANNER_COMPLETED_TRUE);
353         prefs->FlushSync();
354     }
355 }
356 
RingtoneDataShareCreator(const unique_ptr<Runtime> & runtime)357 static DataShare::DataShareExtAbility *RingtoneDataShareCreator(const unique_ptr<Runtime> &runtime)
358 {
359     RINGTONE_DEBUG_LOG("entry");
360     return  RingtoneDataShareExtension::Create(runtime);
361 }
362 
RegisterDataShareCreator()363 __attribute__((constructor)) void RegisterDataShareCreator()
364 {
365     RINGTONE_ERR_LOG("entry");
366     DataShare::DataShareExtAbility::SetCreator(RingtoneDataShareCreator);
367 
368     RINGTONE_ERR_LOG("End");
369 }
370 } // namespace AbilityRuntime
371 } // namespace OHOS
372