1 /*
2 * Copyright (C) 2024 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 "RingtoneRestore"
17
18 #include "ringtone_restore.h"
19
20 #include <sys/stat.h>
21
22 #include "datashare_ext_ability.h"
23 #include "datashare_ext_ability_context.h"
24 #include "result_set_utils.h"
25 #include "ringtone_restore_type.h"
26 #include "ringtone_restore_db_utils.h"
27 #include "ringtone_errno.h"
28 #include "ringtone_file_utils.h"
29 #include "ringtone_log.h"
30 #include "ringtone_type.h"
31
32 namespace OHOS {
33 namespace Media {
34 using namespace std;
35 static const int32_t QUERY_COUNT = 500;
36 static const int32_t INVALID_QUERY_OFFSET = -1;
Init(const std::string & backupPath)37 int32_t RingtoneRestore::Init(const std::string &backupPath)
38 {
39 RINGTONE_INFO_LOG("Init db start");
40 if (backupPath.empty()) {
41 RINGTONE_ERR_LOG("error: backup path is null");
42 return E_INVALID_ARGUMENTS;
43 }
44 dbPath_ = backupPath + RINGTONE_LIBRARY_DB_PATH_EL1 + "/rdb" + "/" + RINGTONE_LIBRARY_DB_NAME;
45 if (!RingtoneFileUtils::IsFileExists(dbPath_)) {
46 RINGTONE_ERR_LOG("ringtone db is not exist, path=%{public}s", dbPath_.c_str());
47 dbPath_ = backupPath + RINGTONE_LIBRARY_DB_PATH + "/rdb" + "/" + RINGTONE_LIBRARY_DB_NAME;
48 if (!RingtoneFileUtils::IsFileExists(dbPath_)) {
49 RINGTONE_ERR_LOG("ringtone db is not exist, path=%{public}s", dbPath_.c_str());
50 return E_FAIL;
51 }
52 }
53 backupPath_ = backupPath;
54 int32_t err = RingtoneRestoreDbUtils::InitDb(restoreRdb_, RINGTONE_LIBRARY_DB_NAME, dbPath_,
55 RINGTONE_BUNDLE_NAME, true);
56 if (err != E_OK) {
57 RINGTONE_ERR_LOG("ringtone rdb fail, err = %{public}d", err);
58 return E_HAS_DB_ERROR;
59 }
60 if (RingtoneRestoreBase::Init(backupPath) != E_OK) {
61 return E_FAIL;
62 }
63
64 RINGTONE_INFO_LOG("Init db successfully");
65 return E_OK;
66 }
67
QueryFileInfos(int32_t offset)68 vector<FileInfo> RingtoneRestore::QueryFileInfos(int32_t offset)
69 {
70 vector<FileInfo> result;
71 string querySql = "SELECT * FROM " + RINGTONE_TABLE;
72 if (offset != INVALID_QUERY_OFFSET) {
73 querySql += " LIMIT " + to_string(offset) + ", " + to_string(QUERY_COUNT);
74 }
75 auto resultSet = restoreRdb_->QuerySql(querySql);
76 if (resultSet == nullptr) {
77 return {};
78 }
79
80 vector<shared_ptr<RingtoneMetadata>> metaDatas {};
81 auto ret = resultSet->GoToFirstRow();
82 while (ret == NativeRdb::E_OK) {
83 auto metaData = make_unique<RingtoneMetadata>();
84 if (PopulateMetadata(resultSet, metaData) != E_OK) {
85 RINGTONE_INFO_LOG("read resultset error");
86 continue;
87 }
88 metaDatas.push_back(std::move(metaData));
89 ret = resultSet->GoToNextRow();
90 };
91 resultSet->Close();
92
93 return ConvertToFileInfos(metaDatas);
94 }
95
ConvertToFileInfos(vector<shared_ptr<RingtoneMetadata>> & metaDatas)96 vector<FileInfo> RingtoneRestore::ConvertToFileInfos(vector<shared_ptr<RingtoneMetadata>> &metaDatas)
97 {
98 vector<FileInfo> infos = {};
99 for (auto meta : metaDatas) {
100 infos.emplace_back(*meta);
101 }
102 return infos;
103 }
104
CheckRestoreFileInfos(vector<FileInfo> & infos)105 void RingtoneRestore::CheckRestoreFileInfos(vector<FileInfo> &infos)
106 {
107 for (auto it = infos.begin(); it != infos.end();) {
108 // at first, check backup file path
109 string srcPath = backupPath_ + it->data;
110 if (!RingtoneFileUtils::IsFileExists(srcPath)) {
111 // 系统铃音不克隆,需要进行设置铃音判断
112 if (it->sourceType == SOURCE_TYPE_PRESET) {
113 it->restorePath = it->data;
114 CheckSetting(*it);
115 }
116 RINGTONE_INFO_LOG("warnning:backup file is not exist, path=%{private}s", srcPath.c_str());
117 infos.erase(it);
118 } else {
119 it++;
120 }
121 }
122 }
123
StartRestore()124 int32_t RingtoneRestore::StartRestore()
125 {
126 if (restoreRdb_ == nullptr || backupPath_.empty()) {
127 return E_FAIL;
128 }
129 auto ret = RingtoneRestoreBase::StartRestore();
130 if (ret != E_OK) {
131 return ret;
132 }
133 CheckNotRingtoneRestore();
134 auto infos = QueryFileInfos(INVALID_QUERY_OFFSET);
135 if ((!infos.empty()) && (infos.size() != 0)) {
136 CheckRestoreFileInfos(infos);
137 ret = InsertTones(infos);
138 }
139 FlushSettings();
140 return ret;
141 }
142
UpdateRestoreFileInfo(FileInfo & info)143 void RingtoneRestore::UpdateRestoreFileInfo(FileInfo &info)
144 {
145 info.displayName = RingtoneFileUtils::GetFileNameFromPath(info.restorePath);
146 if (info.title == TITLE_DEFAULT) {
147 info.title = RingtoneFileUtils::GetBaseNameFromPath(info.restorePath);
148 }
149
150 struct stat statInfo;
151 if (stat(info.restorePath.c_str(), &statInfo) != 0) {
152 RINGTONE_ERR_LOG("stat syscall err %{public}d", errno);
153 return;
154 }
155 info.dateModified = static_cast<int64_t>(RingtoneFileUtils::Timespec2Millisecond(statInfo.st_mtim));
156 }
157
OnPrepare(FileInfo & info,const std::string & destPath)158 bool RingtoneRestore::OnPrepare(FileInfo &info, const std::string &destPath)
159 {
160 if (!RingtoneFileUtils::IsFileExists(destPath)) {
161 return false;
162 }
163
164 string fileName = RingtoneFileUtils::GetFileNameFromPath(info.data);
165 if (fileName.empty()) {
166 RINGTONE_ERR_LOG("src file name is null");
167 return false;
168 }
169 string baseName = RingtoneFileUtils::GetBaseNameFromPath(info.data);
170 if (baseName.empty()) {
171 RINGTONE_ERR_LOG("src file base name is null");
172 return false;
173 }
174 string extensionName = RingtoneFileUtils::GetExtensionFromPath(info.data);
175
176 int32_t repeatCount = 1;
177 string srcPath = backupPath_ + info.data;
178 info.restorePath = destPath + "/" + fileName;
179 while (RingtoneFileUtils::IsFileExists(info.restorePath)) {
180 if (RingtoneFileUtils::IsSameFile(srcPath, info.restorePath)) {
181 CheckSetting(info);
182 RINGTONE_ERR_LOG("samefile: srcPath=%{private}s, dstPath=%{private}s", srcPath.c_str(),
183 info.restorePath.c_str());
184 return false;
185 }
186 info.restorePath = destPath + "/" + baseName + "(" + to_string(repeatCount++) + ")" + "." + extensionName;
187 }
188
189 if (!RingtoneRestoreBase::MoveFile(srcPath, info.restorePath)) {
190 return false;
191 }
192
193 UpdateRestoreFileInfo(info);
194
195 return true;
196 }
197
OnFinished(vector<FileInfo> & infos)198 void RingtoneRestore::OnFinished(vector<FileInfo> &infos)
199 {
200 if (!RingtoneFileUtils::RemoveDirectory(backupPath_)) {
201 RINGTONE_ERR_LOG("cleanup backup dir failed, restorepath=%{public}s, err: %{public}s",
202 backupPath_.c_str(), strerror(errno));
203 }
204 }
205
CheckNotRingtoneRestore()206 void RingtoneRestore::CheckNotRingtoneRestore()
207 {
208 // SIM_CARD_1 ring no ringtone
209 if (RingtoneRestoreBase::DetermineNoRingtone(RINGTONE_COLUMN_RING_TONE_TYPE,
210 RINGTONE_COLUMN_RING_TONE_SOURCE_TYPE, RING_TONE_TYPE_SIM_CARD_1, RING_TONE_TYPE_SIM_CARD_BOTH, restoreRdb_) &&
211 RingtoneRestoreBase::NeedCommitSetting(RINGTONE_COLUMN_RING_TONE_TYPE,
212 RINGTONE_COLUMN_RING_TONE_SOURCE_TYPE, RING_TONE_TYPE_SIM_CARD_1, RING_TONE_TYPE_SIM_CARD_BOTH)) {
213 RINGTONE_INFO_LOG("no ringtone sound for ringtone sim card 1");
214 RingtoneRestoreBase::SetNotRingtone(RINGTONE_COLUMN_RING_TONE_TYPE,
215 RINGTONE_COLUMN_RING_TONE_SOURCE_TYPE, SIM_CARD_1);
216 }
217 // SIM_CARD_2 ring no ringtone
218 if (RingtoneRestoreBase::DetermineNoRingtone(RINGTONE_COLUMN_RING_TONE_TYPE,
219 RINGTONE_COLUMN_RING_TONE_SOURCE_TYPE, RING_TONE_TYPE_SIM_CARD_2, RING_TONE_TYPE_SIM_CARD_BOTH, restoreRdb_) &&
220 RingtoneRestoreBase::NeedCommitSetting(RINGTONE_COLUMN_RING_TONE_TYPE,
221 RINGTONE_COLUMN_RING_TONE_SOURCE_TYPE, RING_TONE_TYPE_SIM_CARD_2, RING_TONE_TYPE_SIM_CARD_BOTH)) {
222 RINGTONE_INFO_LOG("no ringtone sound for ringtone sim card 2");
223 RingtoneRestoreBase::SetNotRingtone(RINGTONE_COLUMN_RING_TONE_TYPE,
224 RINGTONE_COLUMN_RING_TONE_SOURCE_TYPE, SIM_CARD_2);
225 }
226 // SIM_CARD_1 shot no ringtone
227 if (RingtoneRestoreBase::DetermineNoRingtone(RINGTONE_COLUMN_SHOT_TONE_TYPE,
228 RINGTONE_COLUMN_SHOT_TONE_SOURCE_TYPE, SHOT_TONE_TYPE_SIM_CARD_1, SHOT_TONE_TYPE_SIM_CARD_BOTH, restoreRdb_) &&
229 RingtoneRestoreBase::NeedCommitSetting(RINGTONE_COLUMN_SHOT_TONE_TYPE,
230 RINGTONE_COLUMN_SHOT_TONE_SOURCE_TYPE, SHOT_TONE_TYPE_SIM_CARD_1, SHOT_TONE_TYPE_SIM_CARD_BOTH)) {
231 RINGTONE_INFO_LOG("no shot sound for shot sim card 1");
232 RingtoneRestoreBase::SetNotRingtone(RINGTONE_COLUMN_SHOT_TONE_TYPE,
233 RINGTONE_COLUMN_SHOT_TONE_SOURCE_TYPE, SIM_CARD_1);
234 }
235 // SIM_CARD_2 shot no ringtone
236 if (RingtoneRestoreBase::DetermineNoRingtone(RINGTONE_COLUMN_SHOT_TONE_TYPE,
237 RINGTONE_COLUMN_SHOT_TONE_SOURCE_TYPE, SHOT_TONE_TYPE_SIM_CARD_2, SHOT_TONE_TYPE_SIM_CARD_BOTH, restoreRdb_) &&
238 RingtoneRestoreBase::NeedCommitSetting(RINGTONE_COLUMN_SHOT_TONE_TYPE,
239 RINGTONE_COLUMN_SHOT_TONE_SOURCE_TYPE, SHOT_TONE_TYPE_SIM_CARD_2, SHOT_TONE_TYPE_SIM_CARD_BOTH)) {
240 RINGTONE_INFO_LOG("no shot sound for shot sim card 2");
241 RingtoneRestoreBase::SetNotRingtone(RINGTONE_COLUMN_SHOT_TONE_TYPE,
242 RINGTONE_COLUMN_SHOT_TONE_SOURCE_TYPE, SIM_CARD_2);
243 }
244 // notification
245 if (RingtoneRestoreBase::DetermineNoRingtone(RINGTONE_COLUMN_NOTIFICATION_TONE_TYPE,
246 RINGTONE_COLUMN_NOTIFICATION_TONE_SOURCE_TYPE, NOTIFICATION_TONE_TYPE, NOTIFICATION_TONE_TYPE, restoreRdb_) &&
247 RingtoneRestoreBase::NeedCommitSetting(RINGTONE_COLUMN_NOTIFICATION_TONE_TYPE,
248 RINGTONE_COLUMN_NOTIFICATION_TONE_SOURCE_TYPE, NOTIFICATION_TONE_TYPE, NOTIFICATION_TONE_TYPE)) {
249 RINGTONE_INFO_LOG("no notification sound for notification");
250 RingtoneRestoreBase::SetNotRingtone(RINGTONE_COLUMN_NOTIFICATION_TONE_TYPE,
251 RINGTONE_COLUMN_NOTIFICATION_TONE_SOURCE_TYPE, SIM_CARD_1);
252 }
253 }
254 } // namespace Media
255 } // namespace OHOS
256