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 if (RingtoneRestoreBase::Init(backupPath) != E_OK) {
55 return E_FAIL;
56 }
57 int32_t err = RingtoneRestoreDbUtils::InitDb(restoreRdb_, RINGTONE_LIBRARY_DB_NAME, dbPath_,
58 RINGTONE_BUNDLE_NAME, true);
59 if (err != E_OK) {
60 RINGTONE_ERR_LOG("ringtone rdb fail, err = %{public}d", err);
61 return E_HAS_DB_ERROR;
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 auto infos = QueryFileInfos(INVALID_QUERY_OFFSET);
134 if ((!infos.empty()) && (infos.size() != 0)) {
135 CheckRestoreFileInfos(infos);
136 ret = InsertTones(infos);
137 }
138 FlushSettings();
139 return ret;
140 }
141
UpdateRestoreFileInfo(FileInfo &info)142 void RingtoneRestore::UpdateRestoreFileInfo(FileInfo &info)
143 {
144 info.displayName = RingtoneFileUtils::GetFileNameFromPath(info.restorePath);
145 if (info.title == TITLE_DEFAULT) {
146 info.title = RingtoneFileUtils::GetBaseNameFromPath(info.restorePath);
147 }
148
149 struct stat statInfo;
150 if (stat(info.restorePath.c_str(), &statInfo) != 0) {
151 RINGTONE_ERR_LOG("stat syscall err %{public}d", errno);
152 return;
153 }
154 info.dateModified = static_cast<int64_t>(RingtoneFileUtils::Timespec2Millisecond(statInfo.st_mtim));
155 }
156
OnPrepare(FileInfo &info, const std::string &destPath)157 bool RingtoneRestore::OnPrepare(FileInfo &info, const std::string &destPath)
158 {
159 if (!RingtoneFileUtils::IsFileExists(destPath)) {
160 return false;
161 }
162
163 string fileName = RingtoneFileUtils::GetFileNameFromPath(info.data);
164 if (fileName.empty()) {
165 RINGTONE_ERR_LOG("src file name is null");
166 return false;
167 }
168 string baseName = RingtoneFileUtils::GetBaseNameFromPath(info.data);
169 if (baseName.empty()) {
170 RINGTONE_ERR_LOG("src file base name is null");
171 return false;
172 }
173 string extensionName = RingtoneFileUtils::GetExtensionFromPath(info.data);
174
175 int32_t repeatCount = 1;
176 string srcPath = backupPath_ + info.data;
177 info.restorePath = destPath + "/" + fileName;
178 while (RingtoneFileUtils::IsFileExists(info.restorePath)) {
179 if (RingtoneFileUtils::IsSameFile(srcPath, info.restorePath)) {
180 CheckSetting(info);
181 RINGTONE_ERR_LOG("samefile: srcPath=%{private}s, dstPath=%{private}s", srcPath.c_str(),
182 info.restorePath.c_str());
183 return false;
184 }
185 info.restorePath = destPath + "/" + baseName + "(" + to_string(repeatCount++) + ")" + "." + extensionName;
186 }
187
188 if (!RingtoneRestoreBase::MoveFile(srcPath, info.restorePath)) {
189 return false;
190 }
191
192 UpdateRestoreFileInfo(info);
193
194 return true;
195 }
196
OnFinished(vector<FileInfo> &infos)197 void RingtoneRestore::OnFinished(vector<FileInfo> &infos)
198 {
199 if (!RingtoneFileUtils::RemoveDirectory(backupPath_)) {
200 RINGTONE_ERR_LOG("cleanup backup dir failed, restorepath=%{public}s, err: %{public}s",
201 backupPath_.c_str(), strerror(errno));
202 }
203 }
204 } // namespace Media
205 } // namespace OHOS
206