1 /*
2 * Copyright (C) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #define MLOG_TAG "CustomisedToneProcessor"
17
18 #include "customised_tone_processor.h"
19
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <fstream>
23
24 #include "ringtone_type.h"
25 #include "directory_ex.h"
26 #include "avmetadatahelper.h"
27 #include "ringtone_errno.h"
28 #include "ringtone_log.h"
29 #include "dualfwk_conf_loader.h"
30 #include "ringtone_file_utils.h"
31 #include "ringtone_db_const.h"
32 #include "ringtone_scanner_utils.h"
33 #include "ringtone_mimetype_utils.h"
34 #include "ringtone_tracer.h"
35 #include "ringtone_utils.h"
36
37 namespace OHOS {
38 namespace Media {
39 using namespace std;
40
CustomisedToneProcessor()41 CustomisedToneProcessor::CustomisedToneProcessor() {}
42
GetFileFd(const std::string & path,int & fd,struct stat64 & st)43 static int32_t GetFileFd(const std::string &path, int &fd, struct stat64 &st)
44 {
45 std::error_code ec;
46 char realPath[PATH_MAX] = "";
47
48 if (realpath(path.c_str(), realPath) == nullptr) {
49 RINGTONE_ERR_LOG("Realpath input file failed");
50 return E_FAIL;
51 }
52
53 string filePath(realPath);
54 std::filesystem::exists(filePath, ec);
55 if (ec.value() != E_SUCCESS) {
56 RINGTONE_ERR_LOG("GetFileTitle normalized fd failed");
57 return E_FAIL;
58 }
59
60 int mode = O_RDONLY;
61 fd = open(realPath, mode);
62 CHECK_AND_RETURN_RET_LOG(fd > 0, E_FAIL, "open fail path: %{private}s", realPath);
63
64 int32_t ret = fstat64(fd, &st);
65 if (ret != 0) {
66 RINGTONE_ERR_LOG("file stat is err, %{public}d, fd: %{public}d", ret, fd);
67 close(fd);
68 return E_FAIL;
69 }
70
71 return E_OK;
72 }
73
GetFileTitleAndDuration(const std::string & path,FileInfo & fileInfo)74 static int32_t GetFileTitleAndDuration(const std::string &path, FileInfo &fileInfo)
75 {
76 RingtoneTracer tracer;
77 tracer.Start("CustomisedToneProcessor::GetFileTitleAndDuration");
78
79 int fd;
80 struct stat64 st;
81 if (GetFileFd(path, fd, st) != E_OK) {
82 return E_FAIL;
83 }
84
85 shared_ptr<AVMetadataHelper> avMetadataHelper = AVMetadataHelperFactory::CreateAVMetadataHelper();
86 if (avMetadataHelper == nullptr) {
87 close(fd);
88 return 0;
89 }
90 int64_t fileLength = static_cast<int64_t>(st.st_size);
91 int32_t ret = avMetadataHelper->SetSource(fd, 0, fileLength, AV_META_USAGE_META_ONLY);
92 close(fd);
93 if (ret != 0) {
94 RINGTONE_ERR_LOG("av set source is err");
95 return E_FAIL;
96 }
97
98 std::shared_ptr<Meta> avMeta = avMetadataHelper->GetAVMetadata();
99 CHECK_AND_RETURN_RET_LOG(avMeta != nullptr, 0, "avMeta is nullptr");
100 if (!avMeta->GetData(Tag::MEDIA_TITLE, fileInfo.title) || fileInfo.title.empty()) {
101 RINGTONE_ERR_LOG("get file title fail");
102 // If the title can not be obtained, use the prefix of displayname
103 std::string::size_type pos = fileInfo.displayName.find_last_of('.');
104 fileInfo.title = (pos == std::string::npos) ? fileInfo.displayName : fileInfo.displayName.substr(0, pos);
105 }
106
107 std::string duration;
108 if (!avMeta->GetData(Tag::MEDIA_DURATION, duration) || !RingtoneUtils::IsNumber(duration)) {
109 RINGTONE_ERR_LOG("get file duration fail");
110 return E_FAIL;
111 }
112
113 fileInfo.duration = atoi(duration.c_str());
114 return E_SUCCESS;
115 }
116
GetCustomisedAudioPath(DualFwkConf & dualFwkConf)117 int32_t CustomisedToneProcessor::GetCustomisedAudioPath(DualFwkConf &dualFwkConf)
118 {
119 DualFwkConfLoader confLoader;
120 if (confLoader.Init() != E_OK) {
121 RINGTONE_ERR_LOG("Failed to initialize dualFwkConfLoader");
122 return E_FAIL;
123 }
124
125 dualFwkConf.ringtonePath = confLoader.GetConf("ringtone_path");
126 dualFwkConf.ringtone2Path = confLoader.GetConf("ringtone2_path");
127 dualFwkConf.messagePath = confLoader.GetConf("message_path");
128 dualFwkConf.messageSub1 = confLoader.GetConfPath("messageSub1");
129 dualFwkConf.notificationSoundPath = confLoader.GetConf("notification_sound_path");
130 dualFwkConf.alarmAlertPath = confLoader.GetConf("alarm_alert_path");
131
132 return E_OK;
133 }
134
ConvertCustomisedAudioPath(const std::string & ringtonePath)135 std::string CustomisedToneProcessor::ConvertCustomisedAudioPath(const std::string &ringtonePath)
136 {
137 if (ringtonePath.empty()) {
138 RINGTONE_ERR_LOG("customised audio path is empty");
139 return "";
140 }
141
142 std::string::size_type pos = ringtonePath.find(RINGTONE_EXTERNAL_BASE_PATH);
143 if (pos == std::string::npos) {
144 RINGTONE_ERR_LOG("customised audio file not in the directory: %{public}s", RINGTONE_EXTERNAL_BASE_PATH.c_str());
145 return "";
146 }
147
148 std::string absPath = ringtonePath.substr(pos + RINGTONE_EXTERNAL_BASE_PATH.length());
149 bool isMusicPath = ringtonePath.find(RINGTONE_EXTERNAL_MUSIC_PATH) != std::string::npos;
150 std::string fileMgrAudioPath = "";
151 std::string tmpPath;
152 if (isMusicPath && PathToRealPath(FILE_MANAGER_UPDATE_BACKUP_PATH + absPath, tmpPath)) {
153 fileMgrAudioPath = FILE_MANAGER_UPDATE_BACKUP_PATH + absPath;
154 RINGTONE_INFO_LOG("convert %{public}s to %{public}s", ringtonePath.c_str(), fileMgrAudioPath.c_str());
155 return fileMgrAudioPath;
156 }
157
158 if (!isMusicPath && PathToRealPath(FILE_MANAGER_BASE_PATH + absPath, tmpPath)) {
159 fileMgrAudioPath = FILE_MANAGER_BASE_PATH + absPath;
160 RINGTONE_INFO_LOG("convert %{public}s to %{public}s", ringtonePath.c_str(), fileMgrAudioPath.c_str());
161 return fileMgrAudioPath;
162 }
163
164 if (!isMusicPath && PathToRealPath(FILE_MANAGER_UPDATE_BACKUP_PATH + absPath, tmpPath)) {
165 fileMgrAudioPath = FILE_MANAGER_UPDATE_BACKUP_PATH + absPath;
166 RINGTONE_INFO_LOG("convert %{public}s to %{public}s", ringtonePath.c_str(), fileMgrAudioPath.c_str());
167 return fileMgrAudioPath;
168 }
169
170 if (isMusicPath && PathToRealPath(FILE_MANAGER_BASE_PATH + absPath, tmpPath)) {
171 fileMgrAudioPath = FILE_MANAGER_BASE_PATH + absPath;
172 RINGTONE_INFO_LOG("convert %{public}s to %{public}s", ringtonePath.c_str(), fileMgrAudioPath.c_str());
173 return fileMgrAudioPath;
174 }
175
176 RINGTONE_DEBUG_LOG("No rule can convert ringtonePath: %{public}s", ringtonePath.c_str());
177 return fileMgrAudioPath;
178 }
179
BuildFileInfo(const std::string & dualFilePath,int32_t toneType,int32_t ringtoneType,int32_t shotToneType,std::vector<FileInfo> & fileInfos)180 int32_t CustomisedToneProcessor::BuildFileInfo(const std::string &dualFilePath, int32_t toneType, int32_t ringtoneType,
181 int32_t shotToneType, std::vector<FileInfo> &fileInfos)
182 {
183 if (dualFilePath.empty()) {
184 return E_FAIL;
185 }
186
187 std::string customisedAudioPath = ConvertCustomisedAudioPath(dualFilePath);
188 if (customisedAudioPath.empty()) {
189 return E_FAIL;
190 }
191
192 FileInfo fileInfo;
193 fileInfo.toneType = toneType;
194 fileInfo.data = customisedAudioPath;
195 fileInfo.displayName = RingtoneFileUtils::GetFileNameFromPath(fileInfo.data);
196 fileInfo.ringToneType = ringtoneType;
197 fileInfo.shotToneType = shotToneType;
198 fileInfo.sourceType = SOURCE_TYPE_CUSTOMISED;
199 fileInfo.mediaType = RINGTONE_MEDIA_TYPE_AUDIO;
200 fileInfo.dateAdded = RingtoneFileUtils::UTCTimeMilliSeconds();
201
202 GetFileTitleAndDuration(customisedAudioPath, fileInfo);
203 std::string extension = RingtoneScannerUtils::GetFileExtension(customisedAudioPath);
204 fileInfo.mimeType = RingtoneMimeTypeUtils::GetMimeTypeFromExtension(extension);
205
206 struct stat statInfo {};
207 if (stat(customisedAudioPath.c_str(), &statInfo) != 0) {
208 RINGTONE_ERR_LOG("fail to get file %{private}s statInfo, err: %{public}d", customisedAudioPath.c_str(), errno);
209 return E_FAIL;
210 }
211
212 fileInfo.size = statInfo.st_size;
213 fileInfos.emplace_back(fileInfo);
214 return E_OK;
215 }
216
BuildFileInfos()217 std::vector<FileInfo> CustomisedToneProcessor::BuildFileInfos()
218 {
219 std::vector<FileInfo> result;
220 DualFwkConf dualFwkConf;
221 GetCustomisedAudioPath(dualFwkConf);
222 BuildFileInfo(dualFwkConf.ringtonePath, TONE_TYPE_RINGTONE, RING_TONE_TYPE_SIM_CARD_1, SHOT_TONE_TYPE_NOT, result);
223 BuildFileInfo(dualFwkConf.ringtone2Path, TONE_TYPE_RINGTONE, RING_TONE_TYPE_SIM_CARD_2, SHOT_TONE_TYPE_NOT, result);
224 BuildFileInfo(dualFwkConf.notificationSoundPath, TONE_TYPE_NOTIFICATION, RING_TONE_TYPE_NOT, SHOT_TONE_TYPE_NOT,
225 result);
226 BuildFileInfo(dualFwkConf.alarmAlertPath, TONE_TYPE_ALARM, RING_TONE_TYPE_NOT, SHOT_TONE_TYPE_NOT, result);
227 BuildFileInfo(dualFwkConf.messagePath, TONE_TYPE_NOTIFICATION, SHOT_TONE_TYPE_NOT, RING_TONE_TYPE_SIM_CARD_1,
228 result);
229 BuildFileInfo(dualFwkConf.messageSub1, TONE_TYPE_NOTIFICATION, SHOT_TONE_TYPE_NOT, RING_TONE_TYPE_SIM_CARD_2,
230 result);
231 return result;
232 }
233
QueryFileMgrForFileInfo(std::map<std::string,std::shared_ptr<FileInfo>> & infoMap)234 int32_t CustomisedToneProcessor::QueryFileMgrForFileInfo(std::map<std::string, std::shared_ptr<FileInfo>> &infoMap)
235 {
236 std::vector<FileInfo> fileInfos = BuildFileInfos();
237 for (auto fileInfo : fileInfos) {
238 std::shared_ptr<FileInfo> infoPtr = std::make_shared<FileInfo>(fileInfo);
239 infoMap[fileInfo.displayName] = infoPtr;
240 RINGTONE_INFO_LOG("new info found in file_manager: %{public}s", infoPtr->toString().c_str());
241 }
242 return E_SUCCESS;
243 }
244 } // namespace Media
245 } // namespace OHOS