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