已开启
增加相册、设置、桌面系统应用 #166
增加相册、设置、桌面系统应用 #166
已开启
奥德彪创建于 5月28日
共 61 个文件变更+3581-229
MOAT.xml+1-0
@@ -59,6 +59,7 @@ Note:If the text contains special characters, please escape them according to th
59 <licensefile></licensefile>59 <licensefile></licensefile>
60 <policylist>60 <policylist>
61 <policy name="projectPolicy" desc="">61 <policy name="projectPolicy" desc="">
62+ <policyitem type="copyright" name="Copyright (c) 2026 RKH Corp." path=".*" desc="copyright"/>
62 </policy>63 </policy>
63 </policylist>64 </policylist>
64 <filefilterlist>65 <filefilterlist>
@@ -30,6 +30,7 @@
30 "syspara_lite",30 "syspara_lite",
31 "camera_lite",31 "camera_lite",
32 "media_lite",32 "media_lite",
33+ "audio_lite",
33 "permission",34 "permission",
34 "samgr_lite",35 "samgr_lite",
35 "utils_base"36 "utils_base"
@@ -45,10 +46,12 @@
45 "//applications/sample/camera/cameraApp:cameraApp_hap",46 "//applications/sample/camera/cameraApp:cameraApp_hap",
46 "//applications/sample/camera/setting:setting_hap",47 "//applications/sample/camera/setting:setting_hap",
47 "//applications/sample/camera/gallery:gallery_hap",48 "//applications/sample/camera/gallery:gallery_hap",
49+ "//applications/sample/camera/recorder:recorder_hap",
50+ "//applications/sample/camera/gallery:test_jpeg",
48 "//applications/sample/camera/media:media_sample"51 "//applications/sample/camera/media:media_sample"
49 ],52 ],
50 "inner_kits": [],53 "inner_kits": [],
51 "test": []54 "test": []
52 }55 }
53 }56 }
54-}57+}
@@ -13,12 +13,22 @@
13 13 
14import("//build/lite/config/hap_pack.gni")14import("//build/lite/config/hap_pack.gni")
15 15 
16+config("hilog_dir") {
17+ include_dirs =
18+ [ "//base/hiviewdfx/hilog_lite/interfaces/native/innerkits/hilog/" ]
19+}
20+config("hilog_lite_dir") {
21+ include_dirs =
22+ [ "//base/hiviewdfx/hilog_lite/interfaces/native/kits/hilog_lite/" ]
23+}
24+ 
16shared_library("gallery") {25shared_library("gallery") {
17 sources = [26 sources = [
18 "src/gallery_ability.cpp",27 "src/gallery_ability.cpp",
19 "src/gallery_ability_slice.cpp",28 "src/gallery_ability_slice.cpp",
20 "src/picture_ability_slice.cpp",29 "src/picture_ability_slice.cpp",
21 "src/player_ability_slice.cpp",30 "src/player_ability_slice.cpp",
31+ "src/image_decoder.cpp",
22 ]32 ]
23 33 
24 include_dirs = [34 include_dirs = [
@@ -27,6 +37,7 @@ shared_library("gallery") {
27 "${appexecfwk_lite_path}/interfaces/kits/bundle_lite",37 "${appexecfwk_lite_path}/interfaces/kits/bundle_lite",
28 "${aafwk_lite_path}/interfaces/kits/want_lite",38 "${aafwk_lite_path}/interfaces/kits/want_lite",
29 "//foundation/multimedia/media_lite/interfaces/kits/player_lite",39 "//foundation/multimedia/media_lite/interfaces/kits/player_lite",
40+ "//foundation/arkui/ui_lite/frameworks",
30 ]41 ]
31 42 
32 deps = [43 deps = [
@@ -41,6 +52,19 @@ shared_library("gallery") {
41 "//foundation/systemabilitymgr/samgr_lite/samgr:samgr",52 "//foundation/systemabilitymgr/samgr_lite/samgr:samgr",
42 ]53 ]
43 54 
55+ if (defined(ohos_lite)) {
56+ if (ohos_kernel_type == "liteos_m") {
57+ configs += [ ":hilog_lite_dir" ]
58+ deps += [ "//base/hiviewdfx/hilog_lite/frameworks/mini:hilog_lite" ]
59+ } else if (ohos_kernel_type == "liteos_a") {
60+ configs += [ ":hilog_dir" ]
61+ deps += [
62+ "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared",
63+ "//third_party/bounds_checking_function:libsec_shared",
64+ ]
65+ }
66+ }
67+ 
44 ldflags = [ "-shared" ]68 ldflags = [ "-shared" ]
45 69 
46 ldflags += [ "-lstdc++" ]70 ldflags += [ "-lstdc++" ]
@@ -58,7 +82,26 @@ shared_library("gallery") {
58 "OHOS_APPEXECFWK_BMS_BUNDLEMANAGER",82 "OHOS_APPEXECFWK_BMS_BUNDLEMANAGER",
59 "ENABLE_WINDOW=1",83 "ENABLE_WINDOW=1",
60 "ABILITY_WINDOW_SUPPORT",84 "ABILITY_WINDOW_SUPPORT",
85+ "HILOG_ENABLE",
61 ]86 ]
87+ 
88+ # image decode for jpeg/png
89+ deps += [
90+ "//third_party/libjpeg-turbo:libjpeg",
91+ "//third_party/libpng:libpng",
92+ ]
93+ defines += [
94+ "ENABLE_JPEG = 1",
95+ "ENABLE_PNG = 1",
96+ ]
97+}
98+ 
99+copy("test_jpeg") {
100+ sources = [
101+ "resources/photos/photo1.jpeg",
102+ "resources/photos/photo2.jpeg"
103+ ]
104+ outputs = [ "${root_out_dir}/system/internal/{{source_file_part}}" ]
62}105}
63 106 
64hap_pack("gallery_hap") {107hap_pack("gallery_hap") {
@@ -22,6 +22,7 @@
22#include <components/ui_scroll_view.h>22#include <components/ui_scroll_view.h>
23#include "event_listener.h"23#include "event_listener.h"
24#include "gallery_config.h"24#include "gallery_config.h"
25+#include "image_decoder.h"
25 26 
26namespace OHOS {27namespace OHOS {
27class GalleryAbilitySlice : public AbilitySlice {28class GalleryAbilitySlice : public AbilitySlice {
@@ -63,6 +64,7 @@ private:
63 char videoTagIconAbsolutePath[MAX_PATH_LENGTH] = { 0 };64 char videoTagIconAbsolutePath[MAX_PATH_LENGTH] = { 0 };
64 uint16_t pictureOnClickListenerCount_ { 0 };65 uint16_t pictureOnClickListenerCount_ { 0 };
65 EventListener* pictureOnClickListener_[MAX_PICTURE_COUNT] = { nullptr };66 EventListener* pictureOnClickListener_[MAX_PICTURE_COUNT] = { nullptr };
67+ ImageDecoder* imageDecoder_ { nullptr };
66};68};
67}69}
68#endif // OHOS_GALLERY_ABILITY_SLICE_H70#endif // OHOS_GALLERY_ABILITY_SLICE_H
@@ -16,7 +16,11 @@
16#ifndef OHOS_GALLERY_CONFIG_H16#ifndef OHOS_GALLERY_CONFIG_H
17#define OHOS_GALLERY_CONFIG_H17#define OHOS_GALLERY_CONFIG_H
18 18 
19+#include "components/ui_view_group.h"
20+#define GALLERY_BACKGROUND_COLOR Color::ColorTo32(Color::GetColorFromRGB(0xdd, 0xdd, 0xdd))
21+ 
19namespace OHOS {22namespace OHOS {
23+ 
20/** icon resource file path */24/** icon resource file path */
21static const char* const BACK_ICON_PATH = "/gallery/assets/gallery/resources/drawable/ic_back.png";25static const char* const BACK_ICON_PATH = "/gallery/assets/gallery/resources/drawable/ic_back.png";
22static const char* const VIDEO_TAG_ICON_PATH = "/gallery/assets/gallery/resources/drawable/ic_gallery_video_tag.png";26static const char* const VIDEO_TAG_ICON_PATH = "/gallery/assets/gallery/resources/drawable/ic_gallery_video_tag.png";
@@ -29,13 +33,13 @@ static constexpr uint16_t MAX_PATH_LENGTH = 512;
29/** thumb, photo, and video folder path */33/** thumb, photo, and video folder path */
30static const char* const THUMBNAIL_DIRECTORY = "/userdata/thumb";34static const char* const THUMBNAIL_DIRECTORY = "/userdata/thumb";
31static const char* const PHOTO_DIRECTORY = "/userdata/photo";35static const char* const PHOTO_DIRECTORY = "/userdata/photo";
32-static const char* const VIDEO_SOURCE_DIRECTORY = "/userdata/video";36+static const char* const VIDEO_SOURCE_DIRECTORY = "/userdata/photo";
33 37 
34/** general page configuration */38/** general page configuration */
35static constexpr int ROOT_VIEW_POSITION_X = 0;39static constexpr int ROOT_VIEW_POSITION_X = 0;
36static constexpr int ROOT_VIEW_POSITION_Y = 0;40static constexpr int ROOT_VIEW_POSITION_Y = 0;
37-static constexpr int ROOT_VIEW_WIDTH = 960;41+static constexpr int ROOT_VIEW_WIDTH = 1920;
38-static constexpr int ROOT_VIEW_HEIGHT = 480;42+static constexpr int ROOT_VIEW_HEIGHT = 1080;
39static constexpr uint16_t ROOT_VIEW_OPACITY = 255;43static constexpr uint16_t ROOT_VIEW_OPACITY = 255;
40 44 
41static const char* const FONT_NAME = "SourceHanSansSC-Regular.otf";45static const char* const FONT_NAME = "SourceHanSansSC-Regular.otf";
@@ -45,18 +49,20 @@ static constexpr int16_t BACK_ICON_POSITION_X = 38;
45static constexpr int16_t BACK_ICON_POSITION_Y = 17;49static constexpr int16_t BACK_ICON_POSITION_Y = 17;
46 50 
47/** THUMBNAIL */51/** THUMBNAIL */
48-static constexpr int16_t THUMBNAIL_RESOLUTION_X = 120;52+static constexpr int16_t THUMBNAIL_RESOLUTION_X = 236;
49-static constexpr int16_t THUMBNAIL_RESOLUTION_Y = 120;53+static constexpr int16_t THUMBNAIL_RESOLUTION_Y = 236;
50static constexpr int16_t THUMBNAIL_SPACE = 4;54static constexpr int16_t THUMBNAIL_SPACE = 4;
51static constexpr int16_t THUMBNAIL_COLUMN = 3;55static constexpr int16_t THUMBNAIL_COLUMN = 3;
52 56 
53static constexpr int16_t VIDEO_TAG_POSITION_X = 10;57static constexpr int16_t VIDEO_TAG_POSITION_X = 10;
54static constexpr int16_t VIDEO_TAG_POSITION_Y = THUMBNAIL_RESOLUTION_Y - 37;58static constexpr int16_t VIDEO_TAG_POSITION_Y = THUMBNAIL_RESOLUTION_Y - 37;
59+static constexpr int16_t VIDEO_TAG_WIDTH = 27;
60+static constexpr int16_t VIDEO_TAG_HEIGHT = 27;
55 61 
56/** title */62/** title */
57static constexpr int16_t LABEL_POSITION_X = BACK_ICON_POSITION_X + 60;63static constexpr int16_t LABEL_POSITION_X = BACK_ICON_POSITION_X + 60;
58static constexpr int16_t LABEL_POSITION_Y = 0;64static constexpr int16_t LABEL_POSITION_Y = 0;
59-static constexpr int16_t LABEL_WIDTH = 100;65+static constexpr int16_t LABEL_WIDTH = 200;
60static constexpr int16_t LABEL_HEIGHT = 70;66static constexpr int16_t LABEL_HEIGHT = 70;
61static constexpr uint16_t GALLERY_FONT_SIZE = 25;67static constexpr uint16_t GALLERY_FONT_SIZE = 25;
62static constexpr uint16_t GALLERY_DELETE_FONT_SIZE = 22;68static constexpr uint16_t GALLERY_DELETE_FONT_SIZE = 22;
@@ -91,5 +97,6 @@ static constexpr uint16_t SLIDER_WIDTH = ROOT_VIEW_WIDTH - SLIDER_X - TOTAL_TIME
91static constexpr uint16_t KNOB_WIDTH = 25;97static constexpr uint16_t KNOB_WIDTH = 25;
92 98 
93static constexpr uint16_t PLAYER_FONT_SIZE = 18;99static constexpr uint16_t PLAYER_FONT_SIZE = 18;
100+ 
94} // namespace OHOS101} // namespace OHOS
95#endif // OHOS_GALLERY_CONFIG_H102#endif // OHOS_GALLERY_CONFIG_H
@@ -0,0 +1,70 @@
1+/*
2+ * Copyright (c) 2026 RKH Corp.
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+#ifndef GALLERY_LOG_H
17+#define GALLERY_LOG_H
18+ 
19+#ifdef HILOG_ENABLE
20+ 
21+#ifndef LOG_DOMAIN
22+#define LOG_DOMAIN 0xD0000
23+#endif
24+ 
25+#ifndef LOG_TAG
26+#define LOG_TAG "[GALLERY]"
27+#endif
28+ 
29+#include <hilog/log.h>
30+ 
31+#ifdef __cplusplus
32+extern "C" {
33+#endif
34+ 
35+#define FILE_NAME (strrchr((__FILE__), '/') ? strrchr((__FILE__), '/') + 1 : (__FILE__))
36+ 
37+#define LOGD(fmt, ...) HILOG_DEBUG(LOG_APP, "[%s:%d] " fmt, FILE_NAME, __LINE__, ##__VA_ARGS__)
38+#define LOGI(fmt, ...) HILOG_INFO(LOG_APP, "[%s:%d] " fmt, FILE_NAME, __LINE__, ##__VA_ARGS__)
39+#define LOGW(fmt, ...) HILOG_WARN(LOG_APP, "[%s:%d] " fmt, FILE_NAME, __LINE__, ##__VA_ARGS__)
40+#define LOGE(fmt, ...) HILOG_ERROR(LOG_APP, "[%s:%d] " fmt, FILE_NAME, __LINE__, ##__VA_ARGS__)
41+#define LOGF(fmt, ...) HILOG_FATAL(LOG_APP, "[%s:%d] " fmt, FILE_NAME, __LINE__, ##__VA_ARGS__)
42+ 
43+#ifdef __cplusplus
44+}
45+#endif
46+ 
47+#else
48+ 
49+#include <stdio.h>
50+#include <string.h>
51+ 
52+#ifdef __cplusplus
53+extern "C" {
54+#endif
55+ 
56+#define FILE_NAME (strrchr((__FILE__), '/') ? strrchr((__FILE__), '/') + 1 : (__FILE__))
57+ 
58+#define LOGD(fmt, ...) printf("[D][GALLERY][%s:%d] " fmt "\n", FILE_NAME, __LINE__, ##__VA_ARGS__)
59+#define LOGI(fmt, ...) printf("[I][GALLERY][%s:%d] " fmt "\n", FILE_NAME, __LINE__, ##__VA_ARGS__)
60+#define LOGW(fmt, ...) printf("[W][GALLERY][%s:%d] " fmt "\n", FILE_NAME, __LINE__, ##__VA_ARGS__)
61+#define LOGE(fmt, ...) printf("[E][GALLERY][%s:%d] " fmt "\n", FILE_NAME, __LINE__, ##__VA_ARGS__)
62+#define LOGF(fmt, ...) printf("[F][GALLERY][%s:%d] " fmt "\n", FILE_NAME, __LINE__, ##__VA_ARGS__)
63+ 
64+#ifdef __cplusplus
65+}
66+#endif
67+ 
68+#endif
69+ 
70+#endif /* GALLERY_LOG_H */
@@ -0,0 +1,71 @@
1+/*
2+ * Copyright (c) 2026 RKH Corp.
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+#ifndef GALLERY_IMAGE_DECODER_H
17+#define GALLERY_IMAGE_DECODER_H
18+ 
19+#include <memory>
20+#include <string>
21+#include <functional>
22+#include <thread>
23+#include <vector>
24+#include <queue>
25+#include <mutex>
26+#include <condition_variable>
27+#include <atomic>
28+ 
29+#include <common/image.h>
30+#include <ability_event_handler.h>
31+ 
32+namespace OHOS {
33+ 
34+class ImageDecoder {
35+public:
36+ ImageDecoder(AbilityEventHandler* handler, size_t threadCount = 1);
37+ 
38+ ~ImageDecoder();
39+ 
40+ void DecodeImage(const std::string& imagePath, std::function<void(ImageInfo)> uiCallback);
41+ 
42+ void Start();
43+ void Stop();
44+ bool IsRunning();
45+ 
46+private:
47+ struct DecodeTask {
48+ std::string imagePath;
49+ std::function<void(ImageInfo)> callback;
50+ };
51+ 
52+ void WorkerThread();
53+ bool TryGetTask(DecodeTask& task);
54+ void HandleTask(const DecodeTask& task);
55+ void NotifyCallback(const DecodeTask& task, const ImageInfo& imageInfo);
56+ 
57+ ImageInfo DoDecode(const std::string& imagePath);
58+ 
59+private:
60+ std::vector<std::thread> workerThreads_; // 工作线程池
61+ std::queue<DecodeTask> taskQueue_; // 任务队列
62+ std::mutex queueMutex_; // 队列互斥锁
63+ std::condition_variable taskCond_; // 任务条件变量
64+ std::atomic<bool> isRunning_; // 运行状态标记
65+ int maxThreadCount_; // 最大任务个数
66+ 
67+ AbilityEventHandler *eventHandler_ = nullptr;
68+};
69+ 
70+}
71+#endif // GALLERY_IMAGE_DECODER_H
@@ -19,6 +19,7 @@
19#include <ability_loader.h>19#include <ability_loader.h>
20#include "components/ui_image_view.h"20#include "components/ui_image_view.h"
21#include "components/ui_view_group.h"21#include "components/ui_view_group.h"
22+#include "components/ui_label.h"
22#include "event_listener.h"23#include "event_listener.h"
23#include "gallery_config.h"24#include "gallery_config.h"
24 25 
@@ -36,12 +37,13 @@ protected:
36 37 
37private:38private:
38 void Clear();39 void Clear();
39- void InitTitle();40+ void InitTitle(const char* imageName);
40 void InitPicture(const char* path);41 void InitPicture(const char* path);
41 42 
42 RootView* rootView_ { nullptr };43 RootView* rootView_ { nullptr };
43 UIViewGroup* backArea_ { nullptr };44 UIViewGroup* backArea_ { nullptr };
44 UIImageView* backIcon_ { nullptr };45 UIImageView* backIcon_ { nullptr };
46+ UILabel* titleLabel_ { nullptr };
45 EventListener* backIconListener_ { nullptr };47 EventListener* backIconListener_ { nullptr };
46 UIImageView* picture_ { nullptr };48 UIImageView* picture_ { nullptr };
47 char backIconAbsolutePath[MAX_PATH_LENGTH] = { 0 };49 char backIconAbsolutePath[MAX_PATH_LENGTH] = { 0 };
@@ -122,7 +122,7 @@ private:
122 void Clear();122 void Clear();
123 void ShowErrorTips();123 void ShowErrorTips();
124 void SetUpRootView();124 void SetUpRootView();
125- void SetUpBackArea(const char* pathHeader);125+ void SetUpBackArea(const char* pathHeader, const char* imageName);
126 void SetUpVideoPlayer(const Want &want);126 void SetUpVideoPlayer(const Want &want);
127 bool SetUpSurfaceView();127 bool SetUpSurfaceView();
128 void SetUpProgress(int64_t duration);128 void SetUpProgress(int64_t duration);
@@ -137,6 +137,7 @@ private:
137 RootView* rootView_ { nullptr };137 RootView* rootView_ { nullptr };
138 UIViewGroup* backArea_ { nullptr };138 UIViewGroup* backArea_ { nullptr };
139 UIImageView* backIcon_ { nullptr };139 UIImageView* backIcon_ { nullptr };
140+ UILabel* titleLabel_ { nullptr };
140 UISurfaceView* surfaceView_ { nullptr };141 UISurfaceView* surfaceView_ { nullptr };
141 UIViewGroup* animatorGroup_ { nullptr };142 UIViewGroup* animatorGroup_ { nullptr };
142 UIToggleButton* toggleButton_ { nullptr };143 UIToggleButton* toggleButton_ { nullptr };
@@ -0,0 +1,20 @@
1+# Copyright (c) 2026 RKH Corp.
2+# Licensed under the Apache License, Version 2.0 (the "License");
3+# you may not use this file except in compliance with the License.
4+# You may obtain a copy of the License at
5+#
6+# http://www.apache.org/licenses/LICENSE-2.0
7+#
8+# Unless required by applicable law or agreed to in writing, software
9+# distributed under the License is distributed on an "AS IS" BASIS,
10+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+# See the License for the specific language governing permissions and
12+# limitations under the License.
13+ 
14+copy("test_jpeg") {
15+ sources = [
16+ "photo1.jpeg",
17+ "photo2.jpeg"
18+ ]
19+ outputs = [ "${root_out_dir}/system/internal/{{source_file_part}}" ]
20+}
@@ -14,39 +14,39 @@
14 */14 */
15 15 
16#include "gallery_ability.h"16#include "gallery_ability.h"
17+#include "gallery_log.h"
17 18 
18namespace OHOS {19namespace OHOS {
19REGISTER_AA(GalleryAbility)20REGISTER_AA(GalleryAbility)
20 21 
21void GalleryAbility::OnStart(const Want &want)22void GalleryAbility::OnStart(const Want &want)
22{23{
23- printf("GalleryAbility::OnStart\n");24+ LOGI("GalleryAbility::OnStart");
24 SetMainRoute("GalleryAbilitySlice");25 SetMainRoute("GalleryAbilitySlice");
25- 
26 Ability::OnStart(want);26 Ability::OnStart(want);
27}27}
28 28 
29void GalleryAbility::OnInactive()29void GalleryAbility::OnInactive()
30{30{
31- printf("GalleryAbility::OnInactive\n");31+ LOGI("GalleryAbility::OnInactive");
32 Ability::OnInactive();32 Ability::OnInactive();
33}33}
34 34 
35void GalleryAbility::OnActive(const Want &want)35void GalleryAbility::OnActive(const Want &want)
36{36{
37- printf("GalleryAbility::OnActive\n");37+ LOGI("GalleryAbility::OnActive");
38 Ability::OnActive(want);38 Ability::OnActive(want);
39}39}
40 40 
41void GalleryAbility::OnBackground()41void GalleryAbility::OnBackground()
42{42{
43- printf("GalleryAbility::OnBackground\n");43+ LOGI("GalleryAbility::OnBackground");
44 Ability::OnBackground();44 Ability::OnBackground();
45}45}
46 46 
47void GalleryAbility::OnStop()47void GalleryAbility::OnStop()
48{48{
49- printf("GalleryAbility::OnStop\n");49+ LOGI("GalleryAbility::OnStop");
50 Ability::OnStop();50 Ability::OnStop();
51}51}
52}52}
@@ -16,24 +16,29 @@
16#include "gallery_ability_slice.h"16#include "gallery_ability_slice.h"
17#include "ability_env.h"17#include "ability_env.h"
18#include "ability_manager.h"18#include "ability_manager.h"
19+#include <ability_event_handler.h>
19#include "picture_ability_slice.h"20#include "picture_ability_slice.h"
20 21 
21#include "gfx_utils/file.h"22#include "gfx_utils/file.h"
23+#include "gfx_utils/mem_api.h"
22#include "securec.h"24#include "securec.h"
23 25 
26+#include "gallery_log.h"
27+#include "image_decoder.h"
28+ 
24namespace OHOS {29namespace OHOS {
25REGISTER_AS(GalleryAbilitySlice)30REGISTER_AS(GalleryAbilitySlice)
26 31 
27GalleryAbilitySlice::~GalleryAbilitySlice()32GalleryAbilitySlice::~GalleryAbilitySlice()
28{33{
29- printf("~GalleryAbilitySlice() | start \n");34+ LOGI("~GalleryAbilitySlice() | start");
30 Clear();35 Clear();
31- printf("~GalleryAbilitySlice() | end \n");36+ LOGI("~GalleryAbilitySlice() | end");
32}37}
33 38 
34void GalleryAbilitySlice::Clear()39void GalleryAbilitySlice::Clear()
35{40{
36- printf("GalleryAbilitySlice::Clear() | start \n");41+ LOGI("GalleryAbilitySlice::Clear() | start");
37 if (backIcon_ != nullptr) {42 if (backIcon_ != nullptr) {
38 delete backIcon_;43 delete backIcon_;
39 backIcon_ = nullptr;44 backIcon_ = nullptr;
@@ -58,6 +63,10 @@ void GalleryAbilitySlice::Clear()
58 delete deleteLabel_;63 delete deleteLabel_;
59 deleteLabel_ = nullptr;64 deleteLabel_ = nullptr;
60 }65 }
66+ if (imageDecoder_ != nullptr) {
67+ delete imageDecoder_;
68+ imageDecoder_ = nullptr;
69+ }
61 70 
62 ClearThumb();71 ClearThumb();
63 72 
@@ -65,12 +74,12 @@ void GalleryAbilitySlice::Clear()
65 RootView::DestroyWindowRootView(rootView_);74 RootView::DestroyWindowRootView(rootView_);
66 rootView_ = nullptr;75 rootView_ = nullptr;
67 }76 }
68- printf("GalleryAbilitySlice::Clear() | end \n");77+ LOGI("GalleryAbilitySlice::Clear() | end");
69}78}
70 79 
71void GalleryAbilitySlice::ClearThumb()80void GalleryAbilitySlice::ClearThumb()
72{81{
73- printf("GalleryAbilitySlice::ClearThumb() | start \n");82+ LOGI("GalleryAbilitySlice::ClearThumb() | start");
74 if (picContainer_ != nullptr) {83 if (picContainer_ != nullptr) {
75 delete picContainer_;84 delete picContainer_;
76 picContainer_ = nullptr;85 picContainer_ = nullptr;
@@ -94,12 +103,12 @@ void GalleryAbilitySlice::ClearThumb()
94 }103 }
95 pictureCount_ = 0;104 pictureCount_ = 0;
96 pictureOnClickListenerCount_ = 0;105 pictureOnClickListenerCount_ = 0;
97- printf("GalleryAbilitySlice::ClearThumb() | end \n");106+ LOGI("GalleryAbilitySlice::ClearThumb() | end");
98}107}
99 108 
100void GalleryAbilitySlice::ClearPictureList(const UIView* view)109void GalleryAbilitySlice::ClearPictureList(const UIView* view)
101{110{
102- printf("GalleryAbilitySlice::ClearPictureList() | start \n");111+ LOGI("GalleryAbilitySlice::ClearPictureList() | start");
103 if (view == nullptr || !(view->IsViewGroup())) {112 if (view == nullptr || !(view->IsViewGroup())) {
104 return;113 return;
105 }114 }
@@ -113,12 +122,12 @@ void GalleryAbilitySlice::ClearPictureList(const UIView* view)
113 delete child;122 delete child;
114 child = childNext;123 child = childNext;
115 }124 }
116- printf("GalleryAbilitySlice::ClearPictureList() | end \n");125+ LOGI("GalleryAbilitySlice::ClearPictureList() | end");
117}126}
118 127 
119void GalleryAbilitySlice::InitTitle()128void GalleryAbilitySlice::InitTitle()
120{129{
121- printf("GalleryAbilitySlice::InitTitle | start \n");130+ LOGI("GalleryAbilitySlice::InitTitle | start");
122 backIcon_ = new UIImageView();131 backIcon_ = new UIImageView();
123 backIcon_->SetPosition(BACK_ICON_POSITION_X, BACK_ICON_POSITION_Y);132 backIcon_->SetPosition(BACK_ICON_POSITION_X, BACK_ICON_POSITION_Y);
124 backIcon_->SetSrc(backIconAbsolutePath);133 backIcon_->SetSrc(backIconAbsolutePath);
@@ -130,9 +139,9 @@ void GalleryAbilitySlice::InitTitle()
130 backArea_->SetTouchable(true);139 backArea_->SetTouchable(true);
131 140 
132 auto onClick = [this] (UIView& view, const Event& event) -> bool {141 auto onClick = [this] (UIView& view, const Event& event) -> bool {
133- printf("############ Next AS enter #############\n");142+ LOGI("############ Next AS enter #############");
134 TerminateAbility();143 TerminateAbility();
135- printf("############ Next AS exit #############\n");144+ LOGI("############ Next AS exit #############");
136 return true;145 return true;
137 };146 };
138 backIconListener_ = new EventListener(onClick, nullptr);147 backIconListener_ = new EventListener(onClick, nullptr);
@@ -143,6 +152,8 @@ void GalleryAbilitySlice::InitTitle()
143 titleLabel_->SetPosition(LABEL_POSITION_X, LABEL_POSITION_Y, LABEL_WIDTH, LABEL_HEIGHT);152 titleLabel_->SetPosition(LABEL_POSITION_X, LABEL_POSITION_Y, LABEL_WIDTH, LABEL_HEIGHT);
144 titleLabel_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT, UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);153 titleLabel_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT, UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);
145 titleLabel_->SetFont(FONT_NAME, GALLERY_FONT_SIZE);154 titleLabel_->SetFont(FONT_NAME, GALLERY_FONT_SIZE);
155+ titleLabel_->SetStyle(STYLE_TEXT_COLOR, Color::Black().full);
156+ titleLabel_->SetStyle(STYLE_TEXT_OPA, OPA_OPAQUE);
146 titleLabel_->SetText("照片");157 titleLabel_->SetText("照片");
147 158 
148 deleteLabel_ = new UILabel();159 deleteLabel_ = new UILabel();
@@ -151,12 +162,14 @@ void GalleryAbilitySlice::InitTitle()
151 deleteLabel_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT,162 deleteLabel_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT,
152 UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);163 UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);
153 deleteLabel_->SetFont(FONT_NAME, GALLERY_DELETE_FONT_SIZE);164 deleteLabel_->SetFont(FONT_NAME, GALLERY_DELETE_FONT_SIZE);
165+ deleteLabel_->SetStyle(STYLE_TEXT_COLOR, Color::Black().full);
166+ deleteLabel_->SetStyle(STYLE_TEXT_OPA, OPA_OPAQUE);
154 deleteLabel_->SetText("全部删除");167 deleteLabel_->SetText("全部删除");
155 deleteLabel_->SetTouchable(true);168 deleteLabel_->SetTouchable(true);
156 auto deleteClick = [this] (UIView& view, const Event& event) -> bool {169 auto deleteClick = [this] (UIView& view, const Event& event) -> bool {
157- printf("############ DeleteAllData click enter #############\n");170+ LOGI("############ DeleteAllData click enter #############");
158 DeleteAllData();171 DeleteAllData();
159- printf("############ DeleteAllData click exit #############\n");172+ LOGI("############ DeleteAllData click exit #############");
160 return true;173 return true;
161 };174 };
162 deleteClickListener_ = new EventListener(deleteClick, nullptr);175 deleteClickListener_ = new EventListener(deleteClick, nullptr);
@@ -170,11 +183,12 @@ void GalleryAbilitySlice::InitTitle()
170 183 
171void GalleryAbilitySlice::InitPictureList()184void GalleryAbilitySlice::InitPictureList()
172{185{
173- printf("GalleryAbilitySlice::InitPictureList | start \n");186+ LOGI("GalleryAbilitySlice::InitPictureList | start");
174 picContainer_ = new UIScrollView();187 picContainer_ = new UIScrollView();
175 picContainer_->SetPosition(0, LABEL_POSITION_Y + LABEL_HEIGHT);188 picContainer_->SetPosition(0, LABEL_POSITION_Y + LABEL_HEIGHT);
176- picContainer_->Resize(ROOT_VIEW_WIDTH, (THUMBNAIL_RESOLUTION_Y + THUMBNAIL_SPACE) * THUMBNAIL_COLUMN);189+ picContainer_->Resize(ROOT_VIEW_WIDTH, ROOT_VIEW_HEIGHT - (LABEL_POSITION_Y + LABEL_HEIGHT));
177 picContainer_->SetStyle(STYLE_BACKGROUND_OPA, 0);190 picContainer_->SetStyle(STYLE_BACKGROUND_OPA, 0);
191+ picContainer_->SetStyle(STYLE_BACKGROUND_COLOR, Color::Silver().full);
178 rootView_->Add(picContainer_);192 rootView_->Add(picContainer_);
179 193 
180 picList_ = new UIViewGroup();194 picList_ = new UIViewGroup();
@@ -190,23 +204,25 @@ void GalleryAbilitySlice::InitPictureList()
190 totalHeight += THUMBNAIL_RESOLUTION_Y + THUMBNAIL_SPACE;204 totalHeight += THUMBNAIL_RESOLUTION_Y + THUMBNAIL_SPACE;
191 }205 }
192 picList_->Resize(ROOT_VIEW_WIDTH, totalHeight);206 picList_->Resize(ROOT_VIEW_WIDTH, totalHeight);
193- printf("------------ totalHeight : %d ------------", totalHeight);207+ LOGI("------------ totalHeight : %d ------------", totalHeight);
194 picContainer_->Add(picList_);208 picContainer_->Add(picList_);
195}209}
196 210 
197void GalleryAbilitySlice::AddAllPictures(const Point& pos, int16_t numInLine)211void GalleryAbilitySlice::AddAllPictures(const Point& pos, int16_t numInLine)
198{212{
199- printf("GalleryAbilitySlice::AddAllPictures | start | %d\n", numInLine);213+ LOGI("GalleryAbilitySlice::AddAllPictures | start | %d", numInLine);
200 Point imagePos = pos;214 Point imagePos = pos;
201- DIR* drip = opendir(THUMBNAIL_DIRECTORY);215+ LOGI("opendir: %s", PHOTO_DIRECTORY);
216+ DIR* drip = opendir(PHOTO_DIRECTORY);
202 if (drip == nullptr) {217 if (drip == nullptr) {
203 return;218 return;
204 }219 }
205 struct dirent* info = nullptr;220 struct dirent* info = nullptr;
206 while ((info = readdir(drip)) != nullptr && pictureCount_ < MAX_PICTURE_COUNT) {221 while ((info = readdir(drip)) != nullptr && pictureCount_ < MAX_PICTURE_COUNT) {
222+ LOGI("readdir for: %s", info->d_name);
207 uint16_t imageNameLen = static_cast<uint16_t>(strlen(info->d_name));223 uint16_t imageNameLen = static_cast<uint16_t>(strlen(info->d_name));
208 if (imageNameLen > MAX_PATH_LENGTH || (strcmp(info->d_name, ".") == 0) || (strcmp(info->d_name, "..") == 0)) {224 if (imageNameLen > MAX_PATH_LENGTH || (strcmp(info->d_name, ".") == 0) || (strcmp(info->d_name, "..") == 0)) {
209- printf("GalleryAbilitySlice::AddAllPictures | imageNameLen > MAX_PATH_LENGTH | %d\n", imageNameLen);225+ LOGW("GalleryAbilitySlice::AddAllPictures | imageNameLen > MAX_PATH_LENGTH | %d", imageNameLen);
210 continue;226 continue;
211 }227 }
212 char* imageName = new char[imageNameLen + 1]();228 char* imageName = new char[imageNameLen + 1]();
@@ -214,18 +230,19 @@ void GalleryAbilitySlice::AddAllPictures(const Point& pos, int16_t numInLine)
214 pictureName_[pictureCount_] = imageName;230 pictureName_[pictureCount_] = imageName;
215 pictureCount_++;231 pictureCount_++;
216 232 
217- uint16_t pathLen = static_cast<uint16_t>(strlen(THUMBNAIL_DIRECTORY)) + imageNameLen + 1;233+ uint16_t pathLen = static_cast<uint16_t>(strlen(PHOTO_DIRECTORY)) + imageNameLen + 1;
218 if (pathLen > MAX_PATH_LENGTH) {234 if (pathLen > MAX_PATH_LENGTH) {
219- printf("GalleryAbilitySlice::AddAllPictures | pathLen > MAX_PATH_LENGTH | %d\n", pathLen);235+ LOGW("GalleryAbilitySlice::AddAllPictures | pathLen > MAX_PATH_LENGTH | %d", pathLen);
220 continue;236 continue;
221 }237 }
222 char* imagePath = new char[pathLen + 1]();238 char* imagePath = new char[pathLen + 1]();
223- if (sprintf_s(imagePath, pathLen + 1, "%s/%s", THUMBNAIL_DIRECTORY, info->d_name) < 0) {239+ if (sprintf_s(imagePath, pathLen + 1, "%s/%s", PHOTO_DIRECTORY, info->d_name) < 0) {
224- printf("GalleryAbilitySlice::AddAllPictures | sprintf_s error\n");240+ LOGE("GalleryAbilitySlice::AddAllPictures | sprintf_s error");
225 delete[] imagePath;241 delete[] imagePath;
226 continue;242 continue;
227 }243 }
228 244 
245+ LOGI("add image: pos:[%d, %d], name:%s, path:%s", imagePos.x, imagePos.y, imageName, imagePath);
229 picList_->Add(CreateImageItem(imagePos, imageName, imagePath));246 picList_->Add(CreateImageItem(imagePos, imageName, imagePath));
230 delete[] imagePath;247 delete[] imagePath;
231 248 
@@ -245,15 +262,10 @@ UIView* GalleryAbilitySlice::CreateImageItem(const Point& pos, const char* image
245 UIImageView* imageView = new UIImageView();262 UIImageView* imageView = new UIImageView();
246 imageView->SetAutoEnable(false);263 imageView->SetAutoEnable(false);
247 imageView->Resize(THUMBNAIL_RESOLUTION_X, THUMBNAIL_RESOLUTION_Y);264 imageView->Resize(THUMBNAIL_RESOLUTION_X, THUMBNAIL_RESOLUTION_Y);
248- imageView->SetSrc(imagePath);
249 pictureOnClickListener_[pictureOnClickListenerCount_] = GetImageClickListener(imageName);265 pictureOnClickListener_[pictureOnClickListenerCount_] = GetImageClickListener(imageName);
250 imageView->SetOnClickListener(pictureOnClickListener_[pictureOnClickListenerCount_++]);266 imageView->SetOnClickListener(pictureOnClickListener_[pictureOnClickListenerCount_++]);
251 imageView->SetTouchable(true);267 imageView->SetTouchable(true);
252- 268+ imageView->SetResizeMode(UIImageView::FILL);
253- if (strncmp(imageName, PHOTO_PREFIX, strlen(PHOTO_PREFIX)) == 0) {
254- imageView->SetPosition(pos.x, pos.y);
255- return imageView;
256- }
257 imageView->SetPosition(0, 0);269 imageView->SetPosition(0, 0);
258 270 
259 UIViewGroup* imageItem = new UIViewGroup();271 UIViewGroup* imageItem = new UIViewGroup();
@@ -261,15 +273,43 @@ UIView* GalleryAbilitySlice::CreateImageItem(const Point& pos, const char* image
261 imageItem->SetPosition(pos.x, pos.y, THUMBNAIL_RESOLUTION_X, THUMBNAIL_RESOLUTION_Y);273 imageItem->SetPosition(pos.x, pos.y, THUMBNAIL_RESOLUTION_X, THUMBNAIL_RESOLUTION_Y);
262 imageItem->SetTouchable(true);274 imageItem->SetTouchable(true);
263 imageItem->SetOnClickListener(imageView->GetOnClickListener());275 imageItem->SetOnClickListener(imageView->GetOnClickListener());
264- 
265- UIImageView* videoTag = new UIImageView();
266- videoTag->SetPosition(VIDEO_TAG_POSITION_X, VIDEO_TAG_POSITION_Y);
267- videoTag->SetSrc(videoTagIconAbsolutePath);
268- videoTag->SetTouchable(true);
269- videoTag->SetOnClickListener(imageView->GetOnClickListener());
270- 
271 imageItem->Add(imageView);276 imageItem->Add(imageView);
272- imageItem->Add(videoTag);277+ 
278+ std::string filePath(imagePath);
279+ if (filePath.find("mp4") != std::string::npos) {
280+ UIImageView* videoTag = new UIImageView();
281+ std::string videoTagFielPath = videoTagIconAbsolutePath;
282+ videoTag->SetPosition(VIDEO_TAG_POSITION_X, VIDEO_TAG_POSITION_Y, VIDEO_TAG_WIDTH, VIDEO_TAG_HEIGHT);
283+ videoTag->SetTouchable(true);
284+ videoTag->SetOnClickListener(imageView->GetOnClickListener());
285+ imageDecoder_->DecodeImage(videoTagFielPath, [videoTag, videoTagFielPath](ImageInfo imageInfo) {
286+ LOGI("do SetSrc for img, filePath:%s, dataSize:%u", videoTagFielPath.c_str(), imageInfo.dataSize);
287+ videoTag->SetSrc(&imageInfo);
288+ });
289+ 
290+ UILabel* labelView = new UILabel();
291+ labelView->SetPosition(0, 0, THUMBNAIL_RESOLUTION_X, THUMBNAIL_RESOLUTION_Y);
292+ labelView->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER,
293+ UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);
294+ labelView->SetLineBreakMode(UILabel::LineBreakMode::LINE_BREAK_ELLIPSIS);
295+ labelView->SetFont(FONT_NAME, GALLERY_FONT_SIZE);
296+ labelView->SetStyle(STYLE_TEXT_COLOR, Color::White().full);
297+ labelView->SetStyle(STYLE_TEXT_OPA, OPA_OPAQUE);
298+ labelView->SetText(imageName);
299+ 
300+ imageItem->SetStyle(STYLE_BACKGROUND_COLOR, Color::Black().full);
301+ imageItem->SetStyle(STYLE_BACKGROUND_OPA, OPA_OPAQUE);
302+ imageItem->Add(videoTag);
303+ imageItem->Add(labelView);
304+ } else {
305+ std::string fileName = imageName;
306+ std::string filePath = imagePath;
307+ static int num = 0;
308+ imageDecoder_->DecodeImage(filePath, [imageView, filePath](ImageInfo imageInfo) {
309+ LOGI("do SetSrc for img, filePath:%s, dataSize:%u", filePath.c_str(), imageInfo.dataSize);
310+ imageView->SetSrc(&imageInfo);
311+ });
312+ }
273 313 
274 return imageItem;314 return imageItem;
275}315}
@@ -277,28 +317,29 @@ UIView* GalleryAbilitySlice::CreateImageItem(const Point& pos, const char* image
277EventListener* GalleryAbilitySlice::GetImageClickListener(const char* path)317EventListener* GalleryAbilitySlice::GetImageClickListener(const char* path)
278{318{
279 auto onClick = [this, path] (UIView& view, const Event& event) -> bool {319 auto onClick = [this, path] (UIView& view, const Event& event) -> bool {
280- printf("############ Next AS enter #############\n");320+ LOGI("############ Next AS enter #############");
281 Want wantData = { nullptr };321 Want wantData = { nullptr };
282- printf("------- imagePath: %s \n", path);322+ LOGI("------- imagePath: %s ", path);
283 bool ret = SetWantData(&wantData, path, strlen(path) + 1);323 bool ret = SetWantData(&wantData, path, strlen(path) + 1);
284 if (!ret) {324 if (!ret) {
285- printf("############ SetWantData error #############\n");325+ LOGE("############ SetWantData error #############");
286 return ret;326 return ret;
287 }327 }
288 AbilitySlice* nextSlice = nullptr;328 AbilitySlice* nextSlice = nullptr;
289- if (strncmp(path, PHOTO_PREFIX, strlen(PHOTO_PREFIX)) == 0) {329+ std::string filePath(path);
290- printf("--------- enter PictureAbilitySlice \n");330+ if (filePath.find("jpg") != std::string::npos) {
331+ LOGI("--------- enter PictureAbilitySlice");
291 nextSlice = AbilityLoader::GetInstance().GetAbilitySliceByName("PictureAbilitySlice");332 nextSlice = AbilityLoader::GetInstance().GetAbilitySliceByName("PictureAbilitySlice");
292 } else {333 } else {
293- printf("--------- enter PlayerAbilitySlice \n");334+ LOGI("--------- enter PlayerAbilitySlice");
294 nextSlice = AbilityLoader::GetInstance().GetAbilitySliceByName("PlayerAbilitySlice");335 nextSlice = AbilityLoader::GetInstance().GetAbilitySliceByName("PlayerAbilitySlice");
295 }336 }
296 if (nextSlice == nullptr) {337 if (nextSlice == nullptr) {
297- printf("undefined nextSlice\n");338+ LOGW("undefined nextSlice");
298 } else {339 } else {
299 Present(*nextSlice, wantData);340 Present(*nextSlice, wantData);
300 }341 }
301- printf("############ Next AS exit #############\n");342+ LOGI("############ Next AS exit #############");
302 return true;343 return true;
303 };344 };
304 return new EventListener(onClick, nullptr);345 return new EventListener(onClick, nullptr);
@@ -328,23 +369,23 @@ void GalleryAbilitySlice::DeleteAllFilesInDir(const char* path)
328 uint16_t fileNameLen = static_cast<uint16_t>(strlen(info->d_name));369 uint16_t fileNameLen = static_cast<uint16_t>(strlen(info->d_name));
329 uint16_t pathLen = static_cast<uint16_t>(strlen(path)) + fileNameLen + 1;370 uint16_t pathLen = static_cast<uint16_t>(strlen(path)) + fileNameLen + 1;
330 if (pathLen > MAX_PATH_LENGTH) {371 if (pathLen > MAX_PATH_LENGTH) {
331- printf("GalleryAbilitySlice::AddAllPictures | pathLen > MAX_PATH_LENGTH | %d\n", pathLen);372+ LOGW("GalleryAbilitySlice::AddAllPictures | pathLen > MAX_PATH_LENGTH | %d", pathLen);
332 continue;373 continue;
333 }374 }
334 char* filePath = new char[pathLen + 1]();375 char* filePath = new char[pathLen + 1]();
335 if (sprintf_s(filePath, pathLen + 1, "%s/%s", path, info->d_name) < 0) {376 if (sprintf_s(filePath, pathLen + 1, "%s/%s", path, info->d_name) < 0) {
336- printf("GalleryAbilitySlice::AddAllPictures | sprintf_s error\n");377+ LOGE("GalleryAbilitySlice::AddAllPictures | sprintf_s error");
337 delete[] filePath;378 delete[] filePath;
338 continue;379 continue;
339 }380 }
340 if (unlink(filePath) != 0) {381 if (unlink(filePath) != 0) {
341- printf("unlink file error | %s\n", filePath);382+ LOGE("unlink file error | %s", filePath);
342 }383 }
343 delete[] filePath;384 delete[] filePath;
344 }385 }
345 delete info;386 delete info;
346 closedir(drip);387 closedir(drip);
347- printf("GalleryAbilitySlice::DeleteAllFilesInDir() | success | %s\n", path);388+ LOGI("GalleryAbilitySlice::DeleteAllFilesInDir() | success | %s", path);
348}389}
349 390 
350void GalleryAbilitySlice::OnStart(const Want &want)391void GalleryAbilitySlice::OnStart(const Want &want)
@@ -354,18 +395,20 @@ void GalleryAbilitySlice::OnStart(const Want &want)
354 rootView_ = RootView::GetWindowRootView();395 rootView_ = RootView::GetWindowRootView();
355 rootView_->SetPosition(ROOT_VIEW_POSITION_X, ROOT_VIEW_POSITION_Y);396 rootView_->SetPosition(ROOT_VIEW_POSITION_X, ROOT_VIEW_POSITION_Y);
356 rootView_->Resize(ROOT_VIEW_WIDTH, ROOT_VIEW_HEIGHT);397 rootView_->Resize(ROOT_VIEW_WIDTH, ROOT_VIEW_HEIGHT);
357- rootView_->SetStyle(STYLE_BACKGROUND_COLOR, Color::Black().full);398+ rootView_->SetStyle(STYLE_BACKGROUND_COLOR, Color::White().full);
358 399 
359 const char* pathHeader = GetSrcPath();400 const char* pathHeader = GetSrcPath();
360 if (sprintf_s(backIconAbsolutePath, MAX_PATH_LENGTH, "%s%s", pathHeader, BACK_ICON_PATH) < 0) {401 if (sprintf_s(backIconAbsolutePath, MAX_PATH_LENGTH, "%s%s", pathHeader, BACK_ICON_PATH) < 0) {
361- printf("GalleryAbilitySlice::OnStart | backIconAbsolutePath error");402+ LOGE("GalleryAbilitySlice::OnStart | backIconAbsolutePath error");
362 return;403 return;
363 }404 }
364 if (sprintf_s(videoTagIconAbsolutePath, MAX_PATH_LENGTH, "%s%s", pathHeader, VIDEO_TAG_ICON_PATH) < 0) {405 if (sprintf_s(videoTagIconAbsolutePath, MAX_PATH_LENGTH, "%s%s", pathHeader, VIDEO_TAG_ICON_PATH) < 0) {
365- printf("GalleryAbilitySlice::OnStart | videoTagIconAbsolutePath error");406+ LOGE("GalleryAbilitySlice::OnStart | videoTagIconAbsolutePath error");
366 return;407 return;
367 }408 }
368 409 
410+ imageDecoder_ = new ImageDecoder(AbilityEventHandler::GetCurrentHandler(), 1);
411+ 
369 InitTitle();412 InitTitle();
370 InitPictureList();413 InitPictureList();
371 SetUIContent(rootView_);414 SetUIContent(rootView_);
@@ -373,25 +416,28 @@ void GalleryAbilitySlice::OnStart(const Want &want)
373 416 
374void GalleryAbilitySlice::OnInactive()417void GalleryAbilitySlice::OnInactive()
375{418{
376- printf("GalleryAbilitySlice::OnInactive\n");419+ LOGI("GalleryAbilitySlice::OnInactive");
377 AbilitySlice::OnInactive();420 AbilitySlice::OnInactive();
378}421}
379 422 
380void GalleryAbilitySlice::OnActive(const Want &want)423void GalleryAbilitySlice::OnActive(const Want &want)
381{424{
382- printf("GalleryAbilitySlice::OnActive\n");425+ LOGI("GalleryAbilitySlice::OnActive");
383 AbilitySlice::OnActive(want);426 AbilitySlice::OnActive(want);
427+ if (!imageDecoder_->IsRunning()) {
428+ imageDecoder_->Start();
429+ }
384}430}
385 431 
386void GalleryAbilitySlice::OnBackground()432void GalleryAbilitySlice::OnBackground()
387{433{
388- printf("GalleryAbilitySlice::OnBackground\n");434+ LOGI("GalleryAbilitySlice::OnBackground");
389 AbilitySlice::OnBackground();435 AbilitySlice::OnBackground();
390}436}
391 437 
392void GalleryAbilitySlice::OnStop()438void GalleryAbilitySlice::OnStop()
393{439{
394- printf("GalleryAbilitySlice::OnStop\n");440+ LOGI("GalleryAbilitySlice::OnStop");
395 AbilitySlice::OnStop();441 AbilitySlice::OnStop();
396 Clear();442 Clear();
397}443}
@@ -0,0 +1,222 @@
1+/*
2+ * Copyright (c) 2026 RKH Corp.
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 <chrono>
17+#include <iostream>
18+#include <sstream>
19+ 
20+#include <ability_event_handler.h>
21+#include <gfx_utils/file.h>
22+ 
23+#if ENABLE_JPEG
24+#include "jpeglib.h"
25+#endif
26+#if ENABLE_PNG
27+#include "png.h"
28+#endif
29+#include <imgdecode/file_img_decoder.h>
30+#include <imgdecode/jpeg_img_decoder.h>
31+#include <imgdecode/png_img_decoder.h>
32+ 
33+#include "image_decoder.h"
34+#include "gallery_log.h"
35+ 
36+namespace OHOS {
37+ 
38+enum GalleryImageType {
39+ IMG_PNG,
40+ IMG_JPEG,
41+ IMG_GIF,
42+ IMG_UNKNOWN,
43+};
44+const static uint8_t IMG_BYTES_TO_CHECK = 4; // 4: check 4 bytes of image file
45+ 
46+GalleryImageType CheckImgType(const char* src)
47+{
48+ char buf[IMG_BYTES_TO_CHECK] = {0};
49+#ifdef _WIN32
50+ int32_t fd = open(src, O_RDONLY | O_BINARY);
51+#else
52+ int32_t fd = open(src, O_RDONLY);
53+#endif
54+ if (fd < 0) {
55+ LOGE("can't open %s\n", src);
56+ return IMG_UNKNOWN;
57+ }
58+ if (read(fd, buf, IMG_BYTES_TO_CHECK) != IMG_BYTES_TO_CHECK) {
59+ close(fd);
60+ return IMG_UNKNOWN;
61+ }
62+ close(fd);
63+#if ENABLE_PNG
64+ if (!png_sig_cmp(reinterpret_cast<png_const_bytep>(buf), 0, IMG_BYTES_TO_CHECK)) {
65+ return IMG_PNG;
66+ }
67+#endif
68+#if ENABLE_JPEG
69+ // 0xFF 0xD8: JPEG file's header
70+ if ((static_cast<uint8_t>(buf[0]) == 0xFF) && (static_cast<uint8_t>(buf[1]) == 0xD8)) {
71+ return IMG_JPEG;
72+ }
73+#endif
74+ if ((static_cast<uint8_t>(buf[0]) == 0x47) && (static_cast<uint8_t>(buf[1]) == 0x49) &&
75+ (static_cast<uint8_t>(buf[2]) == 0x46)) { // 2: array index of GIF file's header
76+ return IMG_GIF;
77+ }
78+ return IMG_UNKNOWN;
79+}
80+ 
81+ImageDecoder::ImageDecoder(AbilityEventHandler* handler, size_t threadCount) : isRunning_(false),
82+ maxThreadCount_(threadCount),
83+ eventHandler_(handler)
84+{
85+}
86+ 
87+ImageDecoder::~ImageDecoder()
88+{
89+ Stop();
90+}
91+ 
92+void ImageDecoder::DecodeImage(const std::string& imagePath, std::function<void(ImageInfo)> uiCallback)
93+{
94+ std::lock_guard<std::mutex> lock(queueMutex_);
95+ taskQueue_.push({imagePath, uiCallback});
96+ taskCond_.notify_one();
97+}
98+ 
99+void ImageDecoder::Start()
100+{
101+ isRunning_ = true;
102+ for (size_t i = 0; i < maxThreadCount_; ++i) {
103+ workerThreads_.emplace_back(&ImageDecoder::WorkerThread, this);
104+ }
105+}
106+ 
107+void ImageDecoder::Stop()
108+{
109+ if (!isRunning_) return;
110+ 
111+ isRunning_ = false;
112+ taskCond_.notify_all();
113+ 
114+ for (auto& thread : workerThreads_) {
115+ if (thread.joinable()) {
116+ thread.join();
117+ }
118+ }
119+ workerThreads_.clear();
120+}
121+ 
122+bool ImageDecoder::IsRunning()
123+{
124+ return isRunning_;
125+}
126+ 
127+bool ImageDecoder::TryGetTask(DecodeTask& task)
128+{
129+ std::unique_lock<std::mutex> lock(queueMutex_);
130+ taskCond_.wait(lock, [this]() {
131+ return !isRunning_ || !taskQueue_.empty();
132+ });
133+ 
134+ if (isRunning_ && !taskQueue_.empty()) {
135+ task = std::move(taskQueue_.front());
136+ taskQueue_.pop();
137+ return true;
138+ }
139+ return false;
140+}
141+ 
142+void ImageDecoder::HandleTask(const DecodeTask& task)
143+{
144+ if (!isRunning_) {
145+ return;
146+ }
147+ 
148+ ImageInfo imageInfo = DoDecode(task.imagePath);
149+ NotifyCallback(task, imageInfo);
150+}
151+ 
152+void ImageDecoder::NotifyCallback(const DecodeTask& task, const ImageInfo& imageInfo)
153+{
154+ if (eventHandler_) {
155+ eventHandler_->PostTask([task, imageInfo]() {
156+ task.callback(imageInfo);
157+ });
158+ }
159+}
160+ 
161+void ImageDecoder::WorkerThread()
162+{
163+ pid_t tid = gettid();
164+ LOGI("WorkerThread started, tid:%d", tid);
165+ while (isRunning_) {
166+ DecodeTask task;
167+ bool hasTask = TryGetTask(task);
168+ if (hasTask) {
169+ HandleTask(task);
170+ }
171+ }
172+ LOGI("WorkerThread exit, tid: %d", tid);
173+}
174+ 
175+ImageInfo ImageDecoder::DoDecode(const std::string& imagePath)
176+{
177+ pid_t tid = gettid();
178+ LOGI("DoDecode start. path: %s (tid:%d)", imagePath.c_str(), tid);
179+ FileImgDecoder::ImgResDsc desc = {0};
180+ FileImgDecoder* decoder = nullptr;
181+ GalleryImageType type = CheckImgType(imagePath.c_str());
182+ if (type == IMG_PNG) {
183+ decoder = &(PngImgDecoder::GetInstance());
184+ } else if (type == IMG_JPEG) {
185+ decoder = &(JpegImgDecoder::GetInstance());
186+ } else {
187+ LOGE("DoDecode imageType(%d) not supported!", type);
188+ return desc.imgInfo;
189+ }
190+ 
191+ if (decoder == nullptr) {
192+ LOGE("DoDecode decoder is null");
193+ return desc.imgInfo;
194+ }
195+ 
196+ desc.path = imagePath.c_str();
197+ RetCode ret = decoder->Open(desc);
198+ if (ret != RetCode::OK) {
199+ LOGE("DoDecode decoder open failed");
200+ return desc.imgInfo;
201+ }
202+ 
203+ ret = decoder->GetHeader(desc);
204+ if (ret != RetCode::OK) {
205+ LOGE("DoDecode decoder get header failed");
206+ decoder->Close(desc);
207+ return desc.imgInfo;
208+ }
209+ 
210+ ret = decoder->ReadToCache(desc);
211+ if (ret != RetCode::OK) {
212+ LOGE("DoDecode decoder read to cache failed");
213+ decoder->Close(desc);
214+ return desc.imgInfo;
215+ }
216+ 
217+ LOGI("DoDecode end. path: %s (tid:%d) result:%d, imageInfo.data:%p", imagePath.c_str(),
218+ tid, ret, desc.imgInfo.data);
219+ return desc.imgInfo;
220+}
221+}
222+ 
@@ -18,6 +18,7 @@
18#include "gallery_config.h"18#include "gallery_config.h"
19#include "gfx_utils/file.h"19#include "gfx_utils/file.h"
20#include "securec.h"20#include "securec.h"
21+#include "gallery_log.h"
21 22 
22namespace OHOS {23namespace OHOS {
23REGISTER_AS(PictureAbilitySlice)24REGISTER_AS(PictureAbilitySlice)
@@ -29,7 +30,7 @@ PictureAbilitySlice::~PictureAbilitySlice()
29 30 
30void PictureAbilitySlice::Clear()31void PictureAbilitySlice::Clear()
31{32{
32- printf("PictureAbilitySlice::Clear() | start \n");33+ LOGI("PictureAbilitySlice::Clear() | start");
33 if (backIcon_ != nullptr) {34 if (backIcon_ != nullptr) {
34 delete backIcon_;35 delete backIcon_;
35 backIcon_ = nullptr;36 backIcon_ = nullptr;
@@ -50,12 +51,12 @@ void PictureAbilitySlice::Clear()
50 RootView::DestroyWindowRootView(rootView_);51 RootView::DestroyWindowRootView(rootView_);
51 rootView_ = nullptr;52 rootView_ = nullptr;
52 }53 }
53- printf("PictureAbilitySlice::Clear() | end \n");54+ LOGI("PictureAbilitySlice::Clear() | end");
54}55}
55 56 
56-void PictureAbilitySlice::InitTitle()57+void PictureAbilitySlice::InitTitle(const char* imageName)
57{58{
58- printf("PictureAbilitySlice::InitTitle | start \n");59+ LOGI("PictureAbilitySlice::InitTitle | start");
59 backIcon_ = new UIImageView();60 backIcon_ = new UIImageView();
60 backIcon_->SetPosition(BACK_ICON_POSITION_X, BACK_ICON_POSITION_Y);61 backIcon_->SetPosition(BACK_ICON_POSITION_X, BACK_ICON_POSITION_Y);
61 backIcon_->SetSrc(backIconAbsolutePath);62 backIcon_->SetSrc(backIconAbsolutePath);
@@ -67,40 +68,50 @@ void PictureAbilitySlice::InitTitle()
67 backArea_->SetTouchable(true);68 backArea_->SetTouchable(true);
68 69 
69 auto onClick = [this] (UIView &view, const Event &event) -> bool {70 auto onClick = [this] (UIView &view, const Event &event) -> bool {
70- printf("############ terminate AS enter #############\n");71+ LOGI("############ terminate AS enter #############\n");
71 Terminate();72 Terminate();
72- printf("############ terminate AS exit #############\n");73+ LOGI("############ terminate AS exit #############\n");
73 return true;74 return true;
74 };75 };
75 backIconListener_ = new EventListener(onClick, nullptr);76 backIconListener_ = new EventListener(onClick, nullptr);
76 backIcon_->SetOnClickListener(backIconListener_);77 backIcon_->SetOnClickListener(backIconListener_);
77 backArea_->SetOnClickListener(backIconListener_);78 backArea_->SetOnClickListener(backIconListener_);
78 79 
80+ titleLabel_ = new UILabel();
81+ titleLabel_->SetPosition(LABEL_POSITION_X, LABEL_POSITION_Y, LABEL_WIDTH, LABEL_HEIGHT);
82+ titleLabel_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT, UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);
83+ titleLabel_->SetFont(FONT_NAME, GALLERY_FONT_SIZE);
84+ titleLabel_->SetStyle(STYLE_TEXT_COLOR, Color::Black().full);
85+ titleLabel_->SetStyle(STYLE_TEXT_OPA, OPA_OPAQUE);
86+ titleLabel_->SetText(imageName);
87+ 
79 backArea_->Add(backIcon_);88 backArea_->Add(backIcon_);
80 rootView_->Add(backArea_);89 rootView_->Add(backArea_);
90+ rootView_->Add(titleLabel_);
81}91}
82 92 
83void PictureAbilitySlice::InitPicture(const char* path)93void PictureAbilitySlice::InitPicture(const char* path)
84{94{
85- printf("PictureAbilitySlice::InitPicture | start | %s\n", path);95+ LOGI("PictureAbilitySlice::InitPicture | start | %s\n", path);
86 picture_ = new UIImageView();96 picture_ = new UIImageView();
87 picture_->SetSrc(path);97 picture_->SetSrc(path);
88 int16_t imageWidth = picture_->GetWidth();98 int16_t imageWidth = picture_->GetWidth();
89 int16_t imageHeight = picture_->GetHeight();99 int16_t imageHeight = picture_->GetHeight();
100+ LOGI("imageWidth:%d, imageHeight:%d", imageWidth, imageHeight);
90 if (imageWidth > ROOT_VIEW_WIDTH || imageHeight > ROOT_VIEW_HEIGHT) {101 if (imageWidth > ROOT_VIEW_WIDTH || imageHeight > ROOT_VIEW_HEIGHT) {
91 TransformMap transMap(picture_->GetOrigRect());102 TransformMap transMap(picture_->GetOrigRect());
92 float scaleWidth = 1.0;103 float scaleWidth = 1.0;
93 float scaleHeight = 1.0;104 float scaleHeight = 1.0;
94 if (imageWidth > ROOT_VIEW_WIDTH) {105 if (imageWidth > ROOT_VIEW_WIDTH) {
95 scaleWidth = static_cast<float>(ROOT_VIEW_WIDTH) / imageWidth;106 scaleWidth = static_cast<float>(ROOT_VIEW_WIDTH) / imageWidth;
96- printf("########## scaleWidth: %f \n", scaleWidth);107+ LOGI("########## scaleWidth: %f", scaleWidth);
97 }108 }
98 if (imageHeight > ROOT_VIEW_HEIGHT) {109 if (imageHeight > ROOT_VIEW_HEIGHT) {
99 scaleHeight = static_cast<float>(ROOT_VIEW_HEIGHT) / imageHeight;110 scaleHeight = static_cast<float>(ROOT_VIEW_HEIGHT) / imageHeight;
100- printf("########## scaleHeight: %f \n", scaleHeight);111+ LOGI("########## scaleHeight: %f", scaleHeight);
101 }112 }
102 float scale = (scaleWidth < scaleHeight) ? scaleWidth : scaleHeight;113 float scale = (scaleWidth < scaleHeight) ? scaleWidth : scaleHeight;
103- printf("########## scale: %f \n", scale);114+ LOGI("########## scale: %f", scale);
104 transMap.Scale(Vector2<float>(scale, scale), Vector2<float>(0, 0));115 transMap.Scale(Vector2<float>(scale, scale), Vector2<float>(0, 0));
105 picture_->SetTransformMap(transMap);116 picture_->SetTransformMap(transMap);
106 picture_->SetTransformAlgorithm(TransformAlgorithm::NEAREST_NEIGHBOR);117 picture_->SetTransformAlgorithm(TransformAlgorithm::NEAREST_NEIGHBOR);
@@ -109,7 +120,7 @@ void PictureAbilitySlice::InitPicture(const char* path)
109 }120 }
110 int16_t imagePosX = (ROOT_VIEW_WIDTH - imageWidth) / 2; // 2: half121 int16_t imagePosX = (ROOT_VIEW_WIDTH - imageWidth) / 2; // 2: half
111 int16_t imagePosY = (ROOT_VIEW_HEIGHT - imageHeight) / 2; // 2: half122 int16_t imagePosY = (ROOT_VIEW_HEIGHT - imageHeight) / 2; // 2: half
112- printf("########## image pos x: %d | y: %d \n", imagePosX, imagePosY);123+ LOGI("########## image pos x: %d | y: %d", imagePosX, imagePosY);
113 picture_->SetPosition(imagePosX, imagePosY);124 picture_->SetPosition(imagePosX, imagePosY);
114 125 
115 rootView_->Add(picture_);126 rootView_->Add(picture_);
@@ -117,23 +128,23 @@ void PictureAbilitySlice::InitPicture(const char* path)
117 128 
118void PictureAbilitySlice::OnStart(const Want &want)129void PictureAbilitySlice::OnStart(const Want &want)
119{130{
120- printf("######### PictureAbilitySlice::OnStart\n");131+ LOGI("######### PictureAbilitySlice::OnStart\n");
121- printf("receive the data -> %s\n", reinterpret_cast<char*>(want.data));132+ LOGI("receive the data -> %s\n", reinterpret_cast<char*>(want.data));
122 AbilitySlice::OnStart(want);133 AbilitySlice::OnStart(want);
123 134 
124 rootView_ = RootView::GetWindowRootView();135 rootView_ = RootView::GetWindowRootView();
125 rootView_->SetPosition(ROOT_VIEW_POSITION_X, ROOT_VIEW_POSITION_Y);136 rootView_->SetPosition(ROOT_VIEW_POSITION_X, ROOT_VIEW_POSITION_Y);
126 rootView_->Resize(ROOT_VIEW_WIDTH, ROOT_VIEW_HEIGHT);137 rootView_->Resize(ROOT_VIEW_WIDTH, ROOT_VIEW_HEIGHT);
127- rootView_->SetStyle(STYLE_BACKGROUND_COLOR, Color::Black().full);138+ rootView_->SetStyle(STYLE_BACKGROUND_COLOR, Color::White().full);
128 139 
129 uint16_t imagePathLen = strlen(PHOTO_DIRECTORY) + strlen(reinterpret_cast<char*>(want.data)) + 1;140 uint16_t imagePathLen = strlen(PHOTO_DIRECTORY) + strlen(reinterpret_cast<char*>(want.data)) + 1;
130 if (imagePathLen > MAX_PATH_LENGTH) {141 if (imagePathLen > MAX_PATH_LENGTH) {
131- printf("---- imagePathLen > MAX_PATH_LENGTH | %d", imagePathLen);142+ LOGI("---- imagePathLen > MAX_PATH_LENGTH | %d", imagePathLen);
132 return;143 return;
133 }144 }
134 char* imagePath = new char[imagePathLen + 1]();145 char* imagePath = new char[imagePathLen + 1]();
135 if (sprintf_s(imagePath, imagePathLen + 1, "%s/%s", PHOTO_DIRECTORY, reinterpret_cast<char*>(want.data)) < 0) {146 if (sprintf_s(imagePath, imagePathLen + 1, "%s/%s", PHOTO_DIRECTORY, reinterpret_cast<char*>(want.data)) < 0) {
136- printf("PictureAbilitySlice::OnStart | imagePath\n");147+ LOGE("PictureAbilitySlice::OnStart | imagePath\n");
137 delete[] imagePath;148 delete[] imagePath;
138 imagePath = nullptr;149 imagePath = nullptr;
139 return;150 return;
@@ -141,14 +152,14 @@ void PictureAbilitySlice::OnStart(const Want &want)
141 152 
142 const char* pathHeader = GetSrcPath();153 const char* pathHeader = GetSrcPath();
143 if (sprintf_s(backIconAbsolutePath, MAX_PATH_LENGTH, "%s%s", pathHeader, BACK_ICON_PATH) < 0) {154 if (sprintf_s(backIconAbsolutePath, MAX_PATH_LENGTH, "%s%s", pathHeader, BACK_ICON_PATH) < 0) {
144- printf("PictureAbilitySlice::OnStart | backIconAbsolutePath\n");155+ LOGE("PictureAbilitySlice::OnStart | backIconAbsolutePath\n");
145 delete[] imagePath;156 delete[] imagePath;
146 imagePath = nullptr;157 imagePath = nullptr;
147 return;158 return;
148 }159 }
149 160 
150 InitPicture(imagePath);161 InitPicture(imagePath);
151- InitTitle();162+ InitTitle(reinterpret_cast<char*>(want.data));
152 delete[] imagePath;163 delete[] imagePath;
153 164 
154 SetUIContent(rootView_);165 SetUIContent(rootView_);
@@ -156,25 +167,25 @@ void PictureAbilitySlice::OnStart(const Want &want)
156 167 
157void PictureAbilitySlice::OnInactive()168void PictureAbilitySlice::OnInactive()
158{169{
159- printf("PictureAbilitySlice::OnInactive\n");170+ LOGI("PictureAbilitySlice::OnInactive\n");
160 AbilitySlice::OnInactive();171 AbilitySlice::OnInactive();
161}172}
162 173 
163void PictureAbilitySlice::OnActive(const Want &want)174void PictureAbilitySlice::OnActive(const Want &want)
164{175{
165- printf("PictureAbilitySlice::OnActive\n");176+ LOGI("PictureAbilitySlice::OnActive\n");
166 AbilitySlice::OnActive(want);177 AbilitySlice::OnActive(want);
167}178}
168 179 
169void PictureAbilitySlice::OnBackground()180void PictureAbilitySlice::OnBackground()
170{181{
171- printf("PictureAbilitySlice::OnBackground\n");182+ LOGI("PictureAbilitySlice::OnBackground\n");
172 AbilitySlice::OnBackground();183 AbilitySlice::OnBackground();
173}184}
174 185 
175void PictureAbilitySlice::OnStop()186void PictureAbilitySlice::OnStop()
176{187{
177- printf("PictureAbilitySlice::OnStop\n");188+ LOGI("PictureAbilitySlice::OnStop\n");
178 AbilitySlice::OnStop();189 AbilitySlice::OnStop();
179 Clear();190 Clear();
180}191}
@@ -21,6 +21,7 @@
21#include "ability_manager.h"21#include "ability_manager.h"
22#include "components/ui_image_view.h"22#include "components/ui_image_view.h"
23#include "gfx_utils/file.h"23#include "gfx_utils/file.h"
24+#include "gallery_log.h"
24 25 
25using OHOS::Media::Player;26using OHOS::Media::Player;
26using OHOS::Media::Source;27using OHOS::Media::Source;
@@ -32,11 +33,11 @@ REGISTER_AS(PlayerAbilitySlice)
32 33 
33PlayerAbilitySlice::~PlayerAbilitySlice()34PlayerAbilitySlice::~PlayerAbilitySlice()
34{35{
35- printf("################ ~PlayerAbilitySlice enter\n");36+ LOGI("################ ~PlayerAbilitySlice enter");
36 37 
37 /** released in DestoryPlayer(). */38 /** released in DestoryPlayer(). */
38 39 
39- printf("################ ~PlayerAbilitySlice exit\n");40+ LOGI("################ ~PlayerAbilitySlice exit");
40}41}
41 42 
42std::shared_ptr<Player> PlayerAbilitySlice::CreatePlayer()43std::shared_ptr<Player> PlayerAbilitySlice::CreatePlayer()
@@ -50,7 +51,7 @@ std::shared_ptr<Player> PlayerAbilitySlice::CreatePlayer()
50 51 
51void PlayerAbilitySlice::Clear()52void PlayerAbilitySlice::Clear()
52{53{
53- printf("PlayerAbilitySlice::Clear | enter\n");54+ LOGI("PlayerAbilitySlice::Clear | enter");
54 if (backIconListener_ != nullptr) {55 if (backIconListener_ != nullptr) {
55 delete backIconListener_;56 delete backIconListener_;
56 backIconListener_ = nullptr;57 backIconListener_ = nullptr;
@@ -103,7 +104,7 @@ void PlayerAbilitySlice::Clear()
103 RootView::DestroyWindowRootView(rootView_);104 RootView::DestroyWindowRootView(rootView_);
104 rootView_ = nullptr;105 rootView_ = nullptr;
105 }106 }
106- printf("PlayerAbilitySlice::Clear() | end\n");107+ LOGI("PlayerAbilitySlice::Clear() | end");
107}108}
108 109 
109void PlayerAbilitySlice::ShowErrorTips()110void PlayerAbilitySlice::ShowErrorTips()
@@ -115,9 +116,10 @@ void PlayerAbilitySlice::ShowErrorTips()
115 errorTips_->SetFont(FONT_NAME, GALLERY_FONT_SIZE);116 errorTips_->SetFont(FONT_NAME, GALLERY_FONT_SIZE);
116 errorTips_->SetText("视频播放错误");117 errorTips_->SetText("视频播放错误");
117 118 
118- rootView_->Add(backArea_);
119 rootView_->Add(errorTips_);119 rootView_->Add(errorTips_);
120+ rootView_->Add(backArea_);
120 rootView_->Add(backIcon_);121 rootView_->Add(backIcon_);
122+ rootView_->Add(titleLabel_);
121 SetUIContent(rootView_);123 SetUIContent(rootView_);
122}124}
123 125 
@@ -132,19 +134,21 @@ void PlayerAbilitySlice::SetUpRootView()
132 rootView_->SetStyle(STYLE_BACKGROUND_COLOR, Color::Black().full);134 rootView_->SetStyle(STYLE_BACKGROUND_COLOR, Color::Black().full);
133}135}
134 136 
135-void PlayerAbilitySlice::SetUpBackArea(const char* pathHeader)137+void PlayerAbilitySlice::SetUpBackArea(const char* pathHeader, const char* imageName)
136{138{
137 auto onClick = [this] (UIView &view, const Event &event) -> bool {139 auto onClick = [this] (UIView &view, const Event &event) -> bool {
138- printf("############ PlayerAbilitySlice terminate AS enter #############\n");140+ LOGI("############ PlayerAbilitySlice terminate AS enter #############");
139 Terminate();141 Terminate();
140- printf("############ PlayerAbilitySlice terminate AS exit #############\n");142+ LOGI("############ PlayerAbilitySlice terminate AS exit #############");
141 return true;143 return true;
142 };144 };
143 backIcon_ = new UIImageView();145 backIcon_ = new UIImageView();
144 backIcon_->SetPosition(BACK_ICON_POSITION_X, BACK_ICON_POSITION_Y);146 backIcon_->SetPosition(BACK_ICON_POSITION_X, BACK_ICON_POSITION_Y);
147+ backIcon_->SetStyle(STYLE_BACKGROUND_OPA, 0);
148+ backIcon_->SetStyle(STYLE_BACKGROUND_COLOR, Color::White().full);
145 149 
146 if (sprintf_s(backIconAbsolutePath, MAX_PATH_LENGTH, "%s%s", pathHeader, BACK_ICON_PATH) < 0) {150 if (sprintf_s(backIconAbsolutePath, MAX_PATH_LENGTH, "%s%s", pathHeader, BACK_ICON_PATH) < 0) {
147- printf("PlayerAbilitySlice::OnStart | backIconAbsolutePath | %s\n", pathHeader);151+ LOGE("PlayerAbilitySlice::OnStart | backIconAbsolutePath | %s\n", pathHeader);
148 return;152 return;
149 }153 }
150 backIcon_->SetSrc(backIconAbsolutePath);154 backIcon_->SetSrc(backIconAbsolutePath);
@@ -158,8 +162,17 @@ void PlayerAbilitySlice::SetUpBackArea(const char* pathHeader)
158 backArea_->SetTouchable(true);162 backArea_->SetTouchable(true);
159 backArea_->SetOnClickListener(backIconListener_);163 backArea_->SetOnClickListener(backIconListener_);
160 164 
165+ titleLabel_ = new UILabel();
166+ titleLabel_->SetPosition(LABEL_POSITION_X, LABEL_POSITION_Y, LABEL_WIDTH, LABEL_HEIGHT);
167+ titleLabel_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT, UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);
168+ titleLabel_->SetFont(FONT_NAME, GALLERY_FONT_SIZE);
169+ titleLabel_->SetStyle(STYLE_TEXT_COLOR, Color::Black().full);
170+ titleLabel_->SetStyle(STYLE_TEXT_OPA, OPA_OPAQUE);
171+ titleLabel_->SetText(imageName);
172+ 
161 rootView_->Add(backArea_);173 rootView_->Add(backArea_);
162 rootView_->Add(backIcon_);174 rootView_->Add(backIcon_);
175+ rootView_->Add(titleLabel_);
163}176}
164 177 
165void PlayerAbilitySlice::SetUpVideoPlayer(const Want &want)178void PlayerAbilitySlice::SetUpVideoPlayer(const Want &want)
@@ -173,16 +186,16 @@ void PlayerAbilitySlice::SetUpVideoPlayer(const Want &want)
173 int8_t ret = sprintf_s(videoPlayer_->filePath, videoPathLen + 1, "%s/%s", VIDEO_SOURCE_DIRECTORY,186 int8_t ret = sprintf_s(videoPlayer_->filePath, videoPathLen + 1, "%s/%s", VIDEO_SOURCE_DIRECTORY,
174 reinterpret_cast<char*>(want.data));187 reinterpret_cast<char*>(want.data));
175 if (ret < 0) {188 if (ret < 0) {
176- printf("PlayerAbilitySlice::OnStart | videoPlayer_->filePath | %s\n", reinterpret_cast<char*>(want.data));189+ LOGE("PlayerAbilitySlice::OnStart | videoPlayer_->filePath | %s", reinterpret_cast<char*>(want.data));
177 return;190 return;
178 }191 }
179 ret = sprintf_s(&videoPlayer_->filePath[videoPathLen - strlen(AVAILABEL_SOURCE_TYPE)],192 ret = sprintf_s(&videoPlayer_->filePath[videoPathLen - strlen(AVAILABEL_SOURCE_TYPE)],
180 strlen(AVAILABEL_SOURCE_TYPE) + 1, "%s", AVAILABEL_SOURCE_TYPE);193 strlen(AVAILABEL_SOURCE_TYPE) + 1, "%s", AVAILABEL_SOURCE_TYPE);
181 if (ret < 0) {194 if (ret < 0) {
182- printf("PlayerAbilitySlice::OnStart | videoPlayer_->filePath \n");195+ LOGE("PlayerAbilitySlice::OnStart | videoPlayer_->filePath");
183 return;196 return;
184 }197 }
185- printf("------########### mp4 file path | %s\n", videoPlayer_->filePath);198+ LOGI("------########### mp4 file path | %s", videoPlayer_->filePath);
186 199 
187 videoPlayer_->adapter = PlayerAbilitySlice::CreatePlayer();200 videoPlayer_->adapter = PlayerAbilitySlice::CreatePlayer();
188 std::string uri(videoPlayer_->filePath);201 std::string uri(videoPlayer_->filePath);
@@ -199,15 +212,14 @@ bool PlayerAbilitySlice::SetUpSurfaceView()
199 int32_t width = 0;212 int32_t width = 0;
200 int32_t height = 0;213 int32_t height = 0;
201 videoPlayer_->adapter->GetVideoWidth(width);214 videoPlayer_->adapter->GetVideoWidth(width);
202- printf("[%s,%d] width:%d\n", __func__, __LINE__, width);
203 videoPlayer_->adapter->GetVideoHeight(height);215 videoPlayer_->adapter->GetVideoHeight(height);
204- printf("[%s,%d] height:%d\n", __func__, __LINE__, height);216+ LOGI("width:%d, height:%d", width, height);
205 217 
206 if (width <= 0 || height <= 0) {218 if (width <= 0 || height <= 0) {
207 videoPlayer_->adapter->Release();219 videoPlayer_->adapter->Release();
208 delete videoPlayer_;220 delete videoPlayer_;
209 videoPlayer_ = nullptr;221 videoPlayer_ = nullptr;
210- printf("******** width <= 0 || height <= 0 | return \n");222+ LOGE("******** width <= 0 || height <= 0 | return");
211 ShowErrorTips();223 ShowErrorTips();
212 return false;224 return false;
213 }225 }
@@ -263,7 +275,7 @@ void PlayerAbilitySlice::SetUpAnimatorGroup(const char* pathHeader)
263{275{
264 int64_t duration = 0;276 int64_t duration = 0;
265 videoPlayer_->adapter->GetDuration(duration);277 videoPlayer_->adapter->GetDuration(duration);
266- printf("[%s,%d] GetDuration:%lld\n", __func__, __LINE__, duration);278+ LOGI("[%s,%d] GetDuration:%lld", __func__, __LINE__, duration);
267 279 
268 animatorGroup_ = new UIViewGroup();280 animatorGroup_ = new UIViewGroup();
269 animatorGroup_->SetPosition(0, ROOT_VIEW_HEIGHT - STATUS_BAR_GROUP_HEIGHT,281 animatorGroup_->SetPosition(0, ROOT_VIEW_HEIGHT - STATUS_BAR_GROUP_HEIGHT,
@@ -313,12 +325,12 @@ void PlayerAbilitySlice::SetUpToggleButton(const char* pathHeader)
313 toggleButton_->SetState(true);325 toggleButton_->SetState(true);
314 326 
315 if (sprintf_s(videoPlayAbsolutePath, MAX_PATH_LENGTH, "%s%s", pathHeader, VIDEO_PALY_PATH) < 0) {327 if (sprintf_s(videoPlayAbsolutePath, MAX_PATH_LENGTH, "%s%s", pathHeader, VIDEO_PALY_PATH) < 0) {
316- printf("PlayerAbilitySlice::OnStart | videoPlayAbsolutePath\n");328+ LOGE("PlayerAbilitySlice::OnStart | videoPlayAbsolutePath");
317 return;329 return;
318 }330 }
319 331 
320 if (sprintf_s(videoPauseAbsolutePath, MAX_PATH_LENGTH, "%s%s", pathHeader, VIDEO_PAUSE_PATH) < 0) {332 if (sprintf_s(videoPauseAbsolutePath, MAX_PATH_LENGTH, "%s%s", pathHeader, VIDEO_PAUSE_PATH) < 0) {
321- printf("PlayerAbilitySlice::OnStart | videoPauseAbsolutePath\n");333+ LOGE("PlayerAbilitySlice::OnStart | videoPauseAbsolutePath");
322 return;334 return;
323 }335 }
324 toggleButton_->SetImages(videoPauseAbsolutePath, videoPlayAbsolutePath);336 toggleButton_->SetImages(videoPauseAbsolutePath, videoPlayAbsolutePath);
@@ -335,7 +347,7 @@ void PlayerAbilitySlice::SetUpToggleButton(const char* pathHeader)
335 347 
336void PlayerAbilitySlice::OnStart(const Want &want)348void PlayerAbilitySlice::OnStart(const Want &want)
337{349{
338- printf("@@@@@ PlayerAbilitySlice::OnStart\n");350+ LOGI("@@@@@ PlayerAbilitySlice::OnStart");
339 AbilitySlice::OnStart(want);351 AbilitySlice::OnStart(want);
340 352 
341 SetUpRootView();353 SetUpRootView();
@@ -347,7 +359,7 @@ void PlayerAbilitySlice::OnStart(const Want &want)
347 if (!SetUpSurfaceView()) {359 if (!SetUpSurfaceView()) {
348 return;360 return;
349 }361 }
350- SetUpBackArea(pathHeader);362+ SetUpBackArea(pathHeader, reinterpret_cast<char*>(want.data));
351 SetUpAnimatorGroup(pathHeader);363 SetUpAnimatorGroup(pathHeader);
352 364 
353 SetUIContent(rootView_);365 SetUIContent(rootView_);
@@ -357,24 +369,24 @@ void PlayerAbilitySlice::OnStart(const Want &want)
357 animator_->SetToggleBtnListener(onClickListener_);369 animator_->SetToggleBtnListener(onClickListener_);
358 animator_->Start();370 animator_->Start();
359 371 
360- printf("## @@@@@ PlayerAbilitySlice::OnStart | end \n");372+ LOGI("## @@@@@ PlayerAbilitySlice::OnStart | end ");
361}373}
362 374 
363void PlayerAbilitySlice::OnInactive()375void PlayerAbilitySlice::OnInactive()
364{376{
365- printf("PlayerAbilitySlice::OnInactive\n");377+ LOGI("PlayerAbilitySlice::OnInactive");
366 AbilitySlice::OnInactive();378 AbilitySlice::OnInactive();
367}379}
368 380 
369void PlayerAbilitySlice::OnActive(const Want &want)381void PlayerAbilitySlice::OnActive(const Want &want)
370{382{
371- printf("PlayerAbilitySlice::OnActive\n");383+ LOGI("PlayerAbilitySlice::OnActive");
372 AbilitySlice::OnActive(want);384 AbilitySlice::OnActive(want);
373}385}
374 386 
375void PlayerAbilitySlice::OnBackground()387void PlayerAbilitySlice::OnBackground()
376{388{
377- printf("PlayerAbilitySlice::OnBackground\n");389+ LOGI("PlayerAbilitySlice::OnBackground");
378 AbilitySlice::OnBackground();390 AbilitySlice::OnBackground();
379}391}
380 392 
@@ -393,7 +405,7 @@ void PlayerAbilitySlice::OnStop()
393 videoPlayer_ = nullptr;405 videoPlayer_ = nullptr;
394 }406 }
395 Clear();407 Clear();
396- printf("PlayerAbilitySlice::OnStop\n");408+ LOGI("PlayerAbilitySlice::OnStop");
397 AbilitySlice::OnStop();409 AbilitySlice::OnStop();
398}410}
399 411 
@@ -448,11 +460,11 @@ bool ToggleBtnListener::OnClick(UIView &view, const ClickEvent& event)
448 if (button_->GetState()) {460 if (button_->GetState()) {
449 videoPlayer_->adapter->Play();461 videoPlayer_->adapter->Play();
450 animator_->Resume();462 animator_->Resume();
451- printf("ToggleBtnListener::OnClick | play\n");463+ LOGI("ToggleBtnListener::OnClick | play");
452 } else {464 } else {
453 videoPlayer_->adapter->Pause();465 videoPlayer_->adapter->Pause();
454 animator_->Pause();466 animator_->Pause();
455- printf("ToggleBtnListener::OnClick | pause\n");467+ LOGI("ToggleBtnListener::OnClick | pause");
456 }468 }
457 button_->Invalidate();469 button_->Invalidate();
458 return true;470 return true;
@@ -64,8 +64,9 @@ void AppInfo::SetButton(UILabelButton* button)
64 button->SetStyle(STYLE_BORDER_RADIUS, BUTTON_RADIUS);64 button->SetStyle(STYLE_BORDER_RADIUS, BUTTON_RADIUS);
65 button->SetStyle(STYLE_BACKGROUND_OPA, TOTAL_OPACITY);65 button->SetStyle(STYLE_BACKGROUND_OPA, TOTAL_OPACITY);
66 button->SetStyle(STYLE_BORDER_OPA, TOTAL_OPACITY);66 button->SetStyle(STYLE_BORDER_OPA, TOTAL_OPACITY);
67- button->SetStyle(STYLE_TEXT_COLOR, Color::ColorTo32(Color::White()));67+ button->SetStyle(STYLE_TEXT_COLOR, Color::ColorTo32(Color::Black()));
68 button->SetImageSrc(appIconDir_, appIconDir_);68 button->SetImageSrc(appIconDir_, appIconDir_);
69+ button->SetImagePosition(buttonHV_.x / BUTTON_IMAGE_POSITION_SCALE, buttonHV_.y / BUTTON_IMAGE_POSITION_SCALE);
69 button_ = button;70 button_ = button;
70}71}
71 72 
@@ -112,7 +112,7 @@ void MainAbilitySlice::OnStart(const Want& want)
112 rootview_->Resize(Screen::GetInstance().GetWidth(), Screen::GetInstance().GetHeight());112 rootview_->Resize(Screen::GetInstance().GetWidth(), Screen::GetInstance().GetHeight());
113 rootview_->SetStyle(STYLE_BACKGROUND_OPA, UN_OPACITY);113 rootview_->SetStyle(STYLE_BACKGROUND_OPA, UN_OPACITY);
114 rootview_->SetStyle(STYLE_BACKGROUND_COLOR, Color::ColorTo32(Color::GetColorFromRGB(0x30, 0x30, 0x30)));114 rootview_->SetStyle(STYLE_BACKGROUND_COLOR, Color::ColorTo32(Color::GetColorFromRGB(0x30, 0x30, 0x30)));
115- 115+ SetImageView();
116 SetHead();116 SetHead();
117 SetTail();117 SetTail();
118 SetSwipe();118 SetSwipe();
@@ -20,23 +20,24 @@
20#include <securec.h>20#include <securec.h>
21 21 
22namespace OHOS {22namespace OHOS {
23-static constexpr int16_t LABLE_TITLE_HEIGHT = 30; // tail lable height23+constexpr int16_t LABLE_TITLE_HEIGHT = 30; // tail lable height
24-static constexpr int16_t LABLE_TAIL_HEIGHT = 30;24+constexpr int16_t LABLE_TAIL_HEIGHT = 30;
25-static constexpr int16_t APP_WIDTH_COUNT = 7; // blank + app + blank + app + blank25+constexpr int16_t APP_WIDTH_COUNT = 7; // blank + app + blank + app + blank
26-static constexpr int16_t APP_HEIGHT_COUNT = 4; // app + lable + app + lable26+constexpr int16_t APP_HEIGHT_COUNT = 4; // app + lable + app + lable
27-static constexpr int16_t MAX_VIEWGROUP = 3; // swipe window count27+constexpr int16_t MAX_VIEWGROUP = 1; // swipe window count
28-static constexpr int16_t APP_ROW_COUNT = 2; // a swipe view app count in row28+constexpr int16_t APP_ROW_COUNT = 2; // a swipe view app count in row
29-static constexpr int16_t APP_COL_COUNT = 3; // a sswipe view app count in col29+constexpr int16_t APP_COL_COUNT = 3; // a sswipe view app count in col
30-static constexpr int16_t LAUNCHER_FOND_ID = 16; // other view fond id30+constexpr int16_t LAUNCHER_FOND_ID = 16; // other view fond id
31-static constexpr int16_t APP_FOND_ID = 16; // app name fond id31+constexpr int16_t APP_FOND_ID = 16; // app name fond id
32-static constexpr int16_t BIGLAUNCHER_FOND_ID = 48; // time big fond id32+constexpr int16_t BIGLAUNCHER_FOND_ID = 48; // time big fond id
33-static constexpr int16_t TOTAL_OPACITY = 0; // transparent33+constexpr int16_t TOTAL_OPACITY = 0; // transparent
34-static constexpr int16_t HALF_OPACITY = 50; // diaphanous34+constexpr int16_t HALF_OPACITY = 50; // diaphanous
35-static constexpr int16_t UN_OPACITY = 255; // opaque35+constexpr int16_t UN_OPACITY = 255; // opaque
36-static constexpr int16_t BUTTON_RADIUS = 20; // app icon radius36+constexpr int16_t BUTTON_RADIUS = 20; // app icon radius
37-static constexpr int16_t LABLE_RADIUS = 0; // lable icon radius37+constexpr int16_t LABLE_RADIUS = 0; // lable icon radius
38-static constexpr int16_t TITLE_LABLE_OPACITY = 255; // translucent38+constexpr int16_t TITLE_LABLE_OPACITY = 255; // translucent
39-static constexpr int16_t GROUP_VIEW_RADIUS = 20; // view radius39+constexpr int16_t GROUP_VIEW_RADIUS = 20; // view radius
40+constexpr int16_t BUTTON_IMAGE_POSITION_SCALE = 4; // scale factor for button image position
40 41 
41#ifndef TMP_BUF_SIZE42#ifndef TMP_BUF_SIZE
42#define TMP_BUF_SIZE 12843#define TMP_BUF_SIZE 128
@@ -0,0 +1,101 @@
1+# Copyright (c) 2026 RKH Corp.
2+# Licensed under the Apache License, Version 2.0 (the "License");
3+# you may not use this file except in compliance with the License.
4+# You may obtain a copy of the License at
5+#
6+# http://www.apache.org/licenses/LICENSE-2.0
7+#
8+# Unless required by applicable law or agreed to in writing, software
9+# distributed under the License is distributed on an "AS IS" BASIS,
10+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+# See the License for the specific language governing permissions and
12+# limitations under the License.
13+ 
14+import("//build/lite/config/hap_pack.gni")
15+ 
16+config("hilog_dir") {
17+ include_dirs =
18+ [ "//base/hiviewdfx/hilog_lite/interfaces/native/innerkits/hilog/" ]
19+}
20+config("hilog_lite_dir") {
21+ include_dirs =
22+ [ "//base/hiviewdfx/hilog_lite/interfaces/native/kits/hilog_lite/" ]
23+}
24+ 
25+shared_library("recorder") {
26+ sources = [
27+ "src/recorder_ability.cpp",
28+ "src/recorder_ability_main_slice.cpp",
29+ "src/recorder_list_adapter.cpp",
30+ "src/media_utils.cpp",
31+ ]
32+ 
33+ include_dirs = [
34+ "include",
35+ "${aafwk_lite_path}/interfaces/kits/ability_lite",
36+ "${appexecfwk_lite_path}/interfaces/kits/bundle_lite",
37+ "${aafwk_lite_path}/interfaces/kits/want_lite",
38+ "//foundation/multimedia/media_lite/interfaces/kits/player_lite",
39+ ]
40+ 
41+ deps = [
42+ "${aafwk_lite_path}/frameworks/ability_lite:aafwk_abilitykit_lite",
43+ "${appexecfwk_lite_path}/frameworks/bundle_lite:bundle",
44+ "//foundation/arkui/ui_lite:ui_lite",
45+ "//foundation/distributeddatamgr/kv_store/interfaces/inner_api/kv_store:kv_store",
46+ "//foundation/graphic/graphic_utils_lite:utils_lite",
47+ "//foundation/graphic/surface_lite",
48+ "//foundation/multimedia/media_lite/frameworks/player_lite:player_lite",
49+ "//foundation/multimedia/media_lite/frameworks/recorder_lite:recorder_lite",
50+ "//foundation/systemabilitymgr/samgr_lite/samgr:samgr",
51+ ]
52+ 
53+ if (defined(ohos_lite)) {
54+ if (ohos_kernel_type == "liteos_m") {
55+ configs += [ ":hilog_lite_dir" ]
56+ deps += [ "//base/hiviewdfx/hilog_lite/frameworks/mini:hilog_lite" ]
57+ } else if (ohos_kernel_type == "liteos_a") {
58+ configs += [ ":hilog_dir" ]
59+ deps += [
60+ "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared",
61+ "//third_party/bounds_checking_function:libsec_shared",
62+ ]
63+ }
64+ }
65+ 
66+ cflags = [ "-Wall" ]
67+ cflags_cc = cflags
68+ ldflags = [ "-shared" ]
69+ ldflags += [ "-lstdc++" ]
70+ ldflags += [ "-lpthread" ]
71+ ldflags += [ "-L$ohos_root_path/sysroot/usr/lib" ]
72+ ldflags += [ "-Wl,-rpath-link=$ohos_root_path/sysroot/usr/lib" ]
73+ ldflags += [
74+ "-lui",
75+ "-lsurface",
76+ "-lplayer_lite",
77+ "-lability",
78+ ]
79+ 
80+ defines = [
81+ "OHOS_APPEXECFWK_BMS_BUNDLEMANAGER",
82+ "ENABLE_WINDOW=1",
83+ "ABILITY_WINDOW_SUPPORT",
84+ "HILOG_ENABLE",
85+ # "USE_RECORDER_FD"
86+ "USE_RECORDER_API",
87+ "USE_PLAYER_API"
88+ ]
89+}
90+ 
91+hap_pack("recorder_hap") {
92+ deps = [ ":recorder" ]
93+ mode = "hap"
94+ json_path = "config.json"
95+ ability_so_path = "$root_out_dir/librecorder.so"
96+ force = "true"
97+ cert_profile = "cert/recorder_AppProvision_Release.p7b"
98+ resources_path = "resources"
99+ hap_name = "recorder"
100+ privatekey = "HOS Application Provision Release"
101+}
Binary files do not support preview
@@ -0,0 +1,89 @@
1+{
2+ "app": {
3+ "bundleName": "com.ohos.recorder",
4+ "vendor": "ohos",
5+ "version": {
6+ "code": 1,
7+ "name": "1.0"
8+ },
9+ "apiVersion": {
10+ "compatible": 3,
11+ "target": 4
12+ }
13+ },
14+ "deviceConfig": {
15+ "default": {
16+ }
17+ },
18+ "module": {
19+ "package": "com.ohos.recorder",
20+ "name": ".MyHarmonyAbilityPackage",
21+ "deviceType": [
22+ "phone",
23+ "tv",
24+ "tablet",
25+ "pc",
26+ "car",
27+ "smartWatch",
28+ "sportsWatch",
29+ "smartVision"
30+ ],
31+ "distro": {
32+ "deliveryWithInstall": true,
33+ "moduleName": "recorder",
34+ "moduleType": "entry"
35+ },
36+ "abilities": [
37+ {
38+ "name": "RecorderAbility",
39+ "icon": "assets/recorder/resources/drawable/recorder.png",
40+ "label": "test app 1",
41+ "launchType": "standard",
42+ "type": "page",
43+ "visible": true
44+ }
45+ ],
46+ "reqPermissions": [
47+ {
48+ "name": "ohos.permission.MODIFY_AUDIO_SETTINGS",
49+ "reason": "SYSTEM_GRANT",
50+ "usedScene": {
51+ "ability": [
52+ ".FormAbility"
53+ ],
54+ "when": "inuse"
55+ }
56+ },
57+ {
58+ "name": "ohos.permission.READ_MEDIA",
59+ "reason": "USER_GRANT",
60+ "usedScene": {
61+ "ability": [
62+ ".FormAbility"
63+ ],
64+ "when": "inuse"
65+ }
66+ },
67+ {
68+ "name": "ohos.permission.READ_MEDIA_AUDIO",
69+ "reason": "USER_GRANT",
70+ "usedScene": {
71+ "ability": [
72+ ".FormAbility"
73+ ],
74+ "when": "inuse"
75+ }
76+ },
77+ {
78+ "name": "ohos.permission.MICROPHONE",
79+ "reason": "USER_GRANT",
80+ "usedScene": {
81+ "ability": [
82+ ".FormAbility"
83+ ],
84+ "when": "inuse"
85+ }
86+ }
87+ ]
88+ }
89+}
@@ -0,0 +1,68 @@
1+/*
2+ * Copyright (c) 2026 RKH Corp.
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+#ifndef OHOS_EVENT_LISTENER_H
17+#define OHOS_EVENT_LISTENER_H
18+ 
19+#include <components/ui_view.h>
20+#include <functional>
21+#include <utility>
22+ 
23+namespace OHOS {
24+using OnEventFunc = std::function<bool(UIView &view, const Event &event)>;
25+ 
26+class EventListener :
27+ public UIView::OnClickListener,
28+ public UIView::OnLongPressListener {
29+public:
30+ EventListener() = delete;
31+ ~EventListener() override = default;
32+ 
33+ EventListener(OnEventFunc onClick, OnEventFunc onLongPress)
34+ {
35+ onClick_ = std::move(onClick);
36+ onLongPress_ = std::move(onLongPress);
37+ }
38+ 
39+ bool OnClick(UIView& view, const ClickEvent &event) override
40+ {
41+ if (!onClick_) {
42+ return false;
43+ }
44+ UIView *currentView = &view;
45+ if (currentView == nullptr) {
46+ return false;
47+ }
48+ return onClick_(*currentView, event);
49+ }
50+ 
51+ bool OnLongPress(UIView& view, const LongPressEvent &event) override
52+ {
53+ if (!onLongPress_) {
54+ return false;
55+ }
56+ UIView *currentView = &view;
57+ if (currentView == nullptr) {
58+ return false;
59+ }
60+ return onLongPress_(*currentView, event);
61+ }
62+ 
63+private:
64+ OnEventFunc onClick_ {};
65+ OnEventFunc onLongPress_ {};
66+};
67+}
68+#endif // OHOS_EVENT_LISTENER_H
@@ -0,0 +1,80 @@
1+/*
2+ * Copyright (c) 2026 RKH Corp.
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+#ifndef OHOS_MEDIA_UTILS_H
17+#define OHOS_MEDIA_UTILS_H
18+ 
19+#include <memory>
20+ 
21+#ifdef USE_RECORDER_API
22+#include <recorder.h>
23+#endif
24+#ifdef USE_PLAYER_API
25+#include <player.h>
26+#endif
27+ 
28+namespace OHOS {
29+class MediaUtils {
30+public:
31+ ~MediaUtils();
32+ 
33+ // Recorder
34+#ifdef USE_RECORDER_API
35+ bool SetRecorderCallback(Media::RecorderCallback* recorderCallback);
36+#endif
37+ bool StartRecord();
38+ bool StopRecord();
39+ 
40+ // Player
41+#ifdef USE_PLAYER_API
42+ bool SetPlayerCallback(Media::PlayerCallback* playerCallback);
43+#endif
44+ bool StartPlay(const char* filePath);
45+ bool PausePlay();
46+ bool StopPlay();
47+ 
48+private:
49+ bool InitRecorder();
50+ bool CloseRecorder();
51+ bool MoveFiles();
52+ bool EnsureRecorderDirectory();
53+ bool StartRecorderService();
54+ 
55+ bool InitPlayer(const char* filePath);
56+ bool ClosePlayer();
57+ 
58+private:
59+#ifdef USE_RECORDER_API
60+ std::shared_ptr<Media::Recorder> recorder_;
61+ Media::RecorderCallback* recorderCallback_ { nullptr };
62+ std::shared_ptr<Media::RecorderCallback> recorderCallbackPtr_;
63+#endif
64+ 
65+#ifdef USE_PLAYER_API
66+ std::shared_ptr<Media::Player> player_;
67+ Media::PlayerCallback* playerCallback_ { nullptr };
68+ std::shared_ptr<Media::PlayerCallback> playerCallbackPtr_;
69+#endif
70+#ifdef USE_RECORDER_FD
71+ int32_t recordFd_ = -1;
72+#endif
73+ 
74+ bool recording_ = false;
75+ bool playing_ = false;
76+ bool paused_ = false;
77+};
78+}
79+ 
80+#endif // OHOS_RECORDER_ABILITY_H
@@ -0,0 +1,32 @@
1+/*
2+ * Copyright (c) 2026 RKH Corp.
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+#ifndef OHOS_RECORDER_ABILITY_H
17+#define OHOS_RECORDER_ABILITY_H
18+ 
19+#include <ability_loader.h>
20+ 
21+namespace OHOS {
22+class RecorderAbility : public Ability {
23+protected:
24+ void OnStart(const Want &want) override;
25+ void OnInactive() override;
26+ void OnActive(const Want &want) override;
27+ void OnBackground() override;
28+ void OnStop() override;
29+};
30+}
31+ 
32+#endif // OHOS_RECORDER_ABILITY_H
@@ -0,0 +1,120 @@
1+/*
2+ * Copyright (c) 2026 RKH Corp.
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+#ifndef OHOS_RECORDER_ABILITY_MAIN_SLICE_H
17+#define OHOS_RECORDER_ABILITY_MAIN_SLICE_H
18+ 
19+#include <ability_slice.h>
20+#include <components/ui_image_view.h>
21+#include <components/ui_label.h>
22+#include <components/ui_list.h>
23+#include <components/abstract_adapter.h>
24+#include <event_listener.h>
25+ 
26+#include "recorder_config.h"
27+#include "recorder_list_adapter.h"
28+#include "media_utils.h"
29+#include "task_helper.h"
30+ 
31+namespace OHOS {
32+class RecorderAbilityMainSlice : public AbilitySlice, Media::PlayerCallback, Media::RecorderCallback {
33+public:
34+ RecorderAbilityMainSlice() = default;
35+ ~RecorderAbilityMainSlice() override;
36+ 
37+public:
38+ // Media::PlayerCallback overrides
39+ void OnPlaybackComplete() override;
40+ void OnError(int32_t errorType, int32_t errorCode) override;
41+ void OnInfo(int type, int extra) override;
42+ void OnVideoSizeChanged(int width, int height) override {}
43+ void OnRewindToComplete() override {}
44+protected:
45+ void OnStart(const Want &want) override;
46+ void OnInactive() override;
47+ void OnActive(const Want &want) override;
48+ void OnBackground() override;
49+ void OnStop() override;
50+ 
51+private:
52+ void InitTitle();
53+ void InitRecordList();
54+ void InitRecordCtrl();
55+ void InitRecordLabels();
56+ void InitRecordButtons();
57+ void InitRecordListeners();
58+ void AddRecordControlsToRoot();
59+ bool InitImagePath(char* absolutePath, const char* pathHeader, const char* resourcePath, const char* errorTag);
60+ void InitRootView();
61+ bool InitIconPaths(const char* pathHeader);
62+ void Start();
63+ void Stop();
64+ void Pause();
65+ void Resume();
66+ void Cancel();
67+ 
68+ // recorder timer
69+ void StartTimer();
70+ void PauseTimer();
71+ void ResumeTimer();
72+ void StopTimer();
73+ void UpdateRecordTime();
74+ void UpdateDurationLabel();
75+ 
76+ void ReloadItems();
77+ 
78+ void OnItemPlay(int16_t index, const RecordItem& item);
79+ void OnItemDelete(int16_t index, const RecordItem& item);
80+ 
81+ RootView* rootView_ { nullptr };
82+ UIViewGroup* titleBar_ { nullptr };
83+ UIImageView* backButton_ { nullptr };
84+ EventListener* backButtonListener_ { nullptr };
85+ UILabel* titleLabel_ { nullptr };
86+ UILabel* noticeLabel_ { nullptr };
87+ UILabel* durationLabel_ { nullptr };
88+ UIImageView* fsImageView_ { nullptr };
89+ 
90+ UIImageView* startButton_ { nullptr }; // start/stop
91+ UIImageView* pauseButton_ { nullptr }; // pause/resume
92+ UIImageView* cancelButton_ { nullptr };
93+ 
94+ EventListener* startButtonListener_ { nullptr };
95+ EventListener* stopButtonListener_ { nullptr };
96+ EventListener* pauseButtonListener_ { nullptr };
97+ EventListener* resumeButtonListener_ { nullptr };
98+ EventListener* cancelButtonListener_ { nullptr };
99+ 
100+ UILabel* listLabel_ { nullptr };
101+ UIList* list_ { nullptr };
102+ RecorderListAdapter* adapter_ { nullptr };
103+ std::string durationTime_;
104+ MediaUtils mediaUtils_;
105+ 
106+ // recorder timer
107+ std::shared_ptr<Task> recordTimeUpdateTask_;
108+ uint32_t lastRecordTime_;
109+ uint32_t recordDuration_;
110+ 
111+ char backIconAbsolutePath[MAX_PATH_LENGTH] = { 0 };
112+ char fsIconAbsolutePath[MAX_PATH_LENGTH] = { 0 };
113+ char startIconAbsolutePath[MAX_PATH_LENGTH] = { 0 };
114+ char stopIconAbsolutePath[MAX_PATH_LENGTH] = { 0 };
115+ char pauseIconAbsolutePath[MAX_PATH_LENGTH] = { 0 };
116+ char resumeIconAbsolutePath[MAX_PATH_LENGTH] = { 0 };
117+ char cancelIconAbsolutePath[MAX_PATH_LENGTH] = { 0 };
118+};
119+}
120+#endif // OHOS_RECORDER_ABILITY_MAIN_SLICE_H
@@ -0,0 +1,52 @@
1+/*
2+ * Copyright (c) 2026 RKH Corp.
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+#ifndef OHOS_RECORDER_ABILITY_SLICE_H
17+#define OHOS_RECORDER_ABILITY_SLICE_H
18+ 
19+#include <ability_slice.h>
20+#include <components/root_view.h>
21+#include <components/ui_label.h>
22+#include <components/ui_image_view.h>
23+#include <event_listener.h>
24+ 
25+#include "recorder_config.h"
26+ 
27+namespace OHOS {
28+class RecorderAbilitySlice : public AbilitySlice {
29+public:
30+ RecorderAbilitySlice() = default;
31+ ~RecorderAbilitySlice() override;
32+protected:
33+ void OnStart(const Want &want) override;
34+ void OnInactive() override;
35+ void OnActive(const Want &want) override;
36+ void OnBackground() override;
37+ void OnStop() override;
38+ 
39+private:
40+ void SetUpRootView();
41+ void SetUpBackArea();
42+ 
43+private:
44+ RootView* rootView_ { nullptr };
45+ UIViewGroup* backArea_ { nullptr };
46+ UIImageView* backIcon_ { nullptr };
47+ UILabel* titleLabel_ { nullptr };
48+ EventListener* backIconListener_ { nullptr };
49+ char backIconAbsolutePath[MAX_PATH_LENGTH] = { 0 };
50+};
51+} // namespace OHOS
52+#endif // OHOS_RECORDER_ABILITY_SLICE_H
@@ -0,0 +1,194 @@
1+/*
2+ * Copyright (c) 2026 RKH Corp.
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+#ifndef OHOS_RECORDER_CONFIG_H
17+#define OHOS_RECORDER_CONFIG_H
18+ 
19+#include "components/ui_view_group.h"
20+ 
21+namespace OHOS {
22+ 
23+/** icon resource file path */
24+static const char* const BACK_ICON_PATH = "/recorder/assets/recorder/resources/drawable/ic_back.png";
25+static const char* const FS_ICON_PATH = "/recorder/assets/recorder/resources/drawable/fs.png";
26+static const char* const START_ICON_PATH = "/recorder/assets/recorder/resources/drawable/start.png";
27+static const char* const STOP_ICON_PATH = "/recorder/assets/recorder/resources/drawable/stop.png";
28+static const char* const PAUSE_ICON_PATH = "/recorder/assets/recorder/resources/drawable/pause.png";
29+static const char* const RESUME_ICON_PATH = "/recorder/assets/recorder/resources/drawable/resume.png";
30+static const char* const CANCEL_ICON_PATH = "/recorder/assets/recorder/resources/drawable/cancel.png";
31+static const char* const LIST_FILE_ICON_PATH = "/recorder/assets/recorder/resources/drawable/list_file.png";
32+static const char* const LIST_PLAY_ICON_PATH = "/recorder/assets/recorder/resources/drawable/list_play.png";
33+static const char* const LIST_PAUSE_ICON_PATH = "/recorder/assets/recorder/resources/drawable/list_pause.png";
34+static const char* const LIST_DEL_ICON_PATH = "/recorder/assets/recorder/resources/drawable/list_del.png";
35+ 
36+static constexpr int16_t MAX_PICTURE_COUNT = 256;
37+static constexpr uint16_t MAX_PATH_LENGTH = 512;
38+static constexpr uint16_t TIME_FIELD_WIDTH = 2;
39+ 
40+/** recorder folder path */
41+static const char* const RECORDER_DIRECTORY = "/userdata/audio/";
42+static const char* const RECORDER_TEMP_DIRECTORY = "/userdata/audio/norm/";
43+static const char* const RECORDER_TEMP_FILE_POSTFIX = ".MP4";
44+static const char* const RECORDER_FILE_POSTFIX = ".m4a";
45+static const char* const RECORDER_FILE_NAME_FMT = "%Y%m%d_%H%M%S";
46+static const char* const RECORDER_FILE_TIME_FMT = "%Y/%m/%d";
47+static constexpr uint16_t RECORDER_FILE_POSTFIX_LENGTH = 4;
48+ 
49+/** general page configuration */
50+static constexpr int ROOT_VIEW_X = 0;
51+static constexpr int ROOT_VIEW_Y = 0;
52+static constexpr int ROOT_VIEW_WIDTH = 1920;
53+static constexpr int ROOT_VIEW_HEIGHT = 1080;
54+static constexpr uint16_t ROOT_VIEW_OPACITY = 255;
55+ 
56+static const char* const FONT_NAME = "SourceHanSansSC-Regular.otf";
57+ 
58+/** title bar */
59+static constexpr int16_t TITLE_BAR_X = 0;
60+static constexpr int16_t TITLE_BAR_Y = 0;
61+static constexpr int16_t TITLE_BAR_WIDTH = ROOT_VIEW_WIDTH;
62+static constexpr int16_t TITLE_BAR_HEIGHT = 70;
63+// title back icon
64+static constexpr int16_t BACK_ICON_SIZE = 36; // 36 x 36
65+static constexpr int16_t BACK_ICON_PADDING_H = 30;
66+static constexpr int16_t BACK_ICON_PADDING_V = (TITLE_BAR_HEIGHT - BACK_ICON_SIZE) / 2;
67+static constexpr int16_t BACK_ICON_X = 0;
68+static constexpr int16_t BACK_ICON_Y = TITLE_BAR_Y;
69+static constexpr int16_t BACK_ICON_WIDTH = BACK_ICON_SIZE + BACK_ICON_PADDING_H * 2;
70+static constexpr int16_t BACK_ICON_HEIGHT = TITLE_BAR_HEIGHT;
71+// title label
72+static constexpr int16_t TITLE_LABEL_X = BACK_ICON_X + BACK_ICON_SIZE + BACK_ICON_PADDING_H * 2;
73+static constexpr int16_t TITLE_LABEL_Y = 0;
74+static constexpr int16_t TITLE_LABEL_WIDTH = 100;
75+static constexpr int16_t TITLE_LABEL_HEIGHT = TITLE_BAR_HEIGHT;
76+static constexpr uint16_t TITLE_LABEL_FONT_SIZE = 25;
77+ 
78+/** notice label **/
79+static constexpr int16_t NOTICE_LABEL_WIDTH = 400;
80+static constexpr int16_t NOTICE_LABEL_HEIGHT = 36;
81+static constexpr int16_t NOTICE_LABEL_MARGIN_TOP = 30;
82+static constexpr int16_t NOTICE_LABEL_X = (ROOT_VIEW_WIDTH - NOTICE_LABEL_WIDTH) / 2;
83+static constexpr int16_t NOTICE_LABEL_Y = TITLE_BAR_Y + TITLE_BAR_HEIGHT + NOTICE_LABEL_MARGIN_TOP;
84+static constexpr uint16_t NOTICE_LABEL_FONT_SIZE = 32;
85+ 
86+/** duration **/
87+static constexpr int16_t DURATION_LABEL_WIDTH = 400;
88+static constexpr int16_t DURATION_LABEL_HEIGHT = 50;
89+static constexpr int16_t DURATION_LABEL_MARGIN_TOP = 30;
90+static constexpr int16_t DURATION_LABEL_X = (ROOT_VIEW_WIDTH - DURATION_LABEL_WIDTH) / 2;
91+static constexpr int16_t DURATION_LABEL_Y = NOTICE_LABEL_Y + NOTICE_LABEL_HEIGHT + DURATION_LABEL_MARGIN_TOP;
92+static constexpr uint16_t DURATION_LABEL_FONT_SIZE = 48;
93+ 
94+/** fs **/
95+static constexpr int16_t FS_IMAGE_WIDTH = 260;
96+static constexpr int16_t FS_IMAGE_HEIGHT = 110;
97+static constexpr int16_t FS_IMAGE_MARGIN_TOP = 40;
98+static constexpr int16_t FS_IMAGE_X = (ROOT_VIEW_WIDTH - FS_IMAGE_WIDTH) / 2;
99+static constexpr int16_t FS_IMAGE_Y = DURATION_LABEL_Y + DURATION_LABEL_HEIGHT + FS_IMAGE_MARGIN_TOP;
100+ 
101+/** start/stop button */
102+static constexpr int16_t START_BUTTON_SIZE = 140;
103+static constexpr int16_t START_BUTTON_WIDTH = START_BUTTON_SIZE;
104+static constexpr int16_t START_BUTTON_HEIGHT = START_BUTTON_SIZE;
105+static constexpr int16_t START_BUTTON_MARGIN_TOP = 40;
106+static constexpr int16_t START_BUTTON_X = (ROOT_VIEW_WIDTH - START_BUTTON_WIDTH) / 2;
107+static constexpr int16_t START_BUTTON_Y = FS_IMAGE_Y + FS_IMAGE_HEIGHT + START_BUTTON_MARGIN_TOP;
108+ 
109+/** cancel button */
110+static constexpr int16_t CANCEL_BUTTON_SIZE = 80;
111+static constexpr int16_t CANCEL_BUTTON_WIDTH = CANCEL_BUTTON_SIZE;
112+static constexpr int16_t CANCEL_BUTTON_HEIGHT = CANCEL_BUTTON_SIZE;
113+static constexpr int16_t CANCEL_BUTTON_MARGIN_RIGHT = 40;
114+static constexpr int16_t CANCEL_BUTTON_X = START_BUTTON_X - CANCEL_BUTTON_WIDTH - CANCEL_BUTTON_MARGIN_RIGHT;
115+static constexpr int16_t CANCEL_BUTTON_Y = START_BUTTON_Y;
116+ 
117+/** pause/resume button */
118+static constexpr int16_t PAUSE_BUTTON_SIZE = CANCEL_BUTTON_SIZE;
119+static constexpr int16_t PAUSE_BUTTON_WIDTH = PAUSE_BUTTON_SIZE;
120+static constexpr int16_t PAUSE_BUTTON_HEIGHT = PAUSE_BUTTON_SIZE;
121+static constexpr int16_t PAUSE_BUTTON_MARGIN_LEFT = CANCEL_BUTTON_MARGIN_RIGHT;
122+static constexpr int16_t PAUSE_BUTTON_X = START_BUTTON_X + START_BUTTON_WIDTH + PAUSE_BUTTON_MARGIN_LEFT;
123+static constexpr int16_t PAUSE_BUTTON_Y = START_BUTTON_Y;
124+ 
125+/** list */
126+static constexpr int16_t LIST_MARGIN_H = 20;
127+// list lable
128+static constexpr int16_t LIST_LABEL_MARGIN_TOP = 20;
129+static constexpr int16_t LIST_LABEL_X = LIST_MARGIN_H;
130+static constexpr int16_t LIST_LABEL_Y = START_BUTTON_Y + START_BUTTON_HEIGHT + LIST_LABEL_MARGIN_TOP;
131+static constexpr int16_t LIST_LABEL_WIDTH = 200;
132+static constexpr int16_t LIST_LABEL_HEIGHT = 36;
133+static constexpr uint16_t LIST_LABEL_FONT_SIZE = 32;
134+// list
135+static constexpr int16_t LIST_MARGIN_TOP = 20;
136+static constexpr int16_t LIST_MARGIN_BOTTOM = 20;
137+static constexpr int16_t LIST_X = LIST_MARGIN_H;
138+static constexpr int16_t LIST_Y = LIST_LABEL_Y + LIST_LABEL_HEIGHT + LIST_MARGIN_TOP;
139+static constexpr int16_t LIST_WIDTH = ROOT_VIEW_WIDTH - (LIST_MARGIN_H * 2);
140+static constexpr int16_t LIST_HEIGHT = ROOT_VIEW_HEIGHT - LIST_MARGIN_BOTTOM - LIST_Y;
141+// list divider
142+static constexpr int16_t LIST_DIVIDER_HEIGHT = 8;
143+// list item
144+static constexpr int16_t LIST_ITEM_X = 0;
145+static constexpr int16_t LIST_ITEM_Y = 0;
146+static constexpr int16_t LIST_ITEM_WIDTH = LIST_WIDTH;
147+static constexpr int16_t LIST_ITEM_HEIGHT = 110;
148+static constexpr int16_t LIST_ITEM_PADDING_H = 20;
149+static constexpr int16_t LIST_ITEM_PADDING_V = 20;
150+// list item file icon
151+static constexpr int16_t LIST_ITEM_FILE_ICON_X = LIST_ITEM_PADDING_H;
152+static constexpr int16_t LIST_ITEM_FILE_ICON_Y = LIST_ITEM_PADDING_V;
153+static constexpr int16_t LIST_ITEM_FILE_ICON_WIDTH = 72;
154+static constexpr int16_t LIST_ITEM_FILE_ICON_HEIGHT = 72;
155+// list item name label
156+static constexpr int16_t LIST_ITEM_NAME_LABEL_MARGIN_LEFT = 20;
157+static constexpr int16_t LIST_ITEM_NAME_LABEL_X =
158+ LIST_ITEM_FILE_ICON_X + LIST_ITEM_FILE_ICON_WIDTH + LIST_ITEM_NAME_LABEL_MARGIN_LEFT;
159+static constexpr int16_t LIST_ITEM_NAME_LABEL_WIDTH = 500;
160+static constexpr int16_t LIST_ITEM_NAME_LABEL_HEIGHT = 28;
161+static constexpr uint16_t LIST_ITEM_NAME_LABEL_FONT_SIZE = 24;
162+// list item time label
163+static constexpr int16_t LIST_ITEM_TIME_PADDING_TOP = 10;
164+static constexpr int16_t LIST_ITEM_TIME_LABEL_X = LIST_ITEM_NAME_LABEL_X;
165+static constexpr int16_t LIST_ITEM_TIME_LABEL_WIDTH = 200;
166+static constexpr int16_t LIST_ITEM_TIME_LABEL_HEIGHT = 22;
167+static constexpr uint16_t LIST_ITEM_TIME_LABEL_FONT_SIZE = 20;
168+// refactor list time name/time label Y
169+static constexpr int16_t LIST_ITEM_NAME_LABEL_Y =
170+ (LIST_ITEM_HEIGHT -
171+ (LIST_ITEM_NAME_LABEL_HEIGHT + LIST_ITEM_TIME_PADDING_TOP + LIST_ITEM_TIME_LABEL_HEIGHT)) /
172+ 2;
173+static constexpr int16_t LIST_ITEM_TIME_LABEL_Y =
174+ LIST_ITEM_NAME_LABEL_Y + LIST_ITEM_NAME_LABEL_HEIGHT + LIST_ITEM_TIME_PADDING_TOP;
175+// list item play button
176+static constexpr int16_t LIST_ITEM_BUTTON_SIZE = 56;
177+static constexpr int16_t LIST_ITEM_BUTTON_MARGIN = 20;
178+static constexpr int16_t LIST_ITEM_BORDER_RADIUS = 16;
179+static constexpr int16_t LIST_ITEM_PLAY_BUTTON_X =
180+ LIST_ITEM_WIDTH - LIST_ITEM_PADDING_H - LIST_ITEM_BUTTON_SIZE * 2 - LIST_ITEM_BUTTON_MARGIN;
181+static constexpr int16_t LIST_ITEM_PLAY_BUTTON_Y = (LIST_ITEM_HEIGHT - LIST_ITEM_BUTTON_SIZE) / 2;
182+static constexpr int16_t LIST_ITEM_PLAY_BUTTON_WIDTH = LIST_ITEM_BUTTON_SIZE;
183+static constexpr int16_t LIST_ITEM_PLAY_BUTTON_HEIGHT = LIST_ITEM_BUTTON_SIZE;
184+// list item delete button
185+static constexpr int16_t LIST_ITEM_DEL_BUTTON_X = LIST_ITEM_WIDTH - LIST_ITEM_PADDING_H - LIST_ITEM_BUTTON_SIZE;
186+static constexpr int16_t LIST_ITEM_DEL_BUTTON_Y = (LIST_ITEM_HEIGHT - LIST_ITEM_BUTTON_SIZE) / 2;
187+static constexpr int16_t LIST_ITEM_DEL_BUTTON_WIDTH = LIST_ITEM_BUTTON_SIZE;
188+static constexpr int16_t LIST_ITEM_DEL_BUTTON_HEIGHT = LIST_ITEM_BUTTON_SIZE;
189+ 
190+ 
191+/** prefix and File Type */
192+static const char* const AVAILABEL_SOURCE_TYPE = ".aac";
193+} // namespace OHOS
194+#endif // OHOS_RECORDER_CONFIG_H
@@ -0,0 +1,125 @@
1+/*
2+ * Copyright (c) 2026 RKH Corp.
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+#ifndef OHOS_RECORDER_LIST_ADAPTER_H
17+#define OHOS_RECORDER_LIST_ADAPTER_H
18+ 
19+#include <components/ui_view.h>
20+#include <components/ui_image_view.h>
21+#include <components/ui_label.h>
22+#include <components/abstract_adapter.h>
23+#include <event_listener.h>
24+ 
25+#include <vector>
26+#include <functional>
27+#include <memory>
28+ 
29+#include "recorder_config.h"
30+ 
31+namespace OHOS {
32+struct RecordItem {
33+ std::string name; // file name
34+ std::string path; // file path
35+ std::string timeStr;
36+ long time; // create time.
37+ bool started; // play started status
38+ bool paused; // paused status
39+};
40+ 
41+class OnItemPlayListener : public HeapBase {
42+public:
43+ virtual void OnItemPlay(int16_t index, const RecordItem& item) = 0;
44+ virtual ~OnItemPlayListener() = default;
45+};
46+ 
47+class OnItemDeleteListener : public HeapBase {
48+public:
49+ virtual void OnItemDelete(int16_t index, const RecordItem& item) = 0;
50+ virtual ~OnItemDeleteListener() = default;
51+};
52+ 
53+ 
54+using OnItemFunc = std::function<void(int16_t index, const RecordItem& item)>;
55+ 
56+class RecorderListItemListener :
57+ public OnItemPlayListener,
58+ public OnItemDeleteListener {
59+public:
60+ RecorderListItemListener() = delete;
61+ ~RecorderListItemListener() override = default;
62+ 
63+ RecorderListItemListener(OnItemFunc onPlay, OnItemFunc onDelete)
64+ {
65+ onPlay_ = std::move(onPlay);
66+ onDelete_ = std::move(onDelete);
67+ }
68+ 
69+ void OnItemPlay(int16_t index, const RecordItem& item) override
70+ {
71+ if (!onPlay_) {
72+ return;
73+ }
74+ onPlay_(index, item);
75+ }
76+ 
77+ void OnItemDelete(int16_t index, const RecordItem& item) override
78+ {
79+ if (!onDelete_) {
80+ return;
81+ }
82+ onDelete_(index, item);
83+ }
84+ 
85+private:
86+ OnItemFunc onPlay_ {};
87+ OnItemFunc onDelete_ {};
88+};
89+ 
90+ 
91+class RecorderListAdapter : public AbstractAdapter {
92+public:
93+ RecorderListAdapter();
94+ ~RecorderListAdapter() override;
95+ uint16_t GetCount() override;
96+ UIView* GetView(UIView* inView, int16_t index) override;
97+ void Init();
98+ void SetOnItemPlayListener(OnItemPlayListener* listener);
99+ void SetOnItemDeleteListener(OnItemDeleteListener* listener);
100+ void SetItems(std::vector<RecordItem>& items);
101+ void AddItem(const RecordItem& item);
102+ void RemoveItem(int16_t index);
103+ void UpdateItem(int16_t index, const RecordItem& item);
104+ bool GetItem(int16_t index, RecordItem& item) const;
105+private:
106+ UIViewGroup* CreateItemView();
107+ UIImageView* CreateFileIcon();
108+ UILabel* CreateNameLabel();
109+ UILabel* CreateTimeLabel();
110+ UIImageView* CreatePlayButton();
111+ UIImageView* CreateDeleteButton();
112+ void BindItemView(UIViewGroup* root, int16_t index, RecordItem& item);
113+ void ResetItemListeners(UIImageView* playButton, UIImageView* deleteButton);
114+private:
115+ std::vector<RecordItem> items_;
116+ char fileIconAbsolutePath[MAX_PATH_LENGTH] = { 0 };
117+ char playIconAbsolutePath[MAX_PATH_LENGTH] = { 0 };
118+ char pauseIconAbsolutePath[MAX_PATH_LENGTH] = { 0 };
119+ char deleteIconAbsolutePath[MAX_PATH_LENGTH] = { 0 };
120+ OnItemPlayListener* onItemPlayListener_ { nullptr };
121+ OnItemDeleteListener* onItemDeleteListener_ { nullptr };
122+};
123+ 
124+}
125+#endif // OHOS_RECORDER_LIST_ADAPTER_H
@@ -0,0 +1,70 @@
1+/*
2+ * Copyright (c) 2026 RKH Corp.
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+#ifndef RECORDER_LOG_H
17+#define RECORDER_LOG_H
18+ 
19+#ifdef HILOG_ENABLE
20+ 
21+#ifndef LOG_DOMAIN
22+#define LOG_DOMAIN 0xD0000
23+#endif
24+ 
25+#ifndef LOG_TAG
26+#define LOG_TAG "[RECORDER]"
27+#endif
28+ 
29+#include <hilog/log.h>
30+ 
31+#ifdef __cplusplus
32+extern "C" {
33+#endif
34+ 
35+#define FILE_NAME (strrchr((__FILE__), '/') ? strrchr((__FILE__), '/') + 1 : (__FILE__))
36+ 
37+#define LOGD(fmt, ...) HILOG_DEBUG(LOG_APP, "[%s:%d] " fmt, FILE_NAME, __LINE__, ##__VA_ARGS__)
38+#define LOGI(fmt, ...) HILOG_INFO(LOG_APP, "[%s:%d] " fmt, FILE_NAME, __LINE__, ##__VA_ARGS__)
39+#define LOGW(fmt, ...) HILOG_WARN(LOG_APP, "[%s:%d] " fmt, FILE_NAME, __LINE__, ##__VA_ARGS__)
40+#define LOGE(fmt, ...) HILOG_ERROR(LOG_APP, "[%s:%d] " fmt, FILE_NAME, __LINE__, ##__VA_ARGS__)
41+#define LOGF(fmt, ...) HILOG_FATAL(LOG_APP, "[%s:%d] " fmt, FILE_NAME, __LINE__, ##__VA_ARGS__)
42+ 
43+#ifdef __cplusplus
44+}
45+#endif
46+ 
47+#else
48+ 
49+#include <stdio.h>
50+#include <string.h>
51+ 
52+#ifdef __cplusplus
53+extern "C" {
54+#endif
55+ 
56+#define FILE_NAME (strrchr((__FILE__), '/') ? strrchr((__FILE__), '/') + 1 : (__FILE__))
57+ 
58+#define LOGD(fmt, ...) printf("[D][RECORDER][%s:%d] " fmt "\n", FILE_NAME, __LINE__, ##__VA_ARGS__)
59+#define LOGI(fmt, ...) printf("[I][RECORDER][%s:%d] " fmt "\n", FILE_NAME, __LINE__, ##__VA_ARGS__)
60+#define LOGW(fmt, ...) printf("[W][RECORDER][%s:%d] " fmt "\n", FILE_NAME, __LINE__, ##__VA_ARGS__)
61+#define LOGE(fmt, ...) printf("[E][RECORDER][%s:%d] " fmt "\n", FILE_NAME, __LINE__, ##__VA_ARGS__)
62+#define LOGF(fmt, ...) printf("[F][RECORDER][%s:%d] " fmt "\n", FILE_NAME, __LINE__, ##__VA_ARGS__)
63+ 
64+#ifdef __cplusplus
65+}
66+#endif
67+ 
68+#endif
69+ 
70+#endif /* RECORDER_LOG_H */
@@ -0,0 +1,72 @@
1+/*
2+ * Copyright (c) 2026 RKH Corp.
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+#ifndef OHOS_RECORDER_UTILS_H
17+#define OHOS_RECORDER_UTILS_H
18+ 
19+#include <sstream>
20+#include <iomanip>
21+#include <ctime>
22+#include <sys/stat.h>
23+ 
24+#include "recorder_config.h"
25+ 
26+namespace OHOS {
27+const uint32_t MS_PER_SECOND = 1000;
28+const long long MS_PER_MINUTE = 60 * MS_PER_SECOND;
29+const long long MS_PER_HOUR = 60 * MS_PER_MINUTE;
30+ 
31+static std::string FormatDurationTime(uint32_t total_ms)
32+{
33+ if (total_ms == 0) {
34+ return "00:00:00";
35+ }
36+ uint32_t hours = static_cast<uint32_t>(total_ms / MS_PER_HOUR);
37+ total_ms %= MS_PER_HOUR;
38+ uint32_t minutes = static_cast<uint32_t>(total_ms / MS_PER_MINUTE);
39+ total_ms %= MS_PER_MINUTE;
40+ uint32_t seconds = static_cast<uint32_t>(total_ms / MS_PER_SECOND);
41+ 
42+ std::ostringstream oss;
43+ oss << std::setfill('0')
44+ << std::setw(TIME_FIELD_WIDTH) << hours
45+ << ":"
46+ << std::setw(TIME_FIELD_WIDTH) << minutes
47+ << ":"
48+ << std::setw(TIME_FIELD_WIDTH) << seconds;
49+ return oss.str();
50+}
51+ 
52+static std::string FormatTime(long timeMs, const char* format)
53+{
54+ std::time_t time = timeMs;
55+ std::tm* tm = std::localtime(&time);
56+ std::stringstream ss;
57+ ss << std::put_time(tm, format);
58+ return ss.str();
59+}
60+ 
61+static long GetFileTime(const std::string& path)
62+{
63+ struct stat fileStat;
64+ if (stat(path.c_str(), &fileStat) == 0) {
65+ return fileStat.st_mtime;
66+ } else {
67+ LOGE("get file time failed, path:%s, errno:%d", path.c_str(), errno);
68+ return 0;
69+ }
70+}
71+}
72+#endif // OHOS_RECORDER_ABILITY_H
@@ -0,0 +1,46 @@
1+/*
2+ * Copyright (c) 2026 RKH Corp.
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+#ifndef OHOS_RECORDER_TASK_HELPER_H
17+#define OHOS_RECORDER_TASK_HELPER_H
18+ 
19+#include <sstream>
20+#include <iomanip>
21+ 
22+#include <common/task_manager.h>
23+ 
24+namespace OHOS {
25+ 
26+template <typename Callable>
27+class TaskLambdaWrapper : public Task {
28+private:
29+ Callable m_func;
30+public:
31+ explicit TaskLambdaWrapper(Callable func) : m_func(std::move(func)) {}
32+ 
33+ void Callback() override
34+ {
35+ m_func();
36+ }
37+};
38+ 
39+template <typename Callable>
40+static std::shared_ptr<Task> CreateTask(Callable func)
41+{
42+ return std::make_shared<TaskLambdaWrapper<Callable>>(std::move(func));
43+}
44+ 
45+}
46+#endif // OHOS_RECORDER_TASK_HELPER_H
@@ -0,0 +1,464 @@
1+/*
2+ * Copyright (c) 2026 RKH Corp.
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 <dirent.h>
17+#include <fcntl.h>
18+#include <cerrno>
19+#include <cstdio>
20+#include <sys/stat.h>
21+#include <sys/types.h>
22+#include <sstream>
23+ 
24+#include <media_errors.h>
25+ 
26+#include "recorder_ability.h"
27+#include "recorder_log.h"
28+#include "recorder_config.h"
29+#include "media_utils.h"
30+ 
31+namespace OHOS {
32+static constexpr size_t DATETIME_BUFFER_SIZE = 0x100;
33+static constexpr mode_t RECORDER_DIRECTORY_MODE = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
34+ 
35+static std::string GernerateFileName()
36+{
37+ time_t stCurrent;
38+ char aszDatetime[DATETIME_BUFFER_SIZE];
39+ (void)time(&stCurrent);
40+ struct tm *pstCurrentTime = localtime(&(stCurrent));
41+ if (pstCurrentTime == nullptr) {
42+ return "";
43+ }
44+ if (strftime(aszDatetime, DATETIME_BUFFER_SIZE, RECORDER_FILE_NAME_FMT, pstCurrentTime) == 0) {
45+ return "";
46+ }
47+ std::ostringstream oss;
48+ oss << RECORDER_DIRECTORY << aszDatetime << RECORDER_FILE_POSTFIX;
49+ return oss.str();
50+}
51+ 
52+static bool IsDirExists(const char *path)
53+{
54+ struct stat st;
55+ int ret = lstat(path, &st);
56+ if (ret == -1) {
57+ if (errno == ENOENT) {
58+ return false;
59+ }
60+ perror("lstat failed");
61+ exit(EXIT_FAILURE);
62+ }
63+ return S_ISDIR(st.st_mode);
64+}
65+ 
66+MediaUtils::~MediaUtils()
67+{
68+ CloseRecorder();
69+ ClosePlayer();
70+}
71+ 
72+#ifdef USE_RECORDER_API
73+class RecorderCallbackAdapter : public Media::RecorderCallback {
74+public:
75+ RecorderCallbackAdapter(Media::RecorderCallback* from)
76+ {
77+ target = from;
78+ }
79+ ~RecorderCallbackAdapter()
80+ {
81+ target = nullptr;
82+ }
83+ void OnError(int32_t errorType, int32_t errorCode) override
84+ {
85+ if (target) {
86+ target->OnError(errorType, errorCode);
87+ }
88+ }
89+ void OnInfo(int type, int extra) override
90+ {
91+ if (target) {
92+ target->OnError(type, extra);
93+ }
94+ }
95+private:
96+ Media::RecorderCallback *target = nullptr;
97+};
98+ 
99+bool MediaUtils::SetRecorderCallback(Media::RecorderCallback* recorderCallback)
100+{
101+ recorderCallback_ = recorderCallback;
102+ return true;
103+}
104+#endif
105+ 
106+bool MediaUtils::InitRecorder()
107+{
108+ LOGI("InitRecorder");
109+#ifdef USE_RECORDER_API
110+ int32_t audioSourceId = 0;
111+ AudioSourceType inputSource = AUDIO_MIC;
112+ AudioCodecFormat audioFormat = AAC_LC;
113+ int32_t sampleRate = 48000;
114+ int32_t channelCount = 1;
115+ int32_t audioEncodingBitRate = 96000;
116+ 
117+ recorder_ = std::make_shared<Media::Recorder>();
118+ int ret = 0;
119+ 
120+ if ((ret = recorder_->SetAudioSource(inputSource, audioSourceId)) != Media::SUCCESS) {
121+ LOGE("SetAudioSource failed, ret:%d", ret);
122+ return false;
123+ }
124+ if ((ret = recorder_->SetAudioEncoder(audioSourceId, audioFormat)) != Media::SUCCESS) {
125+ LOGE("SetAudioEncoder failed, ret:%d", ret);
126+ return false;
127+ }
128+ if ((ret = recorder_->SetAudioSampleRate(audioSourceId, sampleRate)) != Media::SUCCESS) {
129+ LOGE("SetAudioSampleRate failed, ret:%d", ret);
130+ return false;
131+ }
132+ if ((ret = recorder_->SetAudioChannels(audioSourceId, channelCount)) != Media::SUCCESS) {
133+ LOGE("SetAudioChannels failed, ret:%d", ret);
134+ return false;
135+ }
136+ if ((ret = recorder_->SetAudioEncodingBitRate(audioSourceId, audioEncodingBitRate)) != Media::SUCCESS) {
137+ LOGE("SetAudioEncodingBitRate failed, ret:%d", ret);
138+ return false;
139+ }
140+ if ((ret = recorder_->SetMaxDuration(36000)) != Media::SUCCESS) { // 36000s=10h
141+ LOGE("SetMaxDuration failed, ret:%d", ret);
142+ return false;
143+ }
144+ if ((ret = recorder_->SetOutputFormat(Media::FORMAT_M4A)) != Media::SUCCESS) {
145+ LOGE("SetOutputFormat failed, ret:%d", ret);
146+ return false;
147+ }
148+ recorderCallbackPtr_ = std::make_shared<RecorderCallbackAdapter>(recorderCallback_);
149+ recorder_->SetRecorderCallback(recorderCallbackPtr_);
150+#endif
151+ return true;
152+}
153+ 
154+bool MediaUtils::StartRecord()
155+{
156+ LOGI("StartRecord");
157+ if (recording_) {
158+ LOGW("already recording!");
159+ return false;
160+ }
161+ if (!EnsureRecorderDirectory()) {
162+ return false;
163+ }
164+#ifdef USE_RECORDER_FD
165+ std::string filename = GernerateFileName();
166+ LOGI("GernerateFileName %s", filename.c_str());
167+ recordFd_ = open(filename.c_str(), O_RDWR | O_CREAT);
168+ if (recordFd_ == -1) {
169+ LOGE("open file failed! filename:%s, errno:%d", filename.c_str(), errno);
170+ return false;
171+ }
172+#endif
173+ if (!StartRecorderService()) {
174+ return false;
175+ }
176+ recording_ = true;
177+ return true;
178+}
179+ 
180+bool MediaUtils::EnsureRecorderDirectory()
181+{
182+ if (IsDirExists(RECORDER_DIRECTORY)) {
183+ return true;
184+ }
185+ if (mkdir(RECORDER_DIRECTORY, RECORDER_DIRECTORY_MODE) != 0) {
186+ LOGE("mkdir for %s failed, errno:%d", RECORDER_DIRECTORY, errno);
187+ CloseRecorder();
188+ return false;
189+ }
190+ return true;
191+}
192+ 
193+bool MediaUtils::StartRecorderService()
194+{
195+#ifdef USE_RECORDER_API
196+ if (recorder_ == nullptr) {
197+ LOGW("recorder is nullptr, do init.");
198+ if (!InitRecorder()) {
199+ LOGE("recorder init failed!");
200+ return false;
201+ }
202+ }
203+ 
204+ int ret = 0;
205+#if USE_RECORDER_FD
206+ if ((ret = recorder_->SetOutputFile(recordFd_)) != Media::SUCCESS) {
207+ LOGE("SetOutputPath failed. ret:%d", ret);
208+ CloseRecorder();
209+ return false;
210+ }
211+#else
212+ if ((ret = recorder_->SetOutputPath(RECORDER_DIRECTORY)) != Media::SUCCESS) {
213+ LOGE("SetOutputPath failed. ret:%d", ret);
214+ CloseRecorder();
215+ return false;
216+ }
217+#endif
218+ 
219+ ret = recorder_->Prepare();
220+ if (ret != Media::SUCCESS) {
221+ LOGE("Prepare failed. ret:%d", ret);
222+ CloseRecorder();
223+ return false;
224+ }
225+ ret = recorder_->Start();
226+ if (ret != Media::SUCCESS) {
227+ LOGE("Start failed. ret:%d", ret);
228+ CloseRecorder();
229+ return false;
230+ }
231+#endif
232+ return true;
233+}
234+ 
235+bool MediaUtils::StopRecord()
236+{
237+ LOGI("StopRecord");
238+ if (!recording_) {
239+ LOGW("current not recording!");
240+ return false;
241+ }
242+ CloseRecorder();
243+ MoveFiles();
244+ recording_ = false;
245+ return true;
246+}
247+ 
248+bool MediaUtils::MoveFiles()
249+{
250+ LOGI("MoveFiles");
251+ struct dirent* entry;
252+ DIR* dir = opendir(RECORDER_TEMP_DIRECTORY);
253+ if (dir == nullptr) {
254+ LOGE("open recorder dir failed. errno:%d", errno);
255+ return false;
256+ }
257+ 
258+ while ((entry = readdir(dir)) != nullptr) {
259+ std::string filename = entry->d_name;
260+ if (entry->d_type == DT_REG &&
261+ filename.size() > RECORDER_FILE_POSTFIX_LENGTH &&
262+ (filename.substr(filename.size() - RECORDER_FILE_POSTFIX_LENGTH) == RECORDER_TEMP_FILE_POSTFIX)) {
263+ LOGI("find file: %s", filename.c_str());
264+ std::string src = std::string(RECORDER_TEMP_DIRECTORY) + filename;
265+ std::string dst = std::string(RECORDER_DIRECTORY) +
266+ filename.substr(0, filename.size() - RECORDER_FILE_POSTFIX_LENGTH) +
267+ RECORDER_FILE_POSTFIX;
268+ if (rename(src.c_str(), dst.c_str()) != 0) {
269+ LOGE("rename file failed, errno:%d, src:%s, dst:%s", errno, src.c_str(), dst.c_str());
270+ continue;
271+ }
272+ }
273+ }
274+ closedir(dir);
275+ return true;
276+}
277+ 
278+bool MediaUtils::CloseRecorder()
279+{
280+ LOGI("CloseRecorder");
281+#ifdef USE_RECORDER_API
282+ if (recorder_) {
283+ recorder_->Stop(true);
284+ recorder_->Release();
285+ recorder_ = nullptr;
286+ }
287+#endif
288+ 
289+#ifdef USE_RECORDER_FD
290+ if (recordFd_ != -1) {
291+ FILE *fp = fdopen(recordFd_, "w+");
292+ if (fp) {
293+ fflush(fp);
294+ fsync(recordFd_);
295+ fclose(fp);
296+ close(recordFd_);
297+ }
298+ recordFd_ = -1;
299+ }
300+#endif
301+ return true;
302+}
303+ 
304+// Player
305+#ifdef USE_PLAYER_API
306+class PlayerCallbackAdapter : public Media::PlayerCallback {
307+public:
308+ PlayerCallbackAdapter(Media::PlayerCallback* from)
309+ {
310+ target = from;
311+ }
312+ ~PlayerCallbackAdapter() override
313+ {
314+ target = nullptr;
315+ }
316+ void OnPlaybackComplete() override
317+ {
318+ if (target) {
319+ target->OnPlaybackComplete();
320+ }
321+ }
322+ void OnError(int32_t errorType, int32_t errorCode) override
323+ {
324+ if (target) {
325+ target->OnError(errorType, errorCode);
326+ }
327+ }
328+ void OnInfo(int type, int extra) override
329+ {
330+ if (target) {
331+ target->OnError(type, extra);
332+ }
333+ }
334+ void OnVideoSizeChanged(int width, int height) override
335+ {
336+ if (target) {
337+ target->OnVideoSizeChanged(width, height);
338+ }
339+ }
340+ void OnRewindToComplete() override
341+ {
342+ if (target) {
343+ target->OnRewindToComplete();
344+ }
345+ }
346+private:
347+ Media::PlayerCallback *target = nullptr;
348+};
349+ 
350+bool MediaUtils::SetPlayerCallback(Media::PlayerCallback* playerCallback)
351+{
352+ playerCallback_ = playerCallback;
353+ return true;
354+}
355+#endif
356+ 
357+bool MediaUtils::InitPlayer(const char* filePath)
358+{
359+ LOGI("InitPlayer");
360+#ifdef USE_PLAYER_API
361+ player_ = std::make_shared<Media::Player>();
362+ if (!player_) {
363+ LOGE("create Player failed!");
364+ return false;
365+ }
366+ std::string uri(filePath);
367+ Media::Source source(uri);
368+ int ret = player_->SetSource(source);
369+ if (ret != Media::SUCCESS) {
370+ LOGE("SetSource failed!");
371+ ClosePlayer();
372+ return false;
373+ }
374+ playerCallbackPtr_ = std::make_shared<PlayerCallbackAdapter>(playerCallback_);
375+ player_->SetPlayerCallback(playerCallbackPtr_);
376+#endif
377+ return true;
378+}
379+ 
380+bool MediaUtils::StartPlay(const char* filePath)
381+{
382+ LOGI("StartPlay file:%s", filePath);
383+ if (playing_ && !paused_) {
384+ LOGW("already playing.");
385+ return false;
386+ }
387+#ifdef USE_PLAYER_API
388+ if (!player_) {
389+ LOGE("player is null, do init!");
390+ if (!InitPlayer(filePath)) {
391+ LOGE("init player failed");
392+ return false;
393+ }
394+ }
395+ int ret = 0;
396+ if (playing_ && paused_) {
397+ ret = player_->Play();
398+ if (ret != Media::SUCCESS) {
399+ LOGE("Play(resume) failed!");
400+ ClosePlayer();
401+ return false;
402+ }
403+ } else {
404+ ret = player_->Prepare();
405+ if (ret != Media::SUCCESS) {
406+ LOGE("Prepare failed!");
407+ ClosePlayer();
408+ return false;
409+ }
410+ ret = player_->Play();
411+ if (ret != Media::SUCCESS) {
412+ LOGE("Play failed!");
413+ ClosePlayer();
414+ return false;
415+ }
416+ }
417+#endif
418+ playing_ = true;
419+ paused_ = false;
420+ return true;
421+}
422+ 
423+bool MediaUtils::PausePlay()
424+{
425+ LOGI("PausePlay");
426+#ifdef USE_PLAYER_API
427+ int ret = player_->Pause();
428+ if (ret != Media::SUCCESS) {
429+ LOGE("Pause failed!");
430+ ClosePlayer();
431+ return false;
432+ }
433+#endif
434+ paused_ = true;
435+ return true;
436+}
437+ 
438+bool MediaUtils::StopPlay()
439+{
440+ LOGI("StopPlay");
441+ if (!playing_) {
442+ LOGW("current not playing!");
443+ return false;
444+ }
445+ ClosePlayer();
446+ return true;
447+}
448+ 
449+bool MediaUtils::ClosePlayer()
450+{
451+ LOGI("ClosePlayer");
452+#ifdef USE_PLAYER_API
453+ if (player_) {
454+ player_->Stop();
455+ player_->Release();
456+ player_ = nullptr;
457+ }
458+#endif
459+ playing_ = false;
460+ paused_ = false;
461+ return true;
462+}
463+ 
464+}
@@ -0,0 +1,53 @@
1+/*
2+ * Copyright (c) 2026 RKH Corp.
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 "recorder_ability.h"
17+#include "recorder_log.h"
18+ 
19+namespace OHOS {
20+REGISTER_AA(RecorderAbility)
21+ 
22+void RecorderAbility::OnStart(const Want &want)
23+{
24+ LOGI("Recorder::OnStart");
25+ SetMainRoute("RecorderAbilityMainSlice");
26+ 
27+ Ability::OnStart(want);
28+}
29+ 
30+void RecorderAbility::OnInactive()
31+{
32+ LOGI("Recorder::OnInactive");
33+ Ability::OnInactive();
34+}
35+ 
36+void RecorderAbility::OnActive(const Want &want)
37+{
38+ LOGI("Recorder::OnActive");
39+ Ability::OnActive(want);
40+}
41+ 
42+void RecorderAbility::OnBackground()
43+{
44+ LOGI("Recorder::OnBackground");
45+ Ability::OnBackground();
46+}
47+ 
48+void RecorderAbility::OnStop()
49+{
50+ LOGI("Recorder::OnStop");
51+ Ability::OnStop();
52+}
53+}
@@ -0,0 +1,585 @@
1+/*
2+ * Copyright (c) 2026 RKH Corp.
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 <ability_env.h>
17+#include <ability_loader.h>
18+#include <ability_manager.h>
19+#include <components/text_adapter.h>
20+#include <common/screen.h>
21+#include <hal_tick.h>
22+ 
23+#include <dirent.h>
24+#include <algorithm>
25+#include <cstdio>
26+ 
27+#include "recorder_ability_main_slice.h"
28+#include "recorder_log.h"
29+#include "recorder_utils.h"
30+ 
31+namespace OHOS {
32+REGISTER_AS(RecorderAbilityMainSlice)
33+ 
34+static constexpr uint8_t NOTICE_COLOR_RED = 78;
35+static constexpr uint8_t NOTICE_COLOR_GREEN = 89;
36+static constexpr uint8_t NOTICE_COLOR_BLUE = 105;
37+static constexpr uint8_t ROOT_COLOR_RED = 249;
38+static constexpr uint8_t ROOT_COLOR_GREEN = 250;
39+static constexpr uint8_t ROOT_COLOR_BLUE = 251;
40+ 
41+RecorderAbilityMainSlice::~RecorderAbilityMainSlice()
42+{
43+ LOGI("~RecorderAbilityMainSlice()");
44+ StopTimer();
45+}
46+ 
47+void RecorderAbilityMainSlice::InitTitle()
48+{
49+ LOGI("RecorderAbilityMainSlice::InitTitle");
50+ titleBar_ = new UIViewGroup();
51+ titleBar_->SetPosition(TITLE_BAR_X, TITLE_BAR_Y, TITLE_BAR_WIDTH, TITLE_BAR_HEIGHT);
52+ titleBar_->SetStyle(STYLE_BACKGROUND_COLOR, Color::White().full);
53+ titleBar_->SetStyle(STYLE_BACKGROUND_OPA, OPA_OPAQUE);
54+ 
55+ backButton_ = new UIImageView();
56+ backButton_->SetPosition(BACK_ICON_X, BACK_ICON_Y, BACK_ICON_WIDTH, BACK_ICON_HEIGHT);
57+ backButton_->SetStyle(STYLE_PADDING_LEFT, BACK_ICON_PADDING_H);
58+ backButton_->SetStyle(STYLE_PADDING_RIGHT, BACK_ICON_PADDING_H);
59+ backButton_->SetStyle(STYLE_PADDING_TOP, BACK_ICON_PADDING_V);
60+ backButton_->SetStyle(STYLE_PADDING_BOTTOM, BACK_ICON_PADDING_V);
61+ backButton_->SetSrc(backIconAbsolutePath);
62+ backButton_->SetTouchable(true);
63+ 
64+ auto onClick = [this] (UIView& view, const Event& event) -> bool {
65+ LOGI("TerminateAbility by BackPress");
66+ TerminateAbility();
67+ return true;
68+ };
69+ backButtonListener_ = new EventListener(onClick, nullptr);
70+ backButton_->SetOnClickListener(backButtonListener_);
71+ 
72+ titleLabel_ = new UILabel();
73+ titleLabel_->SetPosition(TITLE_LABEL_X, TITLE_LABEL_Y, TITLE_LABEL_WIDTH, TITLE_LABEL_HEIGHT);
74+ titleLabel_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT, UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);
75+ titleLabel_->SetFont(FONT_NAME, TITLE_LABEL_FONT_SIZE);
76+ titleLabel_->SetStyle(STYLE_TEXT_COLOR, Color::Black().full);
77+ titleLabel_->SetStyle(STYLE_TEXT_OPA, OPA_OPAQUE);
78+ titleLabel_->SetText("录音机");
79+ 
80+ titleBar_->Add(backButton_);
81+ titleBar_->Add(titleLabel_);
82+ rootView_->Add(titleBar_);
83+}
84+ 
85+void RecorderAbilityMainSlice::InitRecordCtrl()
86+{
87+ InitRecordLabels();
88+ InitRecordButtons();
89+ InitRecordListeners();
90+ AddRecordControlsToRoot();
91+}
92+ 
93+void RecorderAbilityMainSlice::InitRecordLabels()
94+{
95+ noticeLabel_ = new UILabel();
96+ noticeLabel_->SetPosition(NOTICE_LABEL_X, NOTICE_LABEL_Y, NOTICE_LABEL_WIDTH, NOTICE_LABEL_HEIGHT);
97+ noticeLabel_->SetAlign(
98+ UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER,
99+ UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);
100+ noticeLabel_->SetFont(FONT_NAME, NOTICE_LABEL_FONT_SIZE);