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