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