• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 "media_file_utils.h"
17 
18 #include <algorithm>
19 
20 #include "data_ability_predicates.h"
21 #include "file_manager_service_def.h"
22 #include "file_manager_service_errno.h"
23 #include "log.h"
24 #include "media_asset.h"
25 #include "media_data_ability_const.h"
26 #include "rdb_errno.h"
27 #include "values_bucket.h"
28 
29 using namespace std;
30 namespace OHOS {
31 namespace FileManagerService {
GetPathFromResult(shared_ptr<NativeRdb::AbsSharedResultSet> result,string & path)32 bool GetPathFromResult(shared_ptr<NativeRdb::AbsSharedResultSet> result, string &path)
33 {
34     int count = 0;
35     result->GetRowCount(count);
36     if (count == RESULTSET_EMPTY) {
37         ERR_LOG("AbsSharedResultSet null");
38         return false;
39     }
40     int32_t columnIndex = 0;
41     GET_COLUMN_INDEX_FROM_NAME(result, Media::MEDIA_DATA_DB_FILE_PATH, columnIndex);
42     result->GoToFirstRow();
43     int ret = result->GetString(columnIndex, path);
44     if (ret != NativeRdb::E_OK) {
45         ERR_LOG("NativeRdb gets path index fail");
46         return false;
47     }
48     GET_COLUMN_INDEX_FROM_NAME(result, Media::MEDIA_DATA_DB_RELATIVE_PATH, columnIndex);
49     string relativePath;
50     ret = result->GetString(columnIndex, relativePath);
51     if (ret != NativeRdb::E_OK) {
52         relativePath = "";
53         DEBUG_LOG("NativeRdb gets relative path is null %{public}d", columnIndex);
54     }
55     // get relative path from absolute path
56     string::size_type pos = path.find_last_of('/');
57     if (pos != string::npos) {
58         path = relativePath + path.substr(pos + 1) + "/";
59     }
60     return true;
61 }
62 
IsNumber(const string & str)63 bool IsNumber(const string &str)
64 {
65     if (str.length() == 0) {
66         ERR_LOG("IsNumber input is empty ");
67         return false;
68     }
69 
70     for (char const &c : str) {
71         if (isdigit(c) == 0) {
72             ERR_LOG("Index is not a number");
73             return false;
74         }
75     }
76 
77     return true;
78 }
79 
GetPathID(const string & uriPath,string & index)80 bool GetPathID(const string &uriPath, string &index)
81 {
82     string::size_type pos = uriPath.find_last_of('/');
83     if (pos == string::npos) {
84         ERR_LOG("invalid uri %{private}s", uriPath.c_str());
85         return false;
86     }
87     index = uriPath.substr(pos + 1);
88     if (!IsNumber(index)) {
89         ERR_LOG("invalid uri %{private}s invalid id %{public}s", uriPath.c_str(), index.c_str());
90         return false;
91     }
92     return true;
93 }
94 
GetMediaType(const string & name)95 int GetMediaType(const string &name)
96 {
97     int mediaType = Media::MediaAsset::GetMediaType(name);
98     if (FILE_MIME_TYPE_MAPS.count(mediaType) == 0) {
99         ERR_LOG("invalid mediaType %{public}d", mediaType);
100         return FILE_MEDIA_TYPE;
101     }
102     return mediaType;
103 }
104 
GetMimeType(const string & name)105 string GetMimeType(const string &name)
106 {
107     int mediaType = GetMediaType(name);
108     if (FILE_MIME_TYPE_MAPS.count(mediaType) == 0) {
109         ERR_LOG("invalid mediaType %{public}d", mediaType);
110         return FILE_MIME_TYPE;
111     }
112     return FILE_MIME_TYPE_MAPS.at(mediaType);
113 }
114 
GetPathFromAlbumPath(const string & albumUri,string & path)115 bool GetPathFromAlbumPath(const string &albumUri, string &path)
116 {
117     string id;
118     if (!GetPathID(albumUri, id)) {
119         ERR_LOG("GetPathID fails");
120         return false;
121     }
122     string selection = Media::MEDIA_DATA_DB_ID + " LIKE ? ";
123     vector<string> selectionArgs = {id};
124     shared_ptr<NativeRdb::AbsSharedResultSet> result = MediaFileUtils::DoQuery(selection, selectionArgs);
125     if (result == nullptr) {
126         ERR_LOG("AbsSharedResultSet null");
127         return false;
128     }
129     return GetPathFromResult(result, path);
130 }
131 
GetType(string type)132 string GetType(string type)
133 {
134     unordered_map<string, int> typeMap = {
135         {"image", Media::MediaType::MEDIA_TYPE_IMAGE},
136         {"video", Media::MediaType::MEDIA_TYPE_VIDEO},
137         {"audio", Media::MediaType::MEDIA_TYPE_AUDIO}
138     };
139     if (typeMap.count(type) == 0) {
140         // type is wrong
141         ERR_LOG("Type %{public}s", type.c_str());
142         return "";
143     }
144     return ToString(typeMap[type]);
145 }
146 
IsFirstLevelUriPath(const string & path)147 bool IsFirstLevelUriPath(const string &path)
148 {
149     // check whether path is first level uri
150     return path == FISRT_LEVEL_ALBUM;
151 }
152 
GetAlbumFromResult(shared_ptr<NativeRdb::AbsSharedResultSet> & result,vector<string> & album)153 bool GetAlbumFromResult(shared_ptr<NativeRdb::AbsSharedResultSet> &result, vector<string> &album)
154 {
155     int count = 0;
156     result->GetRowCount(count);
157     result->GoToFirstRow();
158     int32_t columnIndex;
159     GET_COLUMN_INDEX_FROM_NAME(result, Media::MEDIA_DATA_DB_RELATIVE_PATH, columnIndex);
160     for (int i = 0; i < count; i++) {
161         string path;
162         if (result->GetString(columnIndex, path) != NativeRdb::E_OK) {
163             ERR_LOG("NativeRdb gets path columnIndex fail");
164             return false;
165         }
166         path = MEDIA_ROOT_PATH + "/" + path.substr(0, path.size() - 1);
167         // add into ablum if not in album
168         if (find(album.begin(), album.end(), path) == album.end()) {
169             DEBUG_LOG(" // add into ablum path %{public}s", path.c_str());
170             album.emplace_back(path);
171         }
172         result->GoToNextRow();
173     }
174     return true;
175 }
176 
FindAlbumByType(string type)177 vector<string> FindAlbumByType(string type)
178 {
179     // find out the first level Album
180     // first find out file by type
181     // then get the album
182     string selection = Media::MEDIA_DATA_DB_MEDIA_TYPE + " LIKE ?";
183     vector<string> selectionArgs = {type};
184     shared_ptr<NativeRdb::AbsSharedResultSet> result = MediaFileUtils::DoQuery(selection, selectionArgs);
185     vector<string> album;
186     if (result == nullptr) {
187         ERR_LOG("query album type returns fail");
188         return album;
189     }
190     GetAlbumFromResult(result, album);
191     return album;
192 }
193 
194 /* listfile
195  * ----find "file" type
196  * --------first level view----
197  * --------selection MEDIA_DATA_DB_RELATIVE_PATH == root_path &&
198  * (MEDIA_DATA_DB_MEDIA_TYPE == "file" || MEDIA_DATA_DB_MEDIA_TYPE == "album")
199  * --------other level view ----
200  * --------selection MEDIA_DATA_DB_RELATIVE_PATH == uri.MEDIA_DATA_DB_FILE_PATH &&
201  * (MEDIA_DATA_DB_MEDIA_TYPE == "file" || MEDIA_DATA_DB_MEDIA_TYPE == "album")
202  *
203  * ----find "image"/"audio"/"video" type
204  * --------first level view----
205  * --------find out all album with type file
206  * --------selection MEDIA_DATA_DB_MEDIA_TYPE == type
207  * --------Get the relative path ----> Album path
208  * --------selection MEDIA_DATA_DB_FILE_PATH == Album path1 || selection MEDIA_DATA_DB_FILE_PATH == Album path2 || ...
209  * --------second level view ----
210  * --------selection MEDIA_DATA_DB_RELATIVE_PATH == uri.MEDIA_DATA_DB_FILE_PATH && MEDIA_DATA_DB_MEDIA_TYPE == type
211  */
CreateSelectionAndArgsFirstLevel(const string & type,string & selection,vector<string> & selectionArgs)212 int CreateSelectionAndArgsFirstLevel(const string &type, string &selection, vector<string> &selectionArgs)
213 {
214     if (type == "file") {
215         selection = Media::MEDIA_DATA_DB_RELATIVE_PATH + " LIKE ? AND (" + Media::MEDIA_DATA_DB_MEDIA_TYPE;
216         selection += " LIKE ? OR " + Media::MEDIA_DATA_DB_MEDIA_TYPE + " LIKE ? )";
217         selectionArgs = {
218             RELATIVE_ROOT_PATH, ToString(Media::MediaType::MEDIA_TYPE_FILE),
219             ToString(Media::MediaType::MEDIA_TYPE_ALBUM)
220         };
221     } else {
222         selectionArgs = FindAlbumByType(GetType(type));
223         selection = Media::MEDIA_DATA_DB_FILE_PATH + " LIKE ?";
224         if (selectionArgs.size() > 1) {
225             for (uint32_t i = 1; i < selectionArgs.size(); i++) {
226                 selection += " OR " + Media::MEDIA_DATA_DB_FILE_PATH + " LIKE ?";
227             }
228         }
229     }
230     return SUCCESS;
231 }
232 
CreateSelectionAndArgsOtherLevel(const string & type,const string & albumUri,string & selection,vector<string> & selectionArgs)233 int CreateSelectionAndArgsOtherLevel(const string &type, const string &albumUri, string &selection,
234     vector<string> &selectionArgs)
235 {
236     // get the album path from the album uri
237     string albumPath;
238     if (!GetPathFromAlbumPath(albumUri, albumPath)) {
239         ERR_LOG("path not exsit");
240         return E_NOEXIST;
241     }
242     if (type == "file") {
243         selection = Media::MEDIA_DATA_DB_RELATIVE_PATH + " LIKE ? AND (" + Media::MEDIA_DATA_DB_MEDIA_TYPE;
244         selection += " LIKE ? OR " + Media::MEDIA_DATA_DB_MEDIA_TYPE + " LIKE ? )";
245         selectionArgs = {
246             albumPath, ToString(Media::MediaType::MEDIA_TYPE_FILE),
247             ToString(Media::MediaType::MEDIA_TYPE_ALBUM)
248         };
249     } else {
250         selection = Media::MEDIA_DATA_DB_RELATIVE_PATH + " LIKE ? AND " + Media::MEDIA_DATA_DB_MEDIA_TYPE + " LIKE ?";
251         selectionArgs = { albumPath, GetType(type) };
252     }
253     return SUCCESS;
254 }
255 
GetAlbumPath(const string & name,const string & path,string & albumPath)256 bool GetAlbumPath(const string &name, const string &path, string &albumPath)
257 {
258     if (IsFirstLevelUriPath(path)) {
259         int mediaType = GetMediaType(name);
260         albumPath = (MEDIA_TYPE_FOLDER_MAPS.count(mediaType) == 0) ? MEDIA_TYPE_FOLDER_MAPS.at(FILE_MEDIA_TYPE) :
261             MEDIA_TYPE_FOLDER_MAPS.at(mediaType);
262         return true;
263     }
264     return GetPathFromAlbumPath(path, albumPath);
265 }
266 
ShowSelecArgs(const string & selection,const vector<string> & selectionArgs)267 static void ShowSelecArgs(const string &selection, const vector<string> &selectionArgs)
268 {
269     DEBUG_LOG("selection %{public}s ", selection.c_str());
270     for (auto s : selectionArgs) {
271         DEBUG_LOG("selectionArgs %{public}s", s.c_str());
272     }
273 }
274 
DoListFile(const string & type,const string & path,int offset,int count,shared_ptr<NativeRdb::AbsSharedResultSet> & result)275 int MediaFileUtils::DoListFile(const string &type, const string &path, int offset, int count,
276     shared_ptr<NativeRdb::AbsSharedResultSet> &result)
277 {
278     string selection;
279     vector<string> selectionArgs;
280     if (IsFirstLevelUriPath(path)) {
281         DEBUG_LOG("IsFirstLevelUriPath");
282         CreateSelectionAndArgsFirstLevel(type, selection, selectionArgs);
283     } else {
284         int err = CreateSelectionAndArgsOtherLevel(type, path, selection, selectionArgs);
285         if (err) {
286             ERR_LOG("CreateSelectionAndArgsOtherLevel returns fail");
287             return err;
288         }
289     }
290     result = DoQuery(selection, selectionArgs, offset, count);
291     if (result == nullptr) {
292         ERR_LOG("ListFile folder is empty");
293         return E_EMPTYFOLDER;
294     }
295     return SUCCESS;
296 }
297 
DoQuery(const string & selection,const vector<string> & selectionArgs)298 shared_ptr<NativeRdb::AbsSharedResultSet> MediaFileUtils::DoQuery(const string &selection,
299     const vector<string> &selectionArgs)
300 {
301     return DoQuery(selection, selectionArgs, 0, MAX_NUM);
302 }
303 
DoQuery(const string & selection,const vector<string> & selectionArgs,int offset,int count)304 shared_ptr<NativeRdb::AbsSharedResultSet> MediaFileUtils::DoQuery(const string &selection,
305     const vector<string> &selectionArgs, int offset, int count)
306 {
307     ShowSelecArgs(selection, selectionArgs);
308     NativeRdb::DataAbilityPredicates predicates;
309     predicates.SetWhereClause(selection);
310     predicates.SetWhereArgs(selectionArgs);
311     predicates.SetOrder("date_taken DESC LIMIT " + ToString(offset) + "," + ToString(count));
312     DEBUG_LOG("limit %{public}d, offset %{public}d", count, offset);
313     Uri uri = Uri(Media::MEDIALIBRARY_DATA_URI);
314     vector<string> columns;
315     return abilityHelper->Query(uri, columns, predicates);
316 }
317 
DoInsert(const string & name,const string & path,const string & type,string & uri)318 int MediaFileUtils::DoInsert(const string &name, const string &path, const string &type, string &uri)
319 {
320     NativeRdb::ValuesBucket values;
321     string albumPath;
322     if (!GetAlbumPath(name, path, albumPath)) {
323         ERR_LOG("path not exsit");
324         return E_NOEXIST;
325     }
326     values.PutString(Media::MEDIA_DATA_DB_RELATIVE_PATH, albumPath);
327     values.PutString(Media::MEDIA_DATA_DB_NAME, name);
328     values.PutString(Media::MEDIA_DATA_DB_MIME_TYPE, GetMimeType(name));
329     values.PutInt(Media::MEDIA_DATA_DB_MEDIA_TYPE, GetMediaType(name));
330     Uri createAsset(Media::MEDIALIBRARY_DATA_URI + "/" + Media::MEDIA_FILEOPRN + "/" +
331         Media::MEDIA_FILEOPRN_CREATEASSET);
332     int index = abilityHelper->Insert(createAsset, values);
333     if (index < 0) {
334         ERR_LOG("Fail to create fail file %{public}s uri %{private}s album %{public}s", name.c_str(),
335             path.c_str(), albumPath.c_str());
336         return E_CREATE_FAIL;
337     }
338     // use file id concatenate head as uri
339     uri = (MEDIA_TYPE_URI_MAPS.count(GetMediaType(name)) == 0) ? MEDIA_TYPE_URI_MAPS.at(FILE_MEDIA_TYPE) :
340         MEDIA_TYPE_URI_MAPS.at(GetMediaType(name));
341     uri += "/" + to_string(index);
342 
343     return SUCCESS;
344 }
345 
InitMediaTableColIndexMap(shared_ptr<NativeRdb::AbsSharedResultSet> result)346 bool MediaFileUtils::InitMediaTableColIndexMap(shared_ptr<NativeRdb::AbsSharedResultSet> result)
347 {
348     if (mediaTableMap.size() == 0) {
349         DEBUG_LOG("init mediaTableMap");
350         vector<pair<string, string>> mediaData = {
351             {Media::MEDIA_DATA_DB_ID, "string"},
352             {Media::MEDIA_DATA_DB_URI, "string"},
353             {Media::MEDIA_DATA_DB_MEDIA_TYPE, "string"},
354             {Media::MEDIA_DATA_DB_NAME, "string"},
355             {Media::MEDIA_DATA_DB_SIZE, "int"},
356             {Media::MEDIA_DATA_DB_DATE_ADDED, "int"},
357             {Media::MEDIA_DATA_DB_DATE_MODIFIED, "int"}
358         };
359         for (auto i : mediaData) {
360             int columnIndex = 0;
361             GET_COLUMN_INDEX_FROM_NAME(result, i.first, columnIndex);
362             mediaTableMap.emplace_back(columnIndex, i.second);
363         }
364     }
365     return true;
366 }
367 
GetFileInfo(shared_ptr<NativeRdb::AbsSharedResultSet> result,shared_ptr<FileInfo> & fileInfo)368 bool MediaFileUtils::GetFileInfo(shared_ptr<NativeRdb::AbsSharedResultSet> result,
369     shared_ptr<FileInfo> &fileInfo)
370 {
371     if (!InitMediaTableColIndexMap(result)) {
372         ERR_LOG("InitMediaTableColIndexMap returns fail");
373         return false;
374     }
375     int index = 0;
376     string id;
377     result->GetString(mediaTableMap[index++].first, id);
378     string uri;
379     result->GetString(mediaTableMap[index++].first, uri);
380 
381     string path = uri + "/" + id;
382     fileInfo->SetPath(path);
383     string type;
384     result->GetString(mediaTableMap[index++].first, type);
385     fileInfo->SetType(type);
386     string name;
387     result->GetString(mediaTableMap[index++].first, name);
388     fileInfo->SetName(name);
389     int64_t value;
390     result->GetLong(mediaTableMap[index++].first, value);
391     fileInfo->SetSize(value);
392     result->GetLong(mediaTableMap[index++].first, value);
393     fileInfo->SetAddedTime(value);
394     result->GetLong(mediaTableMap[index++].first, value);
395     fileInfo->SetModifiedTime(value);
396     return true;
397 }
398 
GetFileInfoFromResult(shared_ptr<NativeRdb::AbsSharedResultSet> result,std::vector<shared_ptr<FileInfo>> & fileList)399 int MediaFileUtils::GetFileInfoFromResult(shared_ptr<NativeRdb::AbsSharedResultSet> result,
400     std::vector<shared_ptr<FileInfo>> &fileList)
401 {
402     int count = 0;
403     result->GetRowCount(count);
404     if (count == 0) {
405         ERR_LOG("AbsSharedResultSet null");
406         return E_EMPTYFOLDER;
407     }
408     result->GoToFirstRow();
409     for (int i = 0; i < count; i++) {
410         shared_ptr<FileInfo> fileInfo = make_shared<FileInfo>();
411         GetFileInfo(result, fileInfo);
412         fileList.push_back(fileInfo);
413         result->GoToNextRow();
414     }
415     return SUCCESS;
416 }
417 
InitHelper(sptr<IRemoteObject> obj)418 bool MediaFileUtils::InitHelper(sptr<IRemoteObject> obj)
419 {
420     if (abilityHelper == nullptr) {
421         abilityHelper =  AppExecFwk::DataAbilityHelper::Creator(obj, make_shared<Uri>(Media::MEDIALIBRARY_DATA_URI));
422         if (abilityHelper == nullptr) {
423             DEBUG_LOG("get %{private}s helper fail", Media::MEDIALIBRARY_DATA_URI.c_str());
424             return false;
425         }
426     }
427     return true;
428 }
429 
DoGetRoot(const std::string & name,const std::string & path,std::vector<shared_ptr<FileInfo>> & fileList)430 int MediaFileUtils::DoGetRoot(const std::string &name, const std::string &path,
431     std::vector<shared_ptr<FileInfo>> &fileList)
432 {
433     shared_ptr<FileInfo> image = make_shared<FileInfo>(IMAGE_ROOT_NAME, FISRT_LEVEL_ALBUM, ALBUM_TYPE);
434     fileList.emplace_back(image);
435     shared_ptr<FileInfo> video = make_shared<FileInfo>(VIDEO_ROOT_NAME, FISRT_LEVEL_ALBUM, ALBUM_TYPE);
436     fileList.emplace_back(video);
437     shared_ptr<FileInfo> audio = make_shared<FileInfo>(AUDIO_ROOT_NAME, FISRT_LEVEL_ALBUM, ALBUM_TYPE);
438     fileList.emplace_back(audio);
439     shared_ptr<FileInfo> file = make_shared<FileInfo>(FILE_ROOT_NAME, FISRT_LEVEL_ALBUM, ALBUM_TYPE);
440     fileList.emplace_back(file);
441     return SUCCESS;
442 }
443 } // namespace FileManagerService
444 } // namespace OHOS