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 #include <fstream>
17 #include <vector>
18
19 #include "dualfwk_conf_loader.h"
20 #include "ringtone_errno.h"
21 #include "ringtone_file_utils.h"
22 #include "ringtone_restore_db_utils.h"
23 #include "ringtone_utils.h"
24
25 namespace OHOS {
26 namespace Media {
27
28 static const std::string SETTINGS_DATA_URI_BASE =
29 "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_";
30 static const std::string SETTINGS_DATA_FIELD_KEY = "KEYWORD";
31 static const std::string SETTINGS_DATA_FIELD_VAL = "VALUE";
32 static const std::string ERR_CONFIG_VALUE = "";
33 static std::vector<std::string> SETTINGS_COLUMNS = {SETTINGS_DATA_FIELD_VAL};
34 static const int DEFAULT_USERID = 100;
35
36 const int CHAR_LOWER_CASE_A = 97;
37 const int CHAR_LOWER_CASE_D = 100;
38 const int CHAR_LOWER_CASE_I = 105;
39 const int CHAR_LOWER_CASE_N = 110;
40 const int CHAR_LOWER_CASE_O = 111;
41 const int CHAR_LOWER_CASE_R = 114;
42 const std::string DUAL_NAME = std::string() + static_cast<char>(CHAR_LOWER_CASE_A) +
43 static_cast<char>(CHAR_LOWER_CASE_N) + static_cast<char>(CHAR_LOWER_CASE_D) +
44 static_cast<char>(CHAR_LOWER_CASE_R) + static_cast<char>(CHAR_LOWER_CASE_O) +
45 static_cast<char>(CHAR_LOWER_CASE_I) + static_cast<char>(CHAR_LOWER_CASE_D);
46 static const std::string EXTERNAL_DB_NAME = "external.db";
47 static const std::string EXTERNAL_DB_RESTORE_PATH =
48 "/data/storage/el2/base/.backup/restore/com." + DUAL_NAME + ".providers.media.module/ce/databases/external.db";
49 static const std::string INTERNAL_DB_NAME = "internal.db";
50 static const std::string INTERNAL_DB_RESTORE_PATH =
51 "/data/storage/el2/base/.backup/restore/com." + DUAL_NAME + ".providers.media.module/ce/databases/internal.db";
52
DualFwkConfLoader()53 DualFwkConfLoader::DualFwkConfLoader() {}
54
Init()55 int32_t DualFwkConfLoader::Init()
56 {
57 DataShare::CreateOptions options;
58
59 int userId = 0;
60 if (!RingtoneRestoreDbUtils::GetUserID(userId)) {
61 RINGTONE_DEBUG_LOG("Failed to get userId, using DEFAULT_USERID=%{public}d", DEFAULT_USERID);
62 userId = DEFAULT_USERID;
63 }
64 settingsDataUri_ = SETTINGS_DATA_URI_BASE + std::to_string(userId);
65 RINGTONE_DEBUG_LOG("Getting data share helper with SETTINGS_DATA_URI = %{public}s", settingsDataUri_.c_str());
66
67 dataShareHelper_ = DataShare::DataShareHelper::Creator(settingsDataUri_, options);
68 if (dataShareHelper_ == nullptr) {
69 RINGTONE_WARN_LOG("dataShareHelper_ is null, failed to get data share helper");
70 return E_ERR;
71 }
72
73 RINGTONE_INFO_LOG("Successfully initialized.");
74 return E_OK;
75 }
76
GetSound(const std::string & line)77 static std::string GetSound(const std::string &line)
78 {
79 std::string tag = "sound=\"";
80 auto lenTag = tag.size();
81 auto positionOfTag = line.find(tag);
82 if (positionOfTag == std::string::npos) {
83 return "";
84 }
85 auto positionOfQuote = line.substr(positionOfTag + lenTag).find("\"");
86 if (positionOfQuote == std::string::npos) {
87 return "";
88 }
89 return line.substr(positionOfTag + lenTag, positionOfQuote);
90 }
91
ParseBackupFile(const std::string & backupFile,const std::vector<std::string> & keys,std::map<std::string,std::string> & results)92 static int32_t ParseBackupFile(const std::string &backupFile, const std::vector<std::string> &keys,
93 std::map<std::string, std::string> &results)
94 {
95 RINGTONE_INFO_LOG("parse backupfile %{public}s uid=%{public}d", backupFile.c_str(), getuid());
96 if (RingtoneFileUtils::IsFileExists(backupFile)) {
97 RINGTONE_ERR_LOG("the file exists path: %{private}s", backupFile.c_str());
98 return E_FILE_EXIST;
99 }
100 std::ifstream fs(backupFile);
101 if (!fs.good()) {
102 RINGTONE_ERR_LOG("failed to open file %{private}s", backupFile.c_str());
103 return E_ERR;
104 }
105
106 std::string line;
107 while (std::getline(fs, line)) {
108 for (const auto &key : keys) {
109 auto pos = line.find(key);
110 if (pos == std::string::npos) {
111 continue;
112 }
113 std::string value = GetSound(line);
114 if (value.size() > 0) {
115 results.emplace(key, value);
116 }
117 }
118 }
119 return E_SUCCESS;
120 }
121
Load(DualFwkConf & conf,const RestoreSceneType & type,const std::string & backupFile)122 int32_t DualFwkConfLoader::Load(DualFwkConf &conf, const RestoreSceneType &type, const std::string &backupFile)
123 {
124 if (dataShareHelper_ == nullptr) {
125 RINGTONE_ERR_LOG("DualFwkConfLoader is not initialized successfully");
126 return E_ERR;
127 }
128 std::map<std::string, std::string> backupConfigs;
129 if (ParseBackupFile(backupFile, {"mms_sim1_channel", "mms_sim2_channel"}, backupConfigs) != E_SUCCESS) {
130 RINGTONE_WARN_LOG("Failed to parse backup file %{public}s", backupFile.c_str());
131 }
132
133 if (type == RestoreSceneType::RESTORE_SCENE_TYPE_DUAL_CLONE) {
134 RINGTONE_INFO_LOG("Load configurations for RestoreSceneType::RESTORE_SCENE_TYPE_DUAL_CLONE");
135 conf.notificationSoundPath = GetConf("notification_sound_path");
136 conf.ringtonePath = GetConf("ringtone_path");
137 conf.ringtone2Path = GetConf("ringtone2_path");
138 conf.alarmAlertPath = GetConf("alarm_alert_path");
139 conf.messagePath = GetConf("message_path");
140 conf.messageSub1 = GetConfPath("messageSub1");
141 } else {
142 RINGTONE_INFO_LOG("Load configurations for RestoreSceneType::RESTORE_SCENE_TYPE_DUAL_UPGRADE");
143 conf.notificationSoundPath = GetConf("notification_sound_path");
144 conf.ringtonePath = GetConf("ringtone_path");
145 conf.ringtone2Path = GetConf("ringtone2_path");
146 conf.alarmAlertPath = GetConf("alarm_alert_path");
147 conf.messagePath = GetConf("message_path");
148 conf.messageSub1 = GetConfPath("messageSub1");
149 }
150
151 return E_OK;
152 }
153
ShowConf(const DualFwkConf & conf)154 void DualFwkConfLoader::ShowConf(const DualFwkConf &conf)
155 {
156 RINGTONE_DEBUG_LOG("===================================================");
157 RINGTONE_DEBUG_LOG("conf.notificationSoundPath = %{public}s", conf.notificationSoundPath.c_str());
158 RINGTONE_DEBUG_LOG("conf.ringtonePath = %{public}s", conf.ringtonePath.c_str());
159 RINGTONE_DEBUG_LOG("conf.ringtone2Path = %{public}s", conf.ringtone2Path.c_str());
160 RINGTONE_DEBUG_LOG("conf.alarmAlertPath = %{public}s", conf.alarmAlertPath.c_str());
161 RINGTONE_DEBUG_LOG("conf.messagePath = %{public}s", conf.messagePath.c_str());
162 RINGTONE_DEBUG_LOG("conf.messageSub1 = %{public}s", conf.messageSub1.c_str());
163 RINGTONE_DEBUG_LOG("===================================================");
164 }
165
GetConf(const std::string & key)166 std::string DualFwkConfLoader::GetConf(const std::string &key)
167 {
168 DataShare::DataSharePredicates dataSharePredicates;
169 dataSharePredicates.EqualTo(SETTINGS_DATA_FIELD_KEY, key);
170 Uri uri(settingsDataUri_);
171 auto resultSet = dataShareHelper_->Query(uri, dataSharePredicates, SETTINGS_COLUMNS);
172 if (resultSet == nullptr) {
173 RINGTONE_DEBUG_LOG("resultSet is null, failed to get value of key = %{public}s", key.c_str());
174 return "";
175 }
176
177 int32_t numRows = 0;
178 resultSet->GetRowCount(numRows);
179 RINGTONE_INFO_LOG("%{public}d records found with key = %{public}s", numRows, key.c_str());
180 if (numRows == 0) {
181 RINGTONE_DEBUG_LOG("no record at key = %{public}s, returning an empty string.", key.c_str());
182 return "";
183 }
184 int32_t columnIndex = 0;
185 int32_t rowNumber = 0;
186 resultSet->GoToRow(rowNumber);
187 std::string valueResult = "";
188 int32_t ret = resultSet->GetString(columnIndex, valueResult);
189 if (ret != 0) {
190 RINGTONE_DEBUG_LOG("failed to get string, returning an empty string.");
191 } else {
192 RINGTONE_DEBUG_LOG("valueResult = %{public}s", valueResult.c_str());
193 }
194 return valueResult;
195 }
196
ValueToDBFileID(const std::string & value,std::string & dbName,std::string & dbPath,std::string & fileId)197 int32_t DualFwkConfLoader::ValueToDBFileID(const std::string &value, std::string &dbName, std::string &dbPath,
198 std::string &fileId)
199 {
200 size_t posExternal = value.find("external");
201 if (posExternal != std::string::npos) {
202 dbName = EXTERNAL_DB_NAME;
203 dbPath = EXTERNAL_DB_RESTORE_PATH;
204 }
205
206 size_t posInternal = value.find("internal");
207 if (posInternal != std::string::npos) {
208 dbName = INTERNAL_DB_NAME;
209 dbPath = INTERNAL_DB_RESTORE_PATH;
210 }
211
212 size_t pos = value.rfind("/");
213 if (pos == std::string::npos || (posExternal == std::string::npos && posInternal == std::string::npos)) {
214 RINGTONE_ERR_LOG("Invalid value");
215 return E_ERR;
216 }
217
218 fileId = value.substr(pos + 1);
219 if (!RingtoneUtils::IsNumber(fileId)) {
220 RINGTONE_INFO_LOG("Invalid file id %{public}s", fileId.c_str());
221 return E_ERR;
222 }
223 return E_OK;
224 }
225
GetConfPath(const std::string & key)226 std::string DualFwkConfLoader::GetConfPath(const std::string &key)
227 {
228 std::string dbName;
229 std::string dbPath;
230 std::string fileId;
231 std::string value = GetConf(key);
232 size_t pos = value.find("content://media");
233 if (pos != 0) {
234 RINGTONE_INFO_LOG("key: %{public}s value: %{public}s", key.c_str(), value.c_str());
235 return value;
236 }
237
238 int32_t ret = ValueToDBFileID(value, dbName, dbPath, fileId);
239 if (ret != E_OK) {
240 return ERR_CONFIG_VALUE;
241 }
242
243 if (!RingtoneFileUtils::IsFileExists(dbPath)) {
244 RINGTONE_ERR_LOG("%{public}s is not exist", dbName.c_str());
245 return ERR_CONFIG_VALUE;
246 }
247
248 std::shared_ptr<NativeRdb::RdbStore> rdbStore = nullptr;
249 int32_t err = RingtoneRestoreDbUtils::InitDb(rdbStore, dbName, dbPath, RINGTONE_BUNDLE_NAME, true);
250 if (err != E_OK || rdbStore == nullptr) {
251 RINGTONE_ERR_LOG("Init rdbStore fail. err: %{public}d", err);
252 return ERR_CONFIG_VALUE;
253 }
254
255 std::string querySql = "SELECT _data FROM files WHERE _id = ?";
256 std::vector<std::string> args = { fileId };
257 auto resultSet = rdbStore->QuerySql(querySql, args);
258 if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
259 RINGTONE_ERR_LOG("Query fail.");
260 return ERR_CONFIG_VALUE;
261 }
262
263 std::string data;
264 if (resultSet->GetString(0, data) != NativeRdb::E_OK) {
265 RINGTONE_ERR_LOG("Get data from resultSet fail.");
266 return ERR_CONFIG_VALUE;
267 }
268
269 RINGTONE_INFO_LOG("Get conf path success, data: %{public}s", data.c_str());
270 return data;
271 }
272 } // namespace Media
273 } // namespace OHOS