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
42 using namespace OHOS::DataShare;
43 using ChangeType = OHOS::DataShare::DataShareObserver::ChangeType;
44 using namespace std;
45 using namespace OHOS::NativeRdb;
46
47 namespace OHOS {
48 namespace Media {
49 std::mutex MediaLibraryFaCardOperations::mutex_;
50 const string MEDIA_LIBRARY_PROXY_URI = "datashareproxy://com.ohos.medialibrary.medialibrarydata";
51 static std::map<std::string, std::vector<std::shared_ptr<CardAssetUriObserver>>> formAssetObserversMap;
52 static std::map<ChangeType, int> changeTypeMap = {
53 { ChangeType::INSERT, 0 },
54 { ChangeType::DELETE, 1 },
55 { ChangeType::UPDATE, 2 },
56 { ChangeType::OTHER, 3 },
57 { ChangeType::INVAILD, 4 },
58 };
59
60 bool CardAssetUriObserver::isTaskPosted = false;
61 std::shared_ptr<AppExecFwk::EventHandler> CardAssetUriObserver::deviceHandler_ =
62 std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::Create("MediaLibraryFacard"));
63 std::mutex CardAssetUriObserver::mtx;
64 std::unordered_set<
65 CardAssetUriObserver::AssetChangeInfo,
66 CardAssetUriObserver::AssetChangeInfoHash> CardAssetUriObserver::assetChanges;
67
GetUris()68 std::map<std::string, std::vector<std::string>> MediaLibraryFaCardOperations::GetUris()
69 {
70 lock_guard<mutex> lock(mutex_);
71 MediaLibraryCommand queryFaCardCmd(OperationObject::TAB_FACARD_PHOTO, OperationType::QUERY);
72 std::map<std::string, std::vector<std::string>> resultMap;
73 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
74 if (uniStore == nullptr) {
75 MEDIA_ERR_LOG("UniStore is nullptr");
76 return resultMap;
77 }
78 vector<string> columns = {
79 TabFaCardPhotosColumn::FACARD_PHOTOS_ASSET_URI,
80 TabFaCardPhotosColumn::FACARD_PHOTOS_FORM_ID
81 };
82 auto queryResult = uniStore->Query(queryFaCardCmd, columns);
83 if (queryResult == nullptr) {
84 MEDIA_ERR_LOG("Failed to query assetUris!");
85 return resultMap;
86 }
87 while (queryResult->GoToNextRow() == NativeRdb::E_OK) {
88 string assetUri = GetStringVal(TabFaCardPhotosColumn::FACARD_PHOTOS_ASSET_URI, queryResult);
89 string formId = GetStringVal(TabFaCardPhotosColumn::FACARD_PHOTOS_FORM_ID, queryResult);
90 resultMap[formId].push_back(assetUri);
91 }
92 return resultMap;
93 }
94
GetStringObject(MediaLibraryCommand & cmd,const string & columnName)95 static string GetStringObject(MediaLibraryCommand &cmd, const string &columnName)
96 {
97 ValueObject valueObject;
98 ValuesBucket values = cmd.GetValueBucket();
99 string value;
100 if (values.GetObject(columnName, valueObject)) {
101 valueObject.GetString(value);
102 return value;
103 }
104 return "";
105 }
106
PostAssetChangeTask()107 void CardAssetUriObserver::PostAssetChangeTask()
108 {
109 if (!CardAssetUriObserver::isTaskPosted) {
110 CardAssetUriObserver::isTaskPosted = true;
111 const int DELAY_MILLISECONDS = 2000;
112 CardAssetUriObserver::deviceHandler_->PostTask([this]() {
113 std::lock_guard<std::mutex> lock(CardAssetUriObserver::mtx);
114 std::vector<std::string> assetChangeUris;
115 std::vector<int> assetChangeTypes;
116 for (const auto& change : CardAssetUriObserver::assetChanges) {
117 assetChangeUris.push_back(change.assetChangeUri);
118 MEDIA_DEBUG_LOG("change.assetChangeUri = %{public}s", change.assetChangeUri.c_str());
119 assetChangeTypes.push_back(change.assetChangeType);
120 MEDIA_DEBUG_LOG("change.assetChangeType = %{public}d", change.assetChangeType);
121 }
122 AAFwk::Want want;
123 want.SetElementName("com.huawei.hmos.photos", "FACardServiceAbility");
124 want.SetParam("assetChangeUris", assetChangeUris);
125 want.SetParam("assetChangeTypes", assetChangeTypes);
126 int32_t userId = -1;
127 auto result = AAFwk::AbilityManagerClient::GetInstance()->StartExtensionAbility(
128 want, nullptr, userId, AppExecFwk::ExtensionAbilityType::SERVICE);
129 CardAssetUriObserver::assetChanges.clear();
130 CardAssetUriObserver::isTaskPosted = false;
131 }, "StartExtensionAbility", DELAY_MILLISECONDS);
132 }
133 }
134
OnChange(const ChangeInfo & changeInfo)135 void CardAssetUriObserver::OnChange(const ChangeInfo &changeInfo)
136 {
137 if (changeTypeMap.find(changeInfo.changeType_) != changeTypeMap.end()) {
138 std::lock_guard<std::mutex> lock(CardAssetUriObserver::mtx);
139 MEDIA_DEBUG_LOG("OnChange assetChangeUri = %{public}s", assetChangeUri.c_str());
140 MEDIA_DEBUG_LOG("OnChange assetChangeType = %{public}d", static_cast<int>(changeInfo.changeType_));
141 CardAssetUriObserver::assetChanges.insert(
142 AssetChangeInfo(assetChangeUri, static_cast<int>(changeInfo.changeType_)));
143
144 PostAssetChangeTask();
145 }
146 }
147
RegisterObserver(const std::string & formId,const std::string & registerUri)148 void MediaLibraryFaCardOperations::RegisterObserver(const std::string &formId, const std::string ®isterUri)
149 {
150 const std::string ASSET_URI_PREFIX = "file://media/";
151 const std::string CLOUD_SYNC_SWITCH_URI_PREFIX = "datashareproxy://";
152 MEDIA_DEBUG_LOG("registerUri = %{public}s", registerUri.c_str());
153
154 std::shared_ptr<DataShare::DataShareObserver> observer;
155 if (registerUri.find(ASSET_URI_PREFIX) == 0 || registerUri.find(CLOUD_SYNC_SWITCH_URI_PREFIX) == 0) {
156 auto cardAssetUriObserver = std::make_shared<CardAssetUriObserver>(registerUri);
157 MEDIA_DEBUG_LOG("cardAssetUriObserver->uri = %{public}s", cardAssetUriObserver->assetChangeUri.c_str());
158 formAssetObserversMap[formId].push_back(cardAssetUriObserver);
159 observer = std::static_pointer_cast<DataShare::DataShareObserver>(cardAssetUriObserver);
160 } else {
161 MEDIA_ERR_LOG("registerUri is inValid");
162 return;
163 }
164 Uri notifyUri(registerUri);
165 CreateOptions options;
166 options.enabled_ = true;
167 shared_ptr<DataShare::DataShareHelper> dataShareHelper =
168 DataShare::DataShareHelper::Creator(MEDIA_LIBRARY_PROXY_URI, options);
169 if (dataShareHelper == nullptr) {
170 MEDIA_ERR_LOG("dataShareHelper is nullptr");
171 return;
172 }
173 MEDIA_DEBUG_LOG("notifyUri = %{public}s", notifyUri.ToString().c_str());
174 dataShareHelper->RegisterObserverExt(notifyUri, observer, true);
175 }
176
UnregisterObserver(const std::string & formId)177 void MediaLibraryFaCardOperations::UnregisterObserver(const std::string &formId)
178 {
179 CreateOptions options;
180 options.enabled_ = true;
181 shared_ptr<DataShare::DataShareHelper> dataShareHelper =
182 DataShare::DataShareHelper::Creator(MEDIA_LIBRARY_PROXY_URI, options);
183 if (dataShareHelper == nullptr) {
184 MEDIA_ERR_LOG("dataShareHelper is nullptr");
185 return;
186 }
187 auto itAsset = formAssetObserversMap.find(formId);
188 if (itAsset == formAssetObserversMap.end()) {
189 MEDIA_ERR_LOG("No formAssetObservers found for formId: %{public}s", formId.c_str());
190 return;
191 }
192 const std::vector<std::shared_ptr<CardAssetUriObserver>>& formAssetObservers = itAsset->second;
193 for (const auto& observer : formAssetObservers) {
194 Uri notifyUri(observer->assetChangeUri);
195 dataShareHelper->UnregisterObserverExt(notifyUri,
196 std::static_pointer_cast<DataShare::DataShareObserver>(observer));
197 }
198 formAssetObserversMap.erase(formId);
199 }
200
HandleStoreGalleryFormOperation(MediaLibraryCommand & cmd)201 int32_t MediaLibraryFaCardOperations::HandleStoreGalleryFormOperation(MediaLibraryCommand &cmd)
202 {
203 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
204 if (rdbStore == nullptr) {
205 return E_HAS_DB_ERROR;
206 }
207 int64_t outRowId = -1;
208 lock_guard<mutex> lock(mutex_);
209 int32_t errCode = rdbStore->Insert(cmd, outRowId);
210 if (errCode != NativeRdb::E_OK || outRowId < 0) {
211 MEDIA_ERR_LOG("Insert into db failed, errCode = %{public}d", errCode);
212 return E_HAS_DB_ERROR;
213 }
214 string formId = GetStringObject(cmd, TabFaCardPhotosColumn::FACARD_PHOTOS_FORM_ID);
215 MEDIA_DEBUG_LOG("formId = %{public}s", formId.c_str());
216 string assetRegisterUri = GetStringObject(cmd, TabFaCardPhotosColumn::FACARD_PHOTOS_ASSET_URI);
217 MEDIA_DEBUG_LOG("assetRegisterUri = %{public}s", assetRegisterUri.c_str());
218 MediaLibraryFaCardOperations::RegisterObserver(formId, assetRegisterUri);
219 return static_cast<int32_t>(outRowId);
220 }
221
HandleRemoveGalleryFormOperation(NativeRdb::RdbPredicates & rdbPredicate)222 int32_t MediaLibraryFaCardOperations::HandleRemoveGalleryFormOperation(NativeRdb::RdbPredicates &rdbPredicate)
223 {
224 lock_guard<mutex> lock(mutex_);
225 string formId = rdbPredicate.GetWhereArgs()[0];
226 MediaLibraryFaCardOperations::UnregisterObserver(formId);
227 return MediaLibraryRdbStore::Delete(rdbPredicate);
228 }
229 } // namespace Media
230 } // namespace OHOS