• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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