• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 
16 #include "medialibrary_facard_operations.h"
17 
18 #include <memory>
19 #include <mutex>
20 #include <string>
21 #include "abs_shared_result_set.h"
22 
23 #include "media_column.h"
24 #include "media_file_uri.h"
25 #include "media_file_utils.h"
26 #include "media_log.h"
27 #include "medialibrary_errno.h"
28 #include "medialibrary_object_utils.h"
29 #include "medialibrary_rdbstore.h"
30 #include "rdb_predicates.h"
31 #include "result_set_utils.h"
32 #include "value_object.h"
33 #include "values_bucket.h"
34 #include "datashare_helper.h"
35 #include "medialibrary_data_manager.h"
36 #include "media_facard_photos_column.h"
37 #include "result_set_utils.h"
38 #include "ability_manager_client.h"
39 #include "application_context.h"
40 #include "resource_type.h"
41 #include "ffrt.h"
42 #include "ffrt_inner.h"
43 
44 using namespace OHOS::DataShare;
45 using ChangeType = OHOS::DataShare::DataShareObserver::ChangeType;
46 using namespace std;
47 using namespace OHOS::NativeRdb;
48 
49 namespace OHOS {
50 namespace Media {
51 std::mutex MediaLibraryFaCardOperations::mutex_;
52 const string MEDIA_LIBRARY_PROXY_URI = "datashareproxy://com.ohos.medialibrary.medialibrarydata";
53 static std::map<std::string, std::vector<std::shared_ptr<CardAssetUriObserver>>> formAssetObserversMap;
54 const string CLOUD_SYNC_PROXY_URI = "datashareproxy://com.huawei.hmos.clouddrive/sync_switch";
55 static std::map<std::string, std::vector<sptr<FaCloudSyncSwitchObserver>>> formCloudSyncObserversMap;
56 static std::map<ChangeType, int> changeTypeMap = {
57     { ChangeType::INSERT, 0 },
58     { ChangeType::DELETE, 1 },
59     { ChangeType::UPDATE, 2 },
60     { ChangeType::OTHER, 3 },
61     { ChangeType::INVAILD, 4 },
62 };
63 
64 bool CardAssetUriObserver::isTaskPosted = false;
65 std::mutex CardAssetUriObserver::mtx;
66 std::unordered_set<
67     CardAssetUriObserver::AssetChangeInfo,
68     CardAssetUriObserver::AssetChangeInfoHash> CardAssetUriObserver::assetChanges;
69 
70 bool FaCloudSyncSwitchObserver::isTaskPosted = false;
71 std::mutex FaCloudSyncSwitchObserver::mtx;
72 std::unordered_set<
73     FaCloudSyncSwitchObserver::CloudSyncChangeInfo,
74     FaCloudSyncSwitchObserver::CloudSyncChangeInfoHash> FaCloudSyncSwitchObserver::cloudSyncChanges;
75 // LCOV_EXCL_START
GetUris()76 std::map<std::string, std::vector<std::string>> MediaLibraryFaCardOperations::GetUris()
77 {
78     lock_guard<mutex> lock(mutex_);
79     MediaLibraryCommand queryFaCardCmd(OperationObject::TAB_FACARD_PHOTO, OperationType::QUERY);
80     std::map<std::string, std::vector<std::string>> resultMap;
81     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
82     if (uniStore == nullptr) {
83         MEDIA_ERR_LOG("UniStore is nullptr");
84         return resultMap;
85     }
86     vector<string> columns = {
87         TabFaCardPhotosColumn::FACARD_PHOTOS_ASSET_URI,
88         TabFaCardPhotosColumn::FACARD_PHOTOS_FORM_ID
89     };
90     auto queryResult = uniStore->Query(queryFaCardCmd, columns);
91     if (queryResult == nullptr) {
92         MEDIA_ERR_LOG("Failed to query assetUris!");
93         return resultMap;
94     }
95     while (queryResult->GoToNextRow() == NativeRdb::E_OK) {
96         string assetUri = GetStringVal(TabFaCardPhotosColumn::FACARD_PHOTOS_ASSET_URI, queryResult);
97         string formId = GetStringVal(TabFaCardPhotosColumn::FACARD_PHOTOS_FORM_ID, queryResult);
98         resultMap[formId].push_back(assetUri);
99     }
100     return resultMap;
101 }
102 
GetStringObject(MediaLibraryCommand & cmd,const string & columnName)103 static string GetStringObject(MediaLibraryCommand &cmd, const string &columnName)
104 {
105     ValueObject valueObject;
106     ValuesBucket values = cmd.GetValueBucket();
107     string value;
108     if (values.GetObject(columnName, valueObject)) {
109         valueObject.GetString(value);
110         return value;
111     }
112     return "";
113 }
114 
PostAssetChangeTask()115 void CardAssetUriObserver::PostAssetChangeTask()
116 {
117     if (!CardAssetUriObserver::isTaskPosted) {
118         CardAssetUriObserver::isTaskPosted = true;
119         thread([]() {
120             MEDIA_DEBUG_LOG("CardAssetUriObserver task start");
121             const int DELAY_MILLISECONDS = 2000;
122             this_thread::sleep_for(chrono::milliseconds(DELAY_MILLISECONDS));
123             std::lock_guard<std::mutex> lock(CardAssetUriObserver::mtx);
124             std::vector<std::string> assetChangeUris;
125             std::vector<int> assetChangeTypes;
126             for (const auto& change : CardAssetUriObserver::assetChanges) {
127                 assetChangeUris.push_back(change.assetChangeUri);
128                 MEDIA_DEBUG_LOG("change.assetChangeUri = %{public}s", change.assetChangeUri.c_str());
129                 assetChangeTypes.push_back(change.assetChangeType);
130                 MEDIA_DEBUG_LOG("change.assetChangeType = %{public}d", change.assetChangeType);
131             }
132             AAFwk::Want want;
133             want.SetElementName("com.huawei.hmos.photos", "FACardServiceAbility");
134             want.SetParam("assetChangeUris", assetChangeUris);
135             want.SetParam("assetChangeTypes", assetChangeTypes);
136             int32_t userId = -1;
137             auto result = AAFwk::AbilityManagerClient::GetInstance()->StartExtensionAbility(
138                 want, nullptr, userId, AppExecFwk::ExtensionAbilityType::SERVICE);
139             CardAssetUriObserver::assetChanges.clear();
140             CardAssetUriObserver::isTaskPosted = false;
141             MEDIA_DEBUG_LOG("CardAssetUriObserver task end");
142         }).detach();
143     }
144 }
145 
PostAssetChangeTask()146 void FaCloudSyncSwitchObserver::PostAssetChangeTask()
147 {
148     if (!FaCloudSyncSwitchObserver::isTaskPosted) {
149         FaCloudSyncSwitchObserver::isTaskPosted = true;
150         thread([]() {
151             MEDIA_INFO_LOG("FaCloudSyncSwitchObserver task start");
152             const int DELAY_MILLISECONDS = 2000;
153             this_thread::sleep_for(chrono::milliseconds(DELAY_MILLISECONDS));
154             std::lock_guard<std::mutex> lock(FaCloudSyncSwitchObserver::mtx);
155             std::vector<std::string> assetChangeUris;
156             std::vector<int> assetChangeTypes;
157             for (const auto& change : FaCloudSyncSwitchObserver::cloudSyncChanges) {
158                 assetChangeUris.push_back(change.cloudSyncChangeUri);
159                 assetChangeTypes.push_back(change.cloudSyncChangeType);
160                 MEDIA_INFO_LOG("change.assetChangeUri = %{public}s, change.assetChangeType = %{public}d",
161                     change.cloudSyncChangeUri.c_str(), change.cloudSyncChangeType);
162             }
163             AAFwk::Want want;
164             want.SetElementName("com.huawei.hmos.photos", "FACardServiceAbility");
165             want.SetParam("assetChangeUris", assetChangeUris);
166             want.SetParam("assetChangeTypes", assetChangeTypes);
167             int32_t userId = -1;
168             auto result = AAFwk::AbilityManagerClient::GetInstance()->StartExtensionAbility(
169                 want, nullptr, userId, AppExecFwk::ExtensionAbilityType::SERVICE);
170             FaCloudSyncSwitchObserver::cloudSyncChanges.clear();
171             FaCloudSyncSwitchObserver::isTaskPosted = false;
172             MEDIA_INFO_LOG("FaCloudSyncSwitchObserver task end");
173         }).detach();
174     }
175 }
176 
OnChange(const ChangeInfo & changeInfo)177 void CardAssetUriObserver::OnChange(const ChangeInfo &changeInfo)
178 {
179     if (changeTypeMap.find(changeInfo.changeType_) != changeTypeMap.end()) {
180         std::lock_guard<std::mutex> lock(CardAssetUriObserver::mtx);
181         MEDIA_DEBUG_LOG("OnChange assetChangeUri = %{public}s", assetChangeUri.c_str());
182         MEDIA_DEBUG_LOG("OnChange assetChangeType = %{public}d", static_cast<int>(changeInfo.changeType_));
183         CardAssetUriObserver::assetChanges.insert(
184             AssetChangeInfo(assetChangeUri, static_cast<int>(changeInfo.changeType_)));
185 
186         PostAssetChangeTask();
187     }
188 }
189 
OnChange()190 void FaCloudSyncSwitchObserver::OnChange()
191 {
192     std::lock_guard<std::mutex> lock(FaCloudSyncSwitchObserver::mtx);
193     const int CLOUD_SYNC_TYPE = 3;
194     MEDIA_INFO_LOG("OnChange assetChangeUri = %{public}s, assetChangeType = %{public}d", cloudSyncChangeUri.c_str(),
195         static_cast<int>(CLOUD_SYNC_TYPE));
196     FaCloudSyncSwitchObserver::cloudSyncChanges.insert(
197         CloudSyncChangeInfo(cloudSyncChangeUri, static_cast<int>(CLOUD_SYNC_TYPE)));
198 
199     PostAssetChangeTask();
200 }
201 
RegisterObserver(const std::string & formId,const std::string & registerUri)202 void MediaLibraryFaCardOperations::RegisterObserver(const std::string &formId, const std::string &registerUri)
203 {
204     if (formId.empty() || registerUri.empty()) {
205         MEDIA_ERR_LOG("parameter is null");
206         return;
207     }
208     const std::string ASSET_URI_PREFIX = "file://media/";
209     const std::string CLOUD_SYNC_SWITCH_URI_PREFIX = "datashareproxy://";
210     MEDIA_INFO_LOG("registerUri = %{public}s", registerUri.c_str());
211 
212     std::shared_ptr<DataShare::DataShareObserver> observer;
213     sptr<FaCloudSyncSwitchObserver> cloudSyncObserver;
214     if (registerUri.find(ASSET_URI_PREFIX) == 0) {
215         auto cardAssetUriObserver = std::make_shared<CardAssetUriObserver>(registerUri);
216         if (cardAssetUriObserver == nullptr) {
217             return;
218         }
219         MEDIA_DEBUG_LOG("cardAssetUriObserver->uri = %{public}s", cardAssetUriObserver->assetChangeUri.c_str());
220         formAssetObserversMap[formId].push_back(cardAssetUriObserver);
221         observer = std::static_pointer_cast<DataShare::DataShareObserver>(cardAssetUriObserver);
222     } else if (registerUri.find(CLOUD_SYNC_SWITCH_URI_PREFIX) == 0) {
223         sptr<FaCloudSyncSwitchObserver> cloudSwitchObserver(new (std::nothrow) FaCloudSyncSwitchObserver(registerUri));
224         if (cloudSwitchObserver == nullptr) {
225             return;
226         }
227         MEDIA_INFO_LOG("FaCloudSyncuri = %{public}s", cloudSwitchObserver->cloudSyncChangeUri.c_str());
228         formCloudSyncObserversMap[formId].push_back(cloudSwitchObserver);
229         cloudSyncObserver = cloudSwitchObserver;
230     } else {
231         MEDIA_ERR_LOG("registerUri is inValid");
232         return;
233     }
234     Uri notifyUri(registerUri);
235     CreateOptions options;
236     options.enabled_ = true;
237     shared_ptr<DataShare::DataShareHelper> dataShareHelper;
238     if (registerUri.find(ASSET_URI_PREFIX) == 0) {
239         dataShareHelper = DataShare::DataShareHelper::Creator(MEDIA_LIBRARY_PROXY_URI, options);
240         if (dataShareHelper == nullptr || observer == nullptr) {
241             MEDIA_ERR_LOG("dataShareHelper is nullptr");
242             return;
243         }
244         dataShareHelper->RegisterObserverExt(notifyUri, observer, true);
245     } else if (registerUri.find(CLOUD_SYNC_SWITCH_URI_PREFIX) == 0) {
246         dataShareHelper = DataShare::DataShareHelper::Creator(CLOUD_SYNC_PROXY_URI, options);
247         if (dataShareHelper == nullptr || cloudSyncObserver == nullptr) {
248             MEDIA_ERR_LOG("dataShareHelper is nullptr");
249             return;
250         }
251         dataShareHelper->RegisterObserver(notifyUri, cloudSyncObserver);
252     }
253 }
254 
UnregisterObserver(const std::string & formId)255 void MediaLibraryFaCardOperations::UnregisterObserver(const std::string &formId)
256 {
257     if (formId.empty() || formAssetObserversMap.empty()) {
258         MEDIA_ERR_LOG("parameter is null");
259         return;
260     }
261     CreateOptions options;
262     options.enabled_ = true;
263     shared_ptr<DataShare::DataShareHelper> dataShareHelper;
264     dataShareHelper = DataShare::DataShareHelper::Creator(MEDIA_LIBRARY_PROXY_URI, options);
265     if (dataShareHelper == nullptr) {
266         MEDIA_ERR_LOG("dataShareHelper is nullptr");
267         return;
268     }
269     auto itAsset = formAssetObserversMap.find(formId);
270     if (itAsset == formAssetObserversMap.end()) {
271         MEDIA_ERR_LOG("No formAssetObservers found for formId: %{public}s", formId.c_str());
272         return;
273     }
274     const std::vector<std::shared_ptr<CardAssetUriObserver>>& formAssetObservers = itAsset->second;
275     if (formAssetObservers.empty()) {
276         MEDIA_ERR_LOG("formAssetObservers is null");
277         return;
278     }
279     for (const auto& observer : formAssetObservers) {
280         if (!observer || observer->assetChangeUri.empty()) {
281             MEDIA_ERR_LOG("observer->assetChangeUri is null");
282             return;
283         }
284         Uri notifyUri(observer->assetChangeUri);
285         dataShareHelper->UnregisterObserverExt(notifyUri,
286             std::static_pointer_cast<DataShare::DataShareObserver>(observer));
287     }
288     formAssetObserversMap.erase(formId);
289     if (formCloudSyncObserversMap.empty()) {
290         MEDIA_ERR_LOG("formCloudSyncObserversMap is null");
291         return;
292     }
293     dataShareHelper = DataShare::DataShareHelper::Creator(CLOUD_SYNC_PROXY_URI, options);
294     if (dataShareHelper == nullptr) {
295         MEDIA_ERR_LOG("dataShareHelper is nullptr");
296         return;
297     }
298     auto cloudItAsset = formCloudSyncObserversMap.find(formId);
299     if (cloudItAsset == formCloudSyncObserversMap.end()) {
300         MEDIA_ERR_LOG("No formCloudSyncObserversMap found for formId: %{public}s", formId.c_str());
301         return;
302     }
303     const std::vector<sptr<FaCloudSyncSwitchObserver>>& formCloudSyncObservers = cloudItAsset->second;
304     if (formCloudSyncObservers.empty()) {
305         MEDIA_ERR_LOG("formCloudSyncObservers is null");
306         return;
307     }
308     for (const auto& observer : formCloudSyncObservers) {
309         if (!observer || observer->cloudSyncChangeUri.empty()) {
310             MEDIA_ERR_LOG("observer->cloudSyncChangeUri is null");
311             return;
312         }
313         Uri notifyUri(observer->cloudSyncChangeUri);
314         dataShareHelper->UnregisterObserver(notifyUri, observer);
315     }
316     formCloudSyncObserversMap.erase(formId);
317 }
318 
HandleStoreGalleryFormOperation(MediaLibraryCommand & cmd)319 int32_t MediaLibraryFaCardOperations::HandleStoreGalleryFormOperation(MediaLibraryCommand &cmd)
320 {
321     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
322     if (rdbStore == nullptr) {
323         return E_HAS_DB_ERROR;
324     }
325     int64_t outRowId = -1;
326     lock_guard<mutex> lock(mutex_);
327     int32_t errCode = rdbStore->Insert(cmd, outRowId);
328     if (errCode != NativeRdb::E_OK || outRowId < 0) {
329         MEDIA_ERR_LOG("Insert into db failed, errCode = %{public}d", errCode);
330         return E_HAS_DB_ERROR;
331     }
332     string formId = GetStringObject(cmd, TabFaCardPhotosColumn::FACARD_PHOTOS_FORM_ID);
333     MEDIA_DEBUG_LOG("formId = %{public}s", formId.c_str());
334     string assetRegisterUri = GetStringObject(cmd, TabFaCardPhotosColumn::FACARD_PHOTOS_ASSET_URI);
335     MEDIA_DEBUG_LOG("assetRegisterUri = %{public}s", assetRegisterUri.c_str());
336     MediaLibraryFaCardOperations::RegisterObserver(formId, assetRegisterUri);
337     return static_cast<int32_t>(outRowId);
338 }
339 
HandleRemoveGalleryFormOperation(NativeRdb::RdbPredicates & rdbPredicate)340 int32_t MediaLibraryFaCardOperations::HandleRemoveGalleryFormOperation(NativeRdb::RdbPredicates &rdbPredicate)
341 {
342     lock_guard<mutex> lock(mutex_);
343     string formId = rdbPredicate.GetWhereArgs()[0];
344     MediaLibraryFaCardOperations::UnregisterObserver(formId);
345     return MediaLibraryRdbStore::Delete(rdbPredicate);
346 }
347 
InitRegisterObserver()348 void MediaLibraryFaCardOperations::InitRegisterObserver()
349 {
350     MEDIA_INFO_LOG("enter InitRegisterObserver");
351     const int INIT_NUM = 0;
352     const int END_NUM = 10;
353     const int DELAY_NUM = 100;
354     int cnt = INIT_NUM;
355     std::map<std::string, std::vector<std::string>> urisMap = MediaLibraryFaCardOperations::GetUris();
356     for (const auto& pair : urisMap) {
357         const std::string& formId = pair.first;
358         MEDIA_DEBUG_LOG("InitRegisterObserver formId = %{public}s", formId.c_str());
359         const std::vector<std::string>& uris = pair.second;
360         MEDIA_DEBUG_LOG("InitRegisterObserver uris.size = %{public}zu", uris.size());
361         for (const std::string& uri : uris) {
362             MediaLibraryFaCardOperations::RegisterObserver(formId, uri);
363             MEDIA_DEBUG_LOG("InitRegisterObserver uri = %{public}s", uri.c_str());
364             cnt ++;
365             if (cnt == END_NUM) {
366                 cnt = INIT_NUM;
367                 std::this_thread::sleep_for(std::chrono::milliseconds(DELAY_NUM));
368             }
369         }
370     }
371 }
372 
InitFaCard()373 void MediaLibraryFaCardOperations::InitFaCard()
374 {
375     ffrt::submit([]() { MediaLibraryFaCardOperations::InitRegisterObserver(); });
376 }
377 // LCOV_EXCL_STOP
378 } // namespace Media
379 } // namespace OHOS