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