1 /*
2  * Copyright (c) 2023 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 "VisionOperation"
16 
17 #include <thread>
18 #include "media_analysis_helper.h"
19 #include "media_log.h"
20 #include "medialibrary_data_manager.h"
21 #include "medialibrary_db_const.h"
22 #include "medialibrary_errno.h"
23 #include "medialibrary_rdb_utils.h"
24 #include "medialibrary_unistore_manager.h"
25 #include "medialibrary_vision_operations.h"
26 #include "medialibrary_rdb_transaction.h"
27 #include "medialibrary_rdbstore.h"
28 #include "rdb_utils.h"
29 #include "vision_aesthetics_score_column.h"
30 #include "vision_column.h"
31 #include "vision_total_column.h"
32 #include "vision_recommendation_column.h"
33 
34 using namespace std;
35 using namespace OHOS::NativeRdb;
36 using Uri = OHOS::Uri;
37 using namespace OHOS::DataShare;
38 using namespace OHOS::RdbDataShareAdapter;
39 
40 namespace OHOS {
41 namespace Media {
42 static vector<int> NEED_UPDATE_TYPE = {
43     PhotoAlbumSubType::CLASSIFY, PhotoAlbumSubType::PORTRAIT
44 };
InsertOperation(MediaLibraryCommand & cmd)45 int32_t MediaLibraryVisionOperations::InsertOperation(MediaLibraryCommand &cmd)
46 {
47     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
48     if (rdbStore == nullptr) {
49         return E_HAS_DB_ERROR;
50     }
51     int64_t outRowId = -1;
52     int32_t errCode = rdbStore->Insert(cmd, outRowId);
53     if (errCode != NativeRdb::E_OK || outRowId < 0) {
54         MEDIA_ERR_LOG("Insert into db failed, errCode = %{public}d", errCode);
55         return E_HAS_DB_ERROR;
56     }
57     return static_cast<int32_t>(outRowId);
58 }
59 
UpdateOperation(MediaLibraryCommand & cmd)60 int32_t MediaLibraryVisionOperations::UpdateOperation(MediaLibraryCommand &cmd)
61 {
62     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
63     if (rdbStore == nullptr) {
64         return E_HAS_DB_ERROR;
65     }
66     int32_t updateRows = -1;
67     int32_t errCode = rdbStore->Update(cmd, updateRows);
68     if (errCode != NativeRdb::E_OK || updateRows < 0) {
69         MEDIA_ERR_LOG("Update db failed, errCode = %{public}d", errCode);
70         return E_HAS_DB_ERROR;
71     }
72     return static_cast<int32_t>(updateRows);
73 }
74 
DeleteOperation(MediaLibraryCommand & cmd)75 int32_t MediaLibraryVisionOperations::DeleteOperation(MediaLibraryCommand &cmd)
76 {
77     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
78     if (rdbStore == nullptr) {
79         return E_HAS_DB_ERROR;
80     }
81     int32_t deleteRows = -1;
82     int32_t errCode = rdbStore->Delete(cmd, deleteRows);
83     if (errCode != NativeRdb::E_OK || deleteRows < 0) {
84         MEDIA_ERR_LOG("Delete db failed, errCode = %{public}d", errCode);
85         return E_HAS_DB_ERROR;
86     }
87     return static_cast<int32_t>(deleteRows);
88 }
89 
QueryOperation(MediaLibraryCommand & cmd,const std::vector<std::string> & columns)90 shared_ptr<NativeRdb::ResultSet> MediaLibraryVisionOperations::QueryOperation(MediaLibraryCommand &cmd,
91     const std::vector<std::string> &columns)
92 {
93     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
94     if (rdbStore == nullptr) {
95         return nullptr;
96     }
97     return rdbStore->Query(cmd, columns);
98 }
99 
UpdateAnalysisTotal(string & uriTotal,string & selection,const string & columnName)100 static int32_t UpdateAnalysisTotal(string &uriTotal, string &selection, const string &columnName)
101 {
102     Uri uri = Uri(uriTotal);
103     DataSharePredicates predicate;
104     predicate.SetWhereClause(selection);
105     MediaLibraryCommand cmdTotal(uri);
106     DataShareValuesBucket valueBucket;
107     valueBucket.Put(STATUS, 0);
108     valueBucket.Put(columnName, 0);
109     return MediaLibraryDataManager::GetInstance()->Update(cmdTotal, valueBucket, predicate);
110 }
111 
DeleteFromVisionTables(string & fileId,string & selectionTotal,const string & columnTotal,const string & tableName)112 static int32_t DeleteFromVisionTables(string &fileId, string &selectionTotal,
113     const string &columnTotal, const string &tableName)
114 {
115     string uriTotal = MEDIALIBRARY_DATA_URI + "/" + PAH_ANA_TOTAL;
116     int32_t updateRows = UpdateAnalysisTotal(uriTotal, selectionTotal, columnTotal);
117     MEDIA_DEBUG_LOG("Update %{public}d rows at total for edit commit to %{public}s", updateRows, columnTotal.c_str());
118     if (updateRows <= 0) {
119         return updateRows;
120     }
121 
122     string uriTable = MEDIALIBRARY_DATA_URI + "/" + tableName;
123     Uri uri = Uri(uriTable);
124     DataSharePredicates predicate;
125     predicate.EqualTo(FILE_ID, fileId);
126     MediaLibraryCommand cmdTable(uri);
127     return MediaLibraryDataManager::GetInstance()->Delete(cmdTable, predicate);
128 }
129 
DeleteFromVisionTablesForVideo(string & fileId,const string & tableName)130 static int32_t DeleteFromVisionTablesForVideo(string &fileId, const string &tableName)
131 {
132     string uriTable = MEDIALIBRARY_DATA_URI + "/" + tableName;
133     Uri uri = Uri(uriTable);
134     DataSharePredicates predicate;
135     predicate.EqualTo(FILE_ID, fileId);
136     MediaLibraryCommand cmdTable(uri);
137     return MediaLibraryDataManager::GetInstance()->Delete(cmdTable, predicate);
138 }
139 
UpdateVisionTableForEdit(AsyncTaskData * taskData)140 static void UpdateVisionTableForEdit(AsyncTaskData *taskData)
141 {
142     if (taskData == nullptr) {
143         MEDIA_ERR_LOG("taskData is nullptr");
144         return;
145     }
146     UpdateVisionAsyncTaskData* data = static_cast<UpdateVisionAsyncTaskData*>(taskData);
147     if (data == nullptr) {
148         MEDIA_ERR_LOG("UpdateVisionAsyncTaskData is nullptr");
149         return;
150     }
151     string fileId = to_string(data->fileId_);
152 
153     string selectionTotal = FILE_ID + " = " + fileId + " AND " + LABEL + " = 1";
154     DeleteFromVisionTables(fileId, selectionTotal, LABEL, PAH_ANA_LABEL);
155     DeleteFromVisionTablesForVideo(fileId, PAH_ANA_VIDEO_LABEL);
156 
157     selectionTotal = FILE_ID + " = " + fileId + " AND " + AESTHETICS_SCORE + " = 1";
158     DeleteFromVisionTables(fileId, selectionTotal, AESTHETICS_SCORE, PAH_ANA_ATTS);
159 
160     selectionTotal = FILE_ID + " = " + fileId + " AND " + OCR + " = 1";
161     DeleteFromVisionTables(fileId, selectionTotal, OCR, PAH_ANA_OCR);
162 
163     selectionTotal = FILE_ID + " = " + fileId + " AND " + SALIENCY + " = 1";
164     DeleteFromVisionTables(fileId, selectionTotal, SALIENCY, PAH_ANA_SALIENCY);
165 
166     selectionTotal = FILE_ID + " = " + fileId + " AND " + FACE + " IN (-2, 1, 2, 3, 4)";
167     DeleteFromVisionTables(fileId, selectionTotal, FACE, PAH_ANA_FACE);
168 
169     selectionTotal = FILE_ID + " = " + fileId + " AND " + OBJECT + " = 1";
170     DeleteFromVisionTables(fileId, selectionTotal, OBJECT, PAH_ANA_OBJECT);
171 
172     selectionTotal = FILE_ID + " = " + fileId + " AND " + RECOMMENDATION + " = 1";
173     DeleteFromVisionTables(fileId, selectionTotal, RECOMMENDATION, PAH_ANA_RECOMMENDATION);
174 
175     selectionTotal = FILE_ID + " = " + fileId + " AND " + SEGMENTATION + " = 1";
176     DeleteFromVisionTables(fileId, selectionTotal, SEGMENTATION, PAH_ANA_SEGMENTATION);
177 
178     selectionTotal = FILE_ID + " = " + fileId + " AND " + HEAD + " = 1";
179     DeleteFromVisionTables(fileId, selectionTotal, HEAD, PAH_ANA_HEAD);
180 
181     selectionTotal = FILE_ID + " = " + fileId + " AND " + POSE + " = 1";
182     DeleteFromVisionTables(fileId, selectionTotal, POSE, PAH_ANA_POSE);
183 
184     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
185     if (rdbStore == nullptr) {
186         MEDIA_ERR_LOG("Can not get rdbstore");
187         return;
188     }
189     MediaLibraryRdbUtils::UpdateAnalysisAlbumByFile(rdbStore, {fileId}, NEED_UPDATE_TYPE);
190 }
191 
EditCommitOperation(MediaLibraryCommand & cmd)192 int32_t MediaLibraryVisionOperations::EditCommitOperation(MediaLibraryCommand &cmd)
193 {
194     if (cmd.GetOprnObject() != OperationObject::FILESYSTEM_PHOTO) {
195         return E_SUCCESS;
196     }
197     const ValuesBucket &values = cmd.GetValueBucket();
198     ValueObject valueObject;
199     int32_t fileId;
200     if (values.GetObject(PhotoColumn::MEDIA_ID, valueObject)) {
201         valueObject.GetInt(fileId);
202     } else {
203         return E_HAS_DB_ERROR;
204     }
205 
206     shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
207     if (asyncWorker ==  nullptr) {
208         MEDIA_ERR_LOG("Can not get asyncWorker");
209         return E_ERR;
210     }
211     UpdateVisionAsyncTaskData* taskData = new (std::nothrow) UpdateVisionAsyncTaskData(fileId);
212     if (taskData ==  nullptr) {
213         MEDIA_ERR_LOG("Failed to new taskData");
214         return E_ERR;
215     }
216     shared_ptr<MediaLibraryAsyncTask> updateAsyncTask =
217         make_shared<MediaLibraryAsyncTask>(UpdateVisionTableForEdit, taskData);
218     if (updateAsyncTask != nullptr) {
219         asyncWorker->AddTask(updateAsyncTask, true);
220     } else {
221         MEDIA_ERR_LOG("UpdateAnalysisDataForEdit fail");
222     }
223     return E_SUCCESS;
224 }
225 }
226 }
227