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;
37 static string RINGTONELIBRARY_DB_PATH = "/data/storage/el2/database";
Init(const std::string & backupPath)38 int32_t RingtoneRestore::Init(const std::string &backupPath)
39 {
40 RINGTONE_INFO_LOG("Init db start");
41 if (backupPath.empty()) {
42 RINGTONE_ERR_LOG("error: backup path is null");
43 return E_INVALID_ARGUMENTS;
44 }
45 dbPath_ = backupPath + RINGTONELIBRARY_DB_PATH + "/rdb" + "/" + RINGTONE_LIBRARY_DB_NAME;
46 backupPath_ = backupPath;
47
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 if (RingtoneRestoreBase::Init(backupPath) != E_OK) {
53 return E_FAIL;
54 }
55 int32_t err = RingtoneRestoreDbUtils::InitDb(restoreRdb_, RINGTONE_LIBRARY_DB_NAME, dbPath_,
56 RINGTONE_BUNDLE_NAME, true);
57 if (err != E_OK) {
58 RINGTONE_ERR_LOG("ringtone rdb fail, err = %{public}d", err);
59 return E_HAS_DB_ERROR;
60 }
61
62 RINGTONE_INFO_LOG("Init db successfully");
63 return E_OK;
64 }
65
QueryFileInfos(int32_t offset)66 vector<FileInfo> RingtoneRestore::QueryFileInfos(int32_t offset)
67 {
68 vector<FileInfo> result;
69 string querySql = "SELECT * FROM " + RINGTONE_TABLE;
70 if (offset != INVALID_QUERY_OFFSET) {
71 querySql += " LIMIT " + to_string(offset) + ", " + to_string(QUERY_COUNT);
72 }
73 auto resultSet = restoreRdb_->QuerySql(querySql);
74 if (resultSet == nullptr) {
75 return {};
76 }
77
78 vector<shared_ptr<RingtoneMetadata>> metaDatas {};
79 auto ret = resultSet->GoToFirstRow();
80 while (ret == NativeRdb::E_OK) {
81 auto metaData = make_unique<RingtoneMetadata>();
82 if (PopulateMetadata(resultSet, metaData) != E_OK) {
83 RINGTONE_INFO_LOG("read resultset error");
84 continue;
85 }
86 metaDatas.push_back(std::move(metaData));
87 ret = resultSet->GoToNextRow();
88 };
89 resultSet->Close();
90
91 return ConvertToFileInfos(metaDatas);
92 }
93
ConvertToFileInfos(vector<shared_ptr<RingtoneMetadata>> & metaDatas)94 vector<FileInfo> RingtoneRestore::ConvertToFileInfos(vector<shared_ptr<RingtoneMetadata>> &metaDatas)
95 {
96 vector<FileInfo> infos = {};
97 for (auto meta : metaDatas) {
98 infos.emplace_back(*meta);
99 }
100 return infos;
101 }
102
CheckRestoreFileInfos(vector<FileInfo> & infos)103 void RingtoneRestore::CheckRestoreFileInfos(vector<FileInfo> &infos)
104 {
105 for (auto it = infos.begin(); it != infos.end();) {
106 // at first, check backup file path
107 string srcPath = backupPath_ + it->data;
108 if (!RingtoneFileUtils::IsFileExists(srcPath)) {
109 // 系统铃音不克隆,需要进行设置铃音判断
110 if (it->sourceType == SOURCE_TYPE_PRESET) {
111 it->restorePath = it->data;
112 CheckSetting(*it);
113 }
114 RINGTONE_INFO_LOG("warnning:backup file is not exist, path=%{private}s", srcPath.c_str());
115 infos.erase(it);
116 } else {
117 it++;
118 }
119 }
120 }
121
StartRestore()122 int32_t RingtoneRestore::StartRestore()
123 {
124 if (restoreRdb_ == nullptr || backupPath_.empty()) {
125 return E_FAIL;
126 }
127 auto ret = RingtoneRestoreBase::StartRestore();
128 if (ret != E_OK) {
129 return ret;
130 }
131 auto infos = QueryFileInfos(INVALID_QUERY_OFFSET);
132 if ((!infos.empty()) && (infos.size() != 0)) {
133 CheckRestoreFileInfos(infos);
134 ret = InsertTones(infos);
135 }
136 FlushSettings();
137 return ret;
138 }
139
UpdateRestoreFileInfo(FileInfo & info)140 void RingtoneRestore::UpdateRestoreFileInfo(FileInfo &info)
141 {
142 info.displayName = RingtoneFileUtils::GetFileNameFromPath(info.restorePath);
143 if (info.title == TITLE_DEFAULT) {
144 info.title = RingtoneFileUtils::GetBaseNameFromPath(info.restorePath);
145 }
146
147 struct stat statInfo;
148 if (stat(info.restorePath.c_str(), &statInfo) != 0) {
149 RINGTONE_ERR_LOG("stat syscall err %{public}d", errno);
150 return;
151 }
152 info.dateModified = static_cast<int64_t>(RingtoneFileUtils::Timespec2Millisecond(statInfo.st_mtim));
153 }
154
OnPrepare(FileInfo & info,const std::string & destPath)155 bool RingtoneRestore::OnPrepare(FileInfo &info, const std::string &destPath)
156 {
157 if (!RingtoneFileUtils::IsFileExists(destPath)) {
158 return false;
159 }
160
161 string fileName = RingtoneFileUtils::GetFileNameFromPath(info.data);
162 if (fileName.empty()) {
163 RINGTONE_ERR_LOG("src file name is null");
164 return false;
165 }
166 string baseName = RingtoneFileUtils::GetBaseNameFromPath(info.data);
167 if (baseName.empty()) {
168 RINGTONE_ERR_LOG("src file base name is null");
169 return false;
170 }
171 string extensionName = RingtoneFileUtils::GetExtensionFromPath(info.data);
172
173 int32_t repeatCount = 1;
174 string srcPath = backupPath_ + info.data;
175 info.restorePath = destPath + "/" + fileName;
176 while (RingtoneFileUtils::IsFileExists(info.restorePath)) {
177 if (RingtoneFileUtils::IsSameFile(srcPath, info.restorePath)) {
178 CheckSetting(info);
179 RINGTONE_ERR_LOG("samefile: srcPath=%{private}s, dstPath=%{private}s", srcPath.c_str(),
180 info.restorePath.c_str());
181 return false;
182 }
183 info.restorePath = destPath + "/" + baseName + "(" + to_string(repeatCount++) + ")" + "." + extensionName;
184 }
185
186 if (!RingtoneRestoreBase::MoveFile(srcPath, info.restorePath)) {
187 return false;
188 }
189
190 UpdateRestoreFileInfo(info);
191
192 return true;
193 }
194
OnFinished(vector<FileInfo> & infos)195 void RingtoneRestore::OnFinished(vector<FileInfo> &infos)
196 {
197 if (!RingtoneFileUtils::RemoveDirectory(backupPath_)) {
198 RINGTONE_ERR_LOG("cleanup backup dir failed, restorepath=%{public}s, err: %{public}s",
199 backupPath_.c_str(), strerror(errno));
200 }
201 }
202 } // namespace Media
203 } // namespace OHOS
204