diff --git a/frameworks/innerkitsimpl/media_library_helper/src/fetch_result.cpp b/frameworks/innerkitsimpl/media_library_helper/src/fetch_result.cpp index 6439a7b376ccb7facca3cdc1098f5144a4afd7d5..4b5439aa2d3e8800b88eb758768f6f40743e1195 100644 --- a/frameworks/innerkitsimpl/media_library_helper/src/fetch_result.cpp +++ b/frameworks/innerkitsimpl/media_library_helper/src/fetch_result.cpp @@ -74,6 +74,7 @@ static const ResultTypeMap &GetResultTypeMap() { PhotoColumn::PHOTO_DATE_MONTH, TYPE_STRING}, { PhotoColumn::PHOTO_DATE_DAY, TYPE_STRING}, { PhotoColumn::PHOTO_SHOOTING_MODE, TYPE_STRING}, + { PhotoColumn::PHOTO_SHOOTING_MODE_TAG, TYPE_STRING}, { PhotoColumn::PHOTO_LAST_VISIT_TIME, TYPE_INT64 }, }; return RESULT_TYPE_MAP; diff --git a/frameworks/innerkitsimpl/media_library_helper/src/media_column.cpp b/frameworks/innerkitsimpl/media_library_helper/src/media_column.cpp index 234a45e1d695110f99de8ed46b8f366501110094..0a4a648532832cf9b1d0536d2455cf19f8033eef 100644 --- a/frameworks/innerkitsimpl/media_library_helper/src/media_column.cpp +++ b/frameworks/innerkitsimpl/media_library_helper/src/media_column.cpp @@ -71,6 +71,7 @@ const std::string PhotoColumn::PHOTO_SUBTYPE = "subtype"; const std::string PhotoColumn::CAMERA_SHOT_KEY = "camera_shot_key"; const std::string PhotoColumn::PHOTO_USER_COMMENT = "user_comment"; const std::string PhotoColumn::PHOTO_SHOOTING_MODE = "shooting_mode"; +const std::string PhotoColumn::PHOTO_SHOOTING_MODE_TAG = "shooting_mode_tag"; const std::string PhotoColumn::PHOTO_ALL_EXIF = "all_exif"; const std::string PhotoColumn::PHOTO_DATE_YEAR = "date_year"; const std::string PhotoColumn::PHOTO_DATE_MONTH = "date_month"; @@ -145,6 +146,7 @@ const std::string PhotoColumn::CREATE_PHOTO_TABLE = "CREATE TABLE IF NOT EXISTS PHOTO_DATE_MONTH + " TEXT, " + PHOTO_DATE_DAY + " TEXT, " + PHOTO_SHOOTING_MODE + " TEXT, " + + PHOTO_SHOOTING_MODE_TAG + " TEXT, " + PHOTO_LAST_VISIT_TIME + " BIGINT DEFAULT 0, " + PHOTO_HIDDEN_TIME + " BIGINT DEFAULT 0, " + PHOTO_THUMB_STATUS + " INT DEFAULT 0, " + @@ -246,7 +248,7 @@ const std::set PhotoColumn::PHOTO_COLUMNS = { PhotoColumn::PHOTO_DIRTY, PhotoColumn::PHOTO_CLOUD_ID, PhotoColumn::CAMERA_SHOT_KEY, PhotoColumn::PHOTO_ALL_EXIF, PhotoColumn::PHOTO_USER_COMMENT, PhotoColumn::PHOTO_DATE_YEAR, PhotoColumn::PHOTO_DATE_MONTH, PhotoColumn::PHOTO_DATE_DAY, PhotoColumn::PHOTO_EDIT_TIME, PhotoColumn::PHOTO_CLEAN_FLAG, - PHOTO_SHOOTING_MODE, PhotoColumn::PHOTO_THUMB_STATUS + PhotoColumn::PHOTO_SHOOTING_MODE, PhotoColumn::PHOTO_SHOOTING_MODE_TAG, PhotoColumn::PHOTO_THUMB_STATUS }; bool PhotoColumn::IsPhotoColumn(const std::string &columnName) diff --git a/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_rdbstore.cpp b/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_rdbstore.cpp index bf8674bf51573a3912e9c75f8c5f9123cd2e67b8..8322dc188c4797f1a703b95fc9392e3698c28f5e 100644 --- a/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_rdbstore.cpp +++ b/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_rdbstore.cpp @@ -56,6 +56,13 @@ struct UniqueMemberValuesBucket { int32_t startNumber; }; + +struct ShootingModeValueBucket { + int32_t albumType; + int32_t albumSubType; + std::string albumName; +}; + const std::string MediaLibraryRdbStore::CloudSyncTriggerFunc(const std::vector &args) { CloudSyncHelper::GetInstance()->StartSync(); @@ -611,6 +618,61 @@ int32_t MediaLibraryDataCallBack::PrepareSmartAlbum(RdbStore &store) return NativeRdb::E_OK; } +static int32_t InsertShootingModeAlbumValues( + const ShootingModeValueBucket &shootingModeAlbum, RdbStore &store) +{ + ValuesBucket valuesBucket; + valuesBucket.PutInt(SMARTALBUM_DB_ALBUM_TYPE, shootingModeAlbum.albumType); + valuesBucket.PutInt(COMPAT_ALBUM_SUBTYPE, shootingModeAlbum.albumSubType); + valuesBucket.PutString(MEDIA_DATA_DB_ALBUM_NAME, shootingModeAlbum.albumName); + int64_t outRowId = -1; + int32_t insertResult = store.Insert(outRowId, ANALYSIS_ALBUM_TABLE, valuesBucket); + return insertResult; +} + +static int32_t PrepareShootingModeAlbum(RdbStore &store) +{ + ShootingModeValueBucket portraitAlbum = { + SHOOTING_MODE_TYPE, SHOOTING_MODE_SUB_TYPE, PORTRAIT_ALBUM + }; + ShootingModeValueBucket wideApertureAlbum = { + SHOOTING_MODE_TYPE, SHOOTING_MODE_SUB_TYPE, WIDE_APERTURE_ALBUM + }; + ShootingModeValueBucket nightShotAlbum = { + SHOOTING_MODE_TYPE, SHOOTING_MODE_SUB_TYPE, NIGHT_SHOT_ALBUM + }; + ShootingModeValueBucket movingPictureAlbum = { + SHOOTING_MODE_TYPE, SHOOTING_MODE_SUB_TYPE, MOVING_PICTURE_ALBUM + }; + ShootingModeValueBucket proPhotoAlbum = { + SHOOTING_MODE_TYPE, SHOOTING_MODE_SUB_TYPE, PRO_PHOTO_ALBUM + }; + ShootingModeValueBucket slowMotionAlbum = { + SHOOTING_MODE_TYPE, SHOOTING_MODE_SUB_TYPE, SLOW_MOTION_ALBUM + }; + ShootingModeValueBucket lightPaintingAlbum = { + SHOOTING_MODE_TYPE, SHOOTING_MODE_SUB_TYPE, LIGHT_PAINTING_ALBUM + }; + ShootingModeValueBucket highPixelAlbum = { + SHOOTING_MODE_TYPE, SHOOTING_MODE_SUB_TYPE, HIGH_PIXEL_ALBUM + }; + ShootingModeValueBucket superMicroAlbum = { + SHOOTING_MODE_TYPE, SHOOTING_MODE_SUB_TYPE, SUPER_MACRO_ALBUM + }; + + vector shootingModeValuesBucket = { + portraitAlbum, wideApertureAlbum, nightShotAlbum, movingPictureAlbum, + proPhotoAlbum, lightPaintingAlbum, highPixelAlbum, superMicroAlbum, slowMotionAlbum + }; + for (const auto& shootingModeAlbum : shootingModeValuesBucket) { + if (InsertShootingModeAlbumValues(shootingModeAlbum, store) != NativeRdb::E_OK) { + MEDIA_ERR_LOG("Prepare shootingMode album failed"); + return NativeRdb::E_ERROR; + } + } + return NativeRdb::E_OK; +} + int32_t MediaLibraryDataCallBack::InsertSmartAlbumValues(const SmartAlbumValuesBucket &smartAlbum, RdbStore &store) { ValuesBucket valuesBucket; @@ -707,6 +769,8 @@ static const string &TriggerDeletePhotoClearMap() " BEGIN " + "DELETE FROM " + PhotoMap::TABLE + " WHERE " + PhotoMap::ASSET_ID + "=" + "OLD." + MediaColumn::MEDIA_ID + ";" + + "DELETE FROM " + ANALYSIS_PHOTO_MAP_TABLE + + " WHERE " + PhotoMap::ASSET_ID + "=" + "OLD." + MediaColumn::MEDIA_ID + ";" + " END;"; return TRIGGER_DELETE_ASSETS; } @@ -914,6 +978,11 @@ int32_t MediaLibraryDataCallBack::OnCreate(RdbStore &store) if (PrepareUniqueMemberTable(store) != NativeRdb::E_OK) { return NativeRdb::E_ERROR; } + + if (PrepareShootingModeAlbum(store)!= NativeRdb::E_OK) { + return NativeRdb::E_ERROR; + } + return NativeRdb::E_OK; } @@ -1570,6 +1639,21 @@ void AddShootingModeColumn(RdbStore &store) } } +void AddShootingModeTagColumn(RdbStore &store) +{ + const std::string addShootringModeTag = + "ALTER TABLE " + PhotoColumn::PHOTOS_TABLE + " ADD COLUMN " + + PhotoColumn::PHOTO_SHOOTING_MODE_TAG + " TEXT"; + const std::string dropExpiredClearMapTrigger = + "DROP TRIGGER IF EXISTS delete_photo_clear_map"; + const vector addShootingModeTagColumn = {addShootringModeTag, + dropExpiredClearMapTrigger, TriggerDeletePhotoClearMap()}; + int32_t result = ExecSqls(addShootingModeTagColumn, store); + if (result != NativeRdb::E_OK) { + MEDIA_ERR_LOG("Upgrade rdb shooting_mode error %{private}d", result); + } +} + static void AddHiddenViewColumn(RdbStore &store) { vector upgradeSqls = { @@ -1755,6 +1839,10 @@ static void UpgradeOtherTable(RdbStore &store, int32_t oldVersion) if (oldVersion < VERSION_FIX_DOCS_PATH) { FixDocsPath(store); } + if (oldVersion < VERSION_ADD_SHOOTING_MODE_TAG) { + AddShootingModeTagColumn(store); + PrepareShootingModeAlbum(store); + } } static void UpgradeGalleryFeatureTable(RdbStore &store, int32_t oldVersion) diff --git a/frameworks/innerkitsimpl/test/BUILD.gn b/frameworks/innerkitsimpl/test/BUILD.gn index 8d9f964e1700bfedf36d402dab9cb25cf8773ca5..6a695490ab2a7c698e909708e24c2fc28af950cc 100644 --- a/frameworks/innerkitsimpl/test/BUILD.gn +++ b/frameworks/innerkitsimpl/test/BUILD.gn @@ -35,6 +35,7 @@ group("test") { "unittest/medialibrary_scanner_db_test:unittest", "unittest/medialibrary_scanner_test:unittest", "unittest/medialibrary_search_test:unittest", + "unittest/medialibrary_shooting_mode_album_test:unittest", "unittest/medialibrary_smartalbum_map_operations_test:unittest", "unittest/medialibrary_smartalbum_operations_test:unittest", "unittest/medialibrary_thumbnail_service_test:unittest", diff --git a/frameworks/innerkitsimpl/test/unittest/medialibrary_shooting_mode_album_test/BUILD.gn b/frameworks/innerkitsimpl/test/unittest/medialibrary_shooting_mode_album_test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..8b963f910f964006dd5872b02130a4f14090d038 --- /dev/null +++ b/frameworks/innerkitsimpl/test/unittest/medialibrary_shooting_mode_album_test/BUILD.gn @@ -0,0 +1,72 @@ +# Copyright (C) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/multimedia/media_library/media_library.gni") + +group("unittest") { + testonly = true + deps = [ ":medialibrary_shootingmode_album_test" ] +} + +ohos_unittest("medialibrary_shootingmode_album_test") { + module_out_path = "media_library/medialibrary_shooting_mode_album_test" + include_dirs = [ + "./include", + "../medialibrary_unittest_utils/include", + "${MEDIALIB_UTILS_PATH}/include", + "${MEDIALIB_INNERKITS_PATH}/medialibrary_shooting_mode_album_test/include", + "${MEDIALIB_INTERFACES_PATH}/inner_api/media_library_helper/include", + "${MEDIALIB_SERVICES_PATH}/media_thumbnail/include", + ] + + sources = [ + "../medialibrary_shooting_mode_album_test/src/shooting_mode_album_test.cpp", + "../medialibrary_unittest_utils/src/medialibrary_unittest_utils.cpp", + ] + + deps = [ + "${MEDIALIB_INNERKITS_PATH}/media_library_helper:media_library", + "${MEDIALIB_INNERKITS_PATH}/medialibrary_data_extension:medialibrary_data_extension", + "../../../../../../../ability/ability_runtime/interfaces/inner_api/dataobs_manager:dataobs_manager", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:ability_context_native", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:app_context", + "ability_runtime:dataobs_manager", + "ability_runtime:runtime", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "data_share:datashare_common", + "data_share:datashare_provider", + "hilog:libhilog", + "hitrace:hitrace_meter", + "image_framework:image_native", + "ipc:ipc_single", + "kv_store:distributeddata_inner", + "napi:ace_napi", + "relational_store:native_rdb", + "relational_store:rdb_data_share_adapter", + "user_file_service:file_access_extension_ability_kit", + ] + + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } +} diff --git a/frameworks/innerkitsimpl/test/unittest/medialibrary_shooting_mode_album_test/include/shooting_mode_album_test.h b/frameworks/innerkitsimpl/test/unittest/medialibrary_shooting_mode_album_test/include/shooting_mode_album_test.h new file mode 100644 index 0000000000000000000000000000000000000000..485631b07da16416413bb8605cf508d15e42b06c --- /dev/null +++ b/frameworks/innerkitsimpl/test/unittest/medialibrary_shooting_mode_album_test/include/shooting_mode_album_test.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MEDIA_LIBRARY_SHOOTING_MODE_ALBUM_UNITTEST_H +#define OHOS_MEDIA_LIBRARY_SHOOTING_MODE_ALBUM_UNITTEST_H + +#include + +namespace OHOS::Media { +class ShootingModeAlbumTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; +} // namespace OHOS::Media +#endif // OHOS_MEDIA_LIBRARY_SHOOTING_MODE_ALBUM_UNITTEST_H diff --git a/frameworks/innerkitsimpl/test/unittest/medialibrary_shooting_mode_album_test/src/shooting_mode_album_test.cpp b/frameworks/innerkitsimpl/test/unittest/medialibrary_shooting_mode_album_test/src/shooting_mode_album_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..14d74e44129853df04403c95861eac236f2c1705 --- /dev/null +++ b/frameworks/innerkitsimpl/test/unittest/medialibrary_shooting_mode_album_test/src/shooting_mode_album_test.cpp @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "medialibrary_command.h" +#define MLOG_TAG "ShootingModeAlbumTest" + +#include "shooting_mode_album_test.h" + +#include "fetch_result.h" +#include "media_file_utils.h" +#include "media_log.h" +#include "medialibrary_album_operations.h" +#include "medialibrary_data_manager.h" +#include "medialibrary_db_const.h" +#include "medialibrary_errno.h" +#include "medialibrary_rdbstore.h" +#include "medialibrary_type_const.h" +#include "medialibrary_unittest_utils.h" +#include "photo_album_column.h" +#include "photo_map_column.h" +#include "rdb_predicates.h" +#include "result_set_utils.h" +#include "shooting_mode_column.h" +#include "vision_column.h" + +namespace OHOS::Media { +using namespace std; +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::DataShare; +using OHOS::DataShare::DataShareValuesBucket; +using OHOS::DataShare::DataSharePredicates; + +static shared_ptr g_rdbStore; +const std::string URI_CREATE_PHOTO_ALBUM = MEDIALIBRARY_DATA_URI + "/" + PHOTO_ALBUM_OPRN + "/" + OPRN_CREATE; +const std::string URI_UPDATE_PHOTO_ALBUM = MEDIALIBRARY_DATA_URI + "/" + PHOTO_ALBUM_OPRN + "/" + OPRN_UPDATE; +const std::string URI_ORDER_ALBUM = MEDIALIBRARY_DATA_URI + "/" + PHOTO_ALBUM_OPRN + "/" + OPRN_ORDER_ALBUM; +int32_t ClearTable(const string &table) +{ + RdbPredicates predicates(table); + + int32_t rows = 0; + int32_t err = g_rdbStore->Delete(rows, predicates); + if (err != E_OK) { + MEDIA_ERR_LOG("Failed to clear album table, err: %{public}d", err); + return E_HAS_DB_ERROR; + } + return E_OK; +} + +int32_t ClearAnalysisAlbums() +{ + RdbPredicates predicates(ANALYSIS_ALBUM_TABLE); + predicates.EqualTo(PhotoAlbumColumns::ALBUM_TYPE, to_string(PhotoAlbumType::SMART)); + predicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(PhotoAlbumSubType::SHOOTING_MODE)); + int32_t rows = 0; + int32_t err = g_rdbStore->Delete(rows, predicates); + if (err != E_OK) { + MEDIA_ERR_LOG("Failed to clear AnalysisAlbum table, err: %{public}d", err); + return E_HAS_DB_ERROR; + } + return E_OK; +} + +inline void CheckColumn(shared_ptr &resultSet, const string &column, + ResultSetDataType type, const variant &expected) +{ + EXPECT_EQ(ResultSetUtils::GetValFromColumn(column, resultSet, type), expected); +} + +void DoCheckShootingAlbumData(const string &name) +{ + string albumName = name; + RdbPredicates predicates(ANALYSIS_ALBUM_TABLE); + predicates.EqualTo(PhotoAlbumColumns::ALBUM_NAME, albumName); + predicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, PhotoAlbumSubType::SHOOTING_MODE); + const vector columns = { + PhotoAlbumColumns::ALBUM_ID, + PhotoAlbumColumns::ALBUM_TYPE, + PhotoAlbumColumns::ALBUM_SUBTYPE, + PhotoAlbumColumns::ALBUM_NAME, + PhotoAlbumColumns::ALBUM_COVER_URI, + PhotoAlbumColumns::ALBUM_COUNT, + }; + shared_ptr resultSet = g_rdbStore->Query(predicates, columns); + ASSERT_NE(resultSet, nullptr); + int32_t count = -1; + int32_t ret = resultSet->GetRowCount(count); + CHECK_AND_RETURN_LOG(ret == E_OK, "Failed to get count! err: %{public}d", ret); + MEDIA_INFO_LOG("Query count: %{public}d", count); + ret = resultSet->GoToFirstRow(); + CHECK_AND_RETURN_LOG(ret == E_OK, "Failed to GoToFirstRow! err: %{public}d", ret); + + int32_t albumId = get(ResultSetUtils::GetValFromColumn(PhotoAlbumColumns::ALBUM_ID, resultSet, + TYPE_INT32)); + EXPECT_GT(albumId, 0); + CheckColumn(resultSet, PhotoAlbumColumns::ALBUM_TYPE, TYPE_INT32, PhotoAlbumType::SMART); + CheckColumn(resultSet, PhotoAlbumColumns::ALBUM_SUBTYPE, TYPE_INT32, PhotoAlbumSubType::SHOOTING_MODE); + CheckColumn(resultSet, PhotoAlbumColumns::ALBUM_NAME, TYPE_STRING, albumName); + CheckColumn(resultSet, PhotoAlbumColumns::ALBUM_COVER_URI, TYPE_STRING, ""); + CheckColumn(resultSet, PhotoAlbumColumns::ALBUM_COUNT, TYPE_INT32, 0); +} + +struct ShootingModeValueBucket { + int32_t albumType; + int32_t albumSubType; + std::string albumName; +}; + +static int32_t InsertShootingModeAlbumValues( + const ShootingModeValueBucket &shootingModeAlbum, shared_ptr store) +{ + ValuesBucket valuesBucket; + valuesBucket.PutInt(SMARTALBUM_DB_ALBUM_TYPE, shootingModeAlbum.albumType); + valuesBucket.PutInt(COMPAT_ALBUM_SUBTYPE, shootingModeAlbum.albumSubType); + valuesBucket.PutString(MEDIA_DATA_DB_ALBUM_NAME, shootingModeAlbum.albumName); + int64_t outRowId = -1; + int32_t insertResult = store->Insert(outRowId, ANALYSIS_ALBUM_TABLE, valuesBucket); + return insertResult; +} + +static int32_t CreateShootingModeAlbum() +{ + ShootingModeValueBucket portraitAlbum = { + SHOOTING_MODE_TYPE, SHOOTING_MODE_SUB_TYPE, PORTRAIT_ALBUM + }; + ShootingModeValueBucket wideApertureAlbum = { + SHOOTING_MODE_TYPE, SHOOTING_MODE_SUB_TYPE, WIDE_APERTURE_ALBUM + }; + ShootingModeValueBucket nightShotAlbum = { + SHOOTING_MODE_TYPE, SHOOTING_MODE_SUB_TYPE, NIGHT_SHOT_ALBUM + }; + ShootingModeValueBucket movingPictureAlbum = { + SHOOTING_MODE_TYPE, SHOOTING_MODE_SUB_TYPE, MOVING_PICTURE_ALBUM + }; + ShootingModeValueBucket proPhotoAlbum = { + SHOOTING_MODE_TYPE, SHOOTING_MODE_SUB_TYPE, PRO_PHOTO_ALBUM + }; + ShootingModeValueBucket slowMotionAlbum = { + SHOOTING_MODE_TYPE, SHOOTING_MODE_SUB_TYPE, SLOW_MOTION_ALBUM + }; + ShootingModeValueBucket lightPaintingAlbum = { + SHOOTING_MODE_TYPE, SHOOTING_MODE_SUB_TYPE, LIGHT_PAINTING_ALBUM + }; + ShootingModeValueBucket highPixelAlbum = { + SHOOTING_MODE_TYPE, SHOOTING_MODE_SUB_TYPE, HIGH_PIXEL_ALBUM + }; + ShootingModeValueBucket superMicroAlbum = { + SHOOTING_MODE_TYPE, SHOOTING_MODE_SUB_TYPE, SUPER_MACRO_ALBUM + }; + + vector shootingModeValuesBucket = { + portraitAlbum, wideApertureAlbum, nightShotAlbum, movingPictureAlbum, + proPhotoAlbum, lightPaintingAlbum, highPixelAlbum, superMicroAlbum, slowMotionAlbum + }; + for (const auto& shootingModeAlbum : shootingModeValuesBucket) { + if (InsertShootingModeAlbumValues(shootingModeAlbum, g_rdbStore) != NativeRdb::E_OK) { + MEDIA_ERR_LOG("Prepare shootingMode album failed"); + return NativeRdb::E_ERROR; + } + } + return NativeRdb::E_OK; +} + +inline int32_t DeletePhotoAlbum(DataSharePredicates &predicates) +{ + Uri uri(URI_CREATE_PHOTO_ALBUM); + MediaLibraryCommand cmd(uri, OperationType::DELETE); + return MediaLibraryDataManager::GetInstance()->Delete(cmd, predicates); +} + +void ShootingModeAlbumTest::SetUpTestCase() +{ + MediaLibraryUnitTestUtils::Init(); + g_rdbStore = MediaLibraryDataManager::GetInstance()->rdbStore_; + ClearAnalysisAlbums(); + ClearTable(ANALYSIS_PHOTO_MAP_TABLE); +} + +void ShootingModeAlbumTest::TearDownTestCase() +{ + ClearAnalysisAlbums(); + ClearTable(ANALYSIS_PHOTO_MAP_TABLE); +} + +// SetUp:Execute before each test case +void ShootingModeAlbumTest::SetUp() {} + +void ShootingModeAlbumTest::TearDown() {} + +/** + * @tc.name: photoalbum_create_album_001 + * @tc.desc: Create photo albums test + * 1. Create an album called "photoalbum_create_album_001" + * @tc.type: FUNC + * @tc.require: issueI6B1SE + */ +HWTEST_F(ShootingModeAlbumTest, photoalbum_create_ShootingMode_album_001, TestSize.Level0) +{ + MEDIA_INFO_LOG("photoalbum_create_album_001 enter"); + auto ret = CreateShootingModeAlbum(); + EXPECT_EQ(ret, E_OK); + DoCheckShootingAlbumData(PORTRAIT_ALBUM); + DoCheckShootingAlbumData(WIDE_APERTURE_ALBUM); + DoCheckShootingAlbumData(NIGHT_SHOT_ALBUM); + DoCheckShootingAlbumData(MOVING_PICTURE_ALBUM); + DoCheckShootingAlbumData(PRO_PHOTO_ALBUM); + DoCheckShootingAlbumData(SLOW_MOTION_ALBUM); + DoCheckShootingAlbumData(LIGHT_PAINTING_ALBUM); + DoCheckShootingAlbumData(HIGH_PIXEL_ALBUM); + DoCheckShootingAlbumData(SUPER_MACRO_ALBUM); + MEDIA_INFO_LOG("photoalbum_create_album_001 exit"); +} +} // namespace OHOS::Media diff --git a/frameworks/js/src/media_library_napi.cpp b/frameworks/js/src/media_library_napi.cpp index d644291d577259f5f567fb576d730a75568742a5..6805fdfbe4f9838768fa910291bf8a9c28ea166d 100644 --- a/frameworks/js/src/media_library_napi.cpp +++ b/frameworks/js/src/media_library_napi.cpp @@ -5777,7 +5777,9 @@ static napi_value ParseAlbumTypes(napi_env env, unique_ptrpredicates.And()->EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(albumSubType)); } - + if (albumSubType == PhotoAlbumSubType::SHOOTING_MODE) { + context->predicates.OrderByDesc(PhotoAlbumColumns::ALBUM_COUNT); + } if (!MediaLibraryNapiUtils::IsSystemApp()) { context->predicates.And()->In(PhotoAlbumColumns::ALBUM_SUBTYPE, vector({ to_string(PhotoAlbumSubType::USER_GENERIC), diff --git a/frameworks/services/media_scanner/include/scanner/metadata.h b/frameworks/services/media_scanner/include/scanner/metadata.h index 6917f009de0f8135b25a23980767838d2066a0f7..5d032f5c42f9014a3ec41b57b515fa32347b7903 100644 --- a/frameworks/services/media_scanner/include/scanner/metadata.h +++ b/frameworks/services/media_scanner/include/scanner/metadata.h @@ -126,6 +126,9 @@ public: void SetShootingMode(const VariantData &shootingMode); const std::string &GetShootingMode() const; + void SetShootingModeTag(const VariantData &shootingMode); + const std::string &GetShootingModeTag() const; + void SetLastVisitTime(const VariantData &lastVisitTime); int64_t GetLastVisitTime() const; @@ -174,6 +177,7 @@ private: string dateMonth_; string dateDay_; string shootingMode_; + string shootingModeTag_; int64_t lastVisitTime_; // video, audio, image diff --git a/frameworks/services/media_scanner/include/scanner/scanner_utils.h b/frameworks/services/media_scanner/include/scanner/scanner_utils.h index 7c0fb8cd9a7838ed0547838d0fef1bde82a05262..8b304dc261459739d575c9568f53f139d2173341 100644 --- a/frameworks/services/media_scanner/include/scanner/scanner_utils.h +++ b/frameworks/services/media_scanner/include/scanner/scanner_utils.h @@ -24,6 +24,7 @@ #include "medialibrary_type_const.h" #include "media_scanner_const.h" +#include "shooting_mode_column.h" namespace OHOS { namespace Media { @@ -83,6 +84,23 @@ static std::vector EXTRACTOR_SUPPORTED_MIME = { DEFAULT_IMAGE_MIME_TYPE }; +static const std::unordered_map SHOOTING_MODE_CAST_MAP = { + {PORTRAIT_ALBUM_TAG, PORTRAIT_ALBUM}, + {WIDE_APERTURE_ALBUM_TAG, WIDE_APERTURE_ALBUM}, + {NIGHT_SHOT_ALBUM_TAG, NIGHT_SHOT_ALBUM}, + {REAR_CAMERA_NIGHT_SHOT_TAG, NIGHT_SHOT_ALBUM}, + {MOVING_PICTURE_ALBUM_TAG, MOVING_PICTURE_ALBUM}, + {PRO_PHOTO_ALBUM_TAG, PRO_PHOTO_ALBUM}, + {TAIL_LIGHT_ALBUM_TAG, LIGHT_PAINTING_ALBUM}, + {LIGHT_GRAFFITI_TAG, LIGHT_PAINTING_ALBUM}, + {SILKY_WATER_TAG, LIGHT_PAINTING_ALBUM}, + {STAR_TRACK_TAG, LIGHT_PAINTING_ALBUM}, + {HIGH_PIXEL_ALBUM_TAG, HIGH_PIXEL_ALBUM}, + {SUPER_MACRO_ALBUM_TAG, SUPER_MACRO_ALBUM}, + {SLOW_MOTION_ALBUM_TAG, SLOW_MOTION_ALBUM}, + {SUPER_SLOW_MOTION_ALBUM_TAG, SLOW_MOTION_ALBUM}, +}; + static const std::unordered_map SUPPORTED_EXTN_MAP = { /** Supported image types */ {IMAGE_CONTAINER_TYPE_BMP, DEFAULT_IMAGE_MIME_TYPE}, diff --git a/frameworks/services/media_scanner/src/scanner/media_scanner.cpp b/frameworks/services/media_scanner/src/scanner/media_scanner.cpp index f9194ae5bbca42cee02b1b919a0a7cfd02aebf37..7356a4d89091a39e6dbce753379b9800fc486612 100644 --- a/frameworks/services/media_scanner/src/scanner/media_scanner.cpp +++ b/frameworks/services/media_scanner/src/scanner/media_scanner.cpp @@ -21,13 +21,17 @@ #include "hitrace_meter.h" #include "ipc_skeleton.h" #include "media_file_utils.h" +#include "media_file_uri.h" #include "media_log.h" #include "medialibrary_data_manager_utils.h" +#include "medialibrary_unistore_manager.h" #include "medialibrary_errno.h" #include "medialibrary_notify.h" #include "medialibrary_xcollie_manager.h" #include "mimetype_utils.h" #include "post_event_utils.h" +#include "photo_map_column.h" +#include "vision_column.h" namespace OHOS { namespace Media { @@ -182,6 +186,64 @@ string GetUriWithoutSeg(const string &oldUri) return oldUri; } +static std::string CreateExtUriForAsset(std::unique_ptr &data) +{ + const std::string &filePath = data->GetFilePath(); + const std::string &displayName = data->GetFileName(); + auto mediaType = data->GetFileMediaType(); + if (filePath.empty() || displayName.empty() || mediaType < 0) { + MEDIA_ERR_LOG("param invalid, filePath %{private}s or displayName %{private}s invalid failed.", + filePath.c_str(), displayName.c_str()); + return ""; + } + + string extrUri = MediaFileUtils::GetExtraUri(displayName, filePath); + return MediaFileUtils::GetUriByExtrConditions(ML_FILE_URI_PREFIX + MediaFileUri::GetMediaTypeUri(mediaType, + MEDIA_API_VERSION_V10) + "/", to_string(data->GetFileId()), extrUri); +} + +static int32_t MaintainAnanlysisTable(std::unique_ptr &data, + shared_ptr &rdbStorePtr) +{ + string updateCountAndCoverUriSql = "UPDATE " + ANALYSIS_ALBUM_TABLE + + " SET cover_uri = '" + CreateExtUriForAsset(data) + + "' , count = COALESCE(count, 0) + 1 WHERE album_name = " + + data->GetShootingMode() + " AND album_subtype = " + to_string(PhotoAlbumSubType::SHOOTING_MODE); + int32_t result = rdbStorePtr->ExecuteSql(updateCountAndCoverUriSql); + return result; +} + +static int32_t MaintainShootingModeMap(std::unique_ptr &data, + shared_ptr &rdbStorePtr) +{ + string insertShootingModeSql = "INSERT OR IGNORE INTO " + ANALYSIS_PHOTO_MAP_TABLE + + "(" + PhotoMap::ALBUM_ID + "," + PhotoMap::ASSET_ID + ") SELECT AnalysisAlbum.album_id, " + + "Photos.file_id FROM " + PhotoColumn::PHOTOS_TABLE + " JOIN " + + ANALYSIS_ALBUM_TABLE + " ON Photos.shooting_mode=AnalysisAlbum.album_name WHERE file_id = " + + to_string(data->GetFileId()) + " AND AnalysisAlbum.album_subtype = " + + to_string(PhotoAlbumSubType::SHOOTING_MODE); + int32_t result = rdbStorePtr->ExecuteSql(insertShootingModeSql); + return result; +} + +static int32_t MaintainAlbumRelationship(std::unique_ptr &data) +{ + auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw(); + if (rdbStore == nullptr) { + MEDIA_ERR_LOG("rdbstore is nullptr"); + return E_HAS_DB_ERROR; + } + auto rdbStorePtr = rdbStore->GetRaw(); + if (rdbStorePtr == nullptr) { + MEDIA_ERR_LOG("obtain raw rdbstore fails"); + return E_HAS_DB_ERROR; + } + auto ret = MaintainShootingModeMap(data, rdbStorePtr); + if (ret != E_OK) { + return ret; + } + return MaintainAnanlysisTable(data, rdbStorePtr); +} int32_t MediaScannerObj::Commit() { @@ -205,6 +267,13 @@ int32_t MediaScannerObj::Commit() } } + if (!data_->GetShootingModeTag().empty()) { + auto err = MaintainAlbumRelationship(data_); + if (err != E_OK) { + return err; + } + } + // notify change mediaScannerDb_->NotifyDatabaseChange(data_->GetFileMediaType()); data_ = nullptr; diff --git a/frameworks/services/media_scanner/src/scanner/media_scanner_db.cpp b/frameworks/services/media_scanner/src/scanner/media_scanner_db.cpp index f679906e628287ba02b75b7a723b243f263d7533..5f358073df7b1fbb88c5be59b5c4474cfc818fb8 100644 --- a/frameworks/services/media_scanner/src/scanner/media_scanner_db.cpp +++ b/frameworks/services/media_scanner/src/scanner/media_scanner_db.cpp @@ -233,6 +233,7 @@ static void SetValuesFromMetaDataApi10(const Metadata &metadata, ValuesBucket &v } values.PutString(PhotoColumn::PHOTO_ALL_EXIF, metadata.GetAllExif()); values.PutString(PhotoColumn::PHOTO_SHOOTING_MODE, metadata.GetShootingMode()); + values.PutString(PhotoColumn::PHOTO_SHOOTING_MODE_TAG, metadata.GetShootingModeTag()); values.PutLong(PhotoColumn::PHOTO_LAST_VISIT_TIME, metadata.GetLastVisitTime()); #ifdef MEDIALIBRARY_COMPATIBILITY diff --git a/frameworks/services/media_scanner/src/scanner/metadata.cpp b/frameworks/services/media_scanner/src/scanner/metadata.cpp index 35cb24952fc976143d6ccc46481628f47143ed8b..3de9eeb5f9c6c831b3a7e48394c85f6e174ffe45 100644 --- a/frameworks/services/media_scanner/src/scanner/metadata.cpp +++ b/frameworks/services/media_scanner/src/scanner/metadata.cpp @@ -406,11 +406,21 @@ void Metadata::SetShootingMode(const VariantData &shootingMode) shootingMode_ = get(shootingMode); } +void Metadata::SetShootingModeTag(const VariantData &shootingModeTag) +{ + shootingModeTag_ = get(shootingModeTag); +} + const string &Metadata::GetShootingMode() const { return shootingMode_; } +const string &Metadata::GetShootingModeTag() const +{ + return shootingModeTag_; +} + #ifdef MEDIALIBRARY_COMPATIBILITY void Metadata::SetPhotoSubType(const VariantData &photoSubType) { diff --git a/frameworks/services/media_scanner/src/scanner/metadata_extractor.cpp b/frameworks/services/media_scanner/src/scanner/metadata_extractor.cpp index 02e5de398a3c2c89c296b25016783af993092c24..95a63ef74ebf7bb18085a8943f3dc0e10bcebe2e 100644 --- a/frameworks/services/media_scanner/src/scanner/metadata_extractor.cpp +++ b/frameworks/services/media_scanner/src/scanner/metadata_extractor.cpp @@ -73,6 +73,15 @@ static time_t convertTimeStr2TimeStamp(string &timeStr) return timeStamp; } +static string GetCastShootingMode(string &shootingModeTag) +{ + auto it = SHOOTING_MODE_CAST_MAP.find(shootingModeTag); + if (it != SHOOTING_MODE_CAST_MAP.end()) { + return it->second; + } + return ""; +} + int32_t MetadataExtractor::ExtractImageExif(std::unique_ptr &imageSource, std::unique_ptr &data) { if (imageSource == nullptr) { @@ -105,8 +114,9 @@ int32_t MetadataExtractor::ExtractImageExif(std::unique_ptr &imageS data->SetUserComment(propertyStr); } err = imageSource->GetImagePropertyString(0, PHOTO_DATA_IMAGE_PHOTO_MODE, propertyStr); - if (err == 0) { - data->SetShootingMode(propertyStr); + if (err == 0 && !propertyStr.empty()) { + data->SetShootingModeTag(propertyStr); + data->SetShootingMode(GetCastShootingMode(propertyStr)); } int64_t timeNow = MediaFileUtils::UTCTimeMilliSeconds(); diff --git a/frameworks/utils/include/media_exif.h b/frameworks/utils/include/media_exif.h index f3d94f8df875fed065cf7773ca1c698ec3c17006..1086e0fa927892948e9a5c08542d017c94105ebc 100644 --- a/frameworks/utils/include/media_exif.h +++ b/frameworks/utils/include/media_exif.h @@ -38,7 +38,7 @@ const std::string PHOTO_DATA_IMAGE_IMAGE_DESCRIPTION = "ImageDescription"; const std::string PHOTO_DATA_IMAGE_MAKE = "Make"; const std::string PHOTO_DATA_IMAGE_MODEL = "Model"; const std::string PHOTO_DATA_IMAGE_DATE_TIME = "DateTime"; -const std::string PHOTO_DATA_IMAGE_PHOTO_MODE = "PhotoMode"; +const std::string PHOTO_DATA_IMAGE_PHOTO_MODE = "HwMnoteCaptureMode"; const std::string PHOTO_DATA_IMAGE_SENSITIVITY_TYPE = "SensitivityType"; const std::string PHOTO_DATA_IMAGE_STANDARD_OUTPUT_SENSITIVITY = "StandardOutputSensitivity"; const std::string PHOTO_DATA_IMAGE_RECOMMENDED_EXPOSURE_INDEX = "RecommendedExposureIndex"; diff --git a/frameworks/utils/include/userfile_manager_types.h b/frameworks/utils/include/userfile_manager_types.h index fa4f0ce3729175e661be22cfc463679ac965fd05..292ac889ad1fb2a71d339b4fd28615b63da3b623 100644 --- a/frameworks/utils/include/userfile_manager_types.h +++ b/frameworks/utils/include/userfile_manager_types.h @@ -83,7 +83,8 @@ enum PhotoAlbumSubType : int32_t { CLASSIFY_SUBCATEGORY, GEOGRAPHY_LOCATION, GEOGRAPHY_CITY, - ANALYSIS_END = GEOGRAPHY_CITY, + SHOOTING_MODE, + ANALYSIS_END = SHOOTING_MODE, ANY = std::numeric_limits::max() }; diff --git a/interfaces/inner_api/media_library_helper/include/media_column.h b/interfaces/inner_api/media_library_helper/include/media_column.h index 42dcce349b19502190ebb1f50694b7c570b13cad..ea67b4cc86170b26ce53eb92f17c9e740753a1b2 100644 --- a/interfaces/inner_api/media_library_helper/include/media_column.h +++ b/interfaces/inner_api/media_library_helper/include/media_column.h @@ -96,6 +96,7 @@ public: static const std::string PHOTO_DATE_MONTH; static const std::string PHOTO_DATE_DAY; static const std::string PHOTO_SHOOTING_MODE; + static const std::string PHOTO_SHOOTING_MODE_TAG; static const std::string PHOTO_LAST_VISIT_TIME; static const std::string PHOTO_HIDDEN_TIME; static const std::string PHOTO_THUMB_STATUS; diff --git a/interfaces/inner_api/media_library_helper/include/medialibrary_db_const.h b/interfaces/inner_api/media_library_helper/include/medialibrary_db_const.h index 5feee23fe0b30ff983cd58621cc3a1d3c6f4df06..b4918bc039805b1c18293071d6c78bc5f96ba958 100644 --- a/interfaces/inner_api/media_library_helper/include/medialibrary_db_const.h +++ b/interfaces/inner_api/media_library_helper/include/medialibrary_db_const.h @@ -22,7 +22,7 @@ namespace OHOS { namespace Media { -const int32_t MEDIA_RDB_VERSION = 42; +const int32_t MEDIA_RDB_VERSION = 43; enum { VERSION_ADD_CLOUD = 2, VERSION_ADD_META_MODIFED = 3, @@ -68,6 +68,7 @@ enum { VERSION_UPDATE_SOURCE_ALBUM_TRIGGER = 40, VERSION_ADD_IMAGE_VIDEO_COUNT = 41, VERSION_ADD_SCHPT_HIDDEN_TIME_INDEX = 42, + VERSION_ADD_SHOOTING_MODE_TAG = 43, }; enum { diff --git a/interfaces/inner_api/media_library_helper/include/shooting_mode_column.h b/interfaces/inner_api/media_library_helper/include/shooting_mode_column.h new file mode 100644 index 0000000000000000000000000000000000000000..0ca32e17d5595b6cebcb6beb527bbf49591d8c51 --- /dev/null +++ b/interfaces/inner_api/media_library_helper/include/shooting_mode_column.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_INNERKITS_SHOOTING_MODE_COLUMN_H +#define INTERFACES_INNERKITS_SHOOTING_MODE_COLUMN_H + +#include + +#include "userfile_manager_types.h" + +namespace OHOS { +namespace Media { +/* ShootingMode album const values */ +constexpr int32_t SHOOTING_MODE_TYPE = PhotoAlbumType::SMART; +constexpr int32_t SHOOTING_MODE_SUB_TYPE = PhotoAlbumSubType::SHOOTING_MODE; + +/* ShootingMode tag value wrote by camera */ +const std::string PORTRAIT_ALBUM_TAG = "23"; +const std::string WIDE_APERTURE_ALBUM_TAG = "19"; +const std::string NIGHT_SHOT_ALBUM_TAG = "7"; +const std::string REAR_CAMERA_NIGHT_SHOT_TAG = "42"; +const std::string MOVING_PICTURE_ALBUM_TAG = "20"; +const std::string PRO_PHOTO_ALBUM_TAG = "2"; +const std::string TAIL_LIGHT_ALBUM_TAG = "9"; +const std::string LIGHT_GRAFFITI_TAG = "10"; +const std::string SILKY_WATER_TAG = "11"; +const std::string STAR_TRACK_TAG = "12"; +const std::string HIGH_PIXEL_ALBUM_TAG = "53"; +const std::string SUPER_MACRO_ALBUM_TAG = "47"; +const std::string SLOW_MOTION_ALBUM_TAG = "TypeSlowMotion"; +const std::string SUPER_SLOW_MOTION_ALBUM_TAG = "TypeSSlowMotion"; + +/* ShootingMode value in medialibrary */ +const std::string PORTRAIT_ALBUM = "1"; +const std::string WIDE_APERTURE_ALBUM = "2"; +const std::string NIGHT_SHOT_ALBUM = "3"; +const std::string MOVING_PICTURE_ALBUM = "4"; +const std::string PRO_PHOTO_ALBUM = "5"; +const std::string SLOW_MOTION_ALBUM = "6"; +const std::string LIGHT_PAINTING_ALBUM = "7"; +const std::string HIGH_PIXEL_ALBUM = "8"; +const std::string SUPER_MACRO_ALBUM = "9"; +}; +} // namespace OHOS::Media +#endif // INTERFACES_INNERKITS_SHOOTING_MODE_COLUMN_H \ No newline at end of file diff --git a/interfaces/kits/js/include/medialibrary_napi_utils.h b/interfaces/kits/js/include/medialibrary_napi_utils.h index be87e163f69dcc288dc5097b7c1dabeb8703399b..fb26ba0425cf3ccb3e74b55a7100fef972d70180 100644 --- a/interfaces/kits/js/include/medialibrary_napi_utils.h +++ b/interfaces/kits/js/include/medialibrary_napi_utils.h @@ -267,7 +267,8 @@ const std::vector systemAlbumSubType { }; const std::vector analysisAlbumSubType { - "CLASSIFY_CATEGORY", "CLASSIFY_SUBCATEGORY", "GEOGRAPHY_LOCATION", "GEOGRAPHY_CITY" + "CLASSIFY_CATEGORY", "CLASSIFY_SUBCATEGORY", "GEOGRAPHY_LOCATION", + "GEOGRAPHY_CITY", "SHOOTING_MODE" }; const std::vector positionTypeEnum {