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 
24 namespace OHOS {
25 namespace Media {
26 
27 static const std::string SETTINGS_DATA_URI_BASE =
28     "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_";
29 static const std::string SETTINGS_DATA_FIELD_KEY = "KEYWORD";
30 static const std::string SETTINGS_DATA_FIELD_VAL = "VALUE";
31 static std::vector<std::string> SETTINGS_COLUMNS = {SETTINGS_DATA_FIELD_VAL};
32 static const int DEFAULT_USERID = 100;
33 
DualFwkConfLoader()34 DualFwkConfLoader::DualFwkConfLoader() {}
35 
Init()36 int32_t DualFwkConfLoader::Init()
37 {
38     DataShare::CreateOptions options;
39 
40     int userId = 0;
41     if (!RingtoneRestoreDbUtils::GetUserID(userId)) {
42         RINGTONE_DEBUG_LOG("Failed to get userId, using DEFAULT_USERID=%{public}d", DEFAULT_USERID);
43         userId = DEFAULT_USERID;
44     }
45     settingsDataUri_ = SETTINGS_DATA_URI_BASE + std::to_string(userId);
46     RINGTONE_DEBUG_LOG("Getting data share helper with SETTINGS_DATA_URI = %{public}s", settingsDataUri_.c_str());
47 
48     dataShareHelper_ = DataShare::DataShareHelper::Creator(settingsDataUri_, options);
49     if (dataShareHelper_ == nullptr) {
50         RINGTONE_WARN_LOG("dataShareHelper_ is null, failed to get data share helper");
51         return E_ERR;
52     }
53 
54     RINGTONE_INFO_LOG("Successfully initialized.");
55     return E_OK;
56 }
57 
GetSound(const std::string &line)58 static std::string GetSound(const std::string &line)
59 {
60     std::string tag = "sound=\"";
61     auto lenTag = tag.size();
62     auto positionOfTag = line.find(tag);
63     if (positionOfTag == std::string::npos) {
64         return "";
65     }
66     auto positionOfQuote = line.substr(positionOfTag + lenTag).find("\"");
67     if (positionOfQuote == std::string::npos) {
68         return "";
69     }
70     return line.substr(positionOfTag + lenTag, positionOfQuote);
71 }
72 
ParseBackupFile(const std::string &backupFile, const std::vector<std::string> &keys, std::map<std::string, std::string> &results)73 static int32_t ParseBackupFile(const std::string &backupFile, const std::vector<std::string> &keys,
74     std::map<std::string, std::string> &results)
75 {
76     RINGTONE_INFO_LOG("parse backupfile %{public}s uid=%{public}d", backupFile.c_str(), getuid());
77     if (RingtoneFileUtils::IsFileExists(backupFile)) {
78         RINGTONE_ERR_LOG("the file exists path: %{private}s", backupFile.c_str());
79         return E_FILE_EXIST;
80     }
81     std::ifstream fs(backupFile);
82     if (!fs.good()) {
83         RINGTONE_ERR_LOG("failed to open file %{private}s", backupFile.c_str());
84         return E_ERR;
85     }
86 
87     std::string line;
88     while (std::getline(fs, line)) {
89         for (const auto &key : keys) {
90             auto pos = line.find(key);
91             if (pos == std::string::npos) {
92                 continue;
93             }
94             std::string value = GetSound(line);
95             if (value.size() > 0) {
96                 results.emplace(key, value);
97             }
98         }
99     }
100     return E_SUCCESS;
101 }
102 
Load(DualFwkConf &conf, const RestoreSceneType &type, const std::string &backupFile)103 int32_t DualFwkConfLoader::Load(DualFwkConf &conf, const RestoreSceneType &type, const std::string &backupFile)
104 {
105     if (dataShareHelper_ == nullptr) {
106         RINGTONE_ERR_LOG("DualFwkConfLoader is not initialized successfully");
107         return E_ERR;
108     }
109     std::map<std::string, std::string> backupConfigs;
110     if (ParseBackupFile(backupFile, {"mms_sim1_channel", "mms_sim2_channel"}, backupConfigs) != E_SUCCESS) {
111         RINGTONE_WARN_LOG("Failed to parse backup file %{public}s", backupFile.c_str());
112     }
113 
114     if (type == RestoreSceneType::RESTORE_SCENE_TYPE_DUAL_CLONE) {
115         RINGTONE_INFO_LOG("Load configurations for RestoreSceneType::RESTORE_SCENE_TYPE_DUAL_CLONE");
116         conf.notificationSoundPath = GetConf("notification_sound");
117         conf.ringtonePath = GetConf("ringtone_path");
118         conf.ringtone2Path = GetConf("ringtone2_path");
119         conf.alarmAlertPath = GetConf("alarm_alert");
120         conf.messagePath = GetConf("message_path");
121         conf.messageSub1 = GetConf("message_sub1");
122         conf.messagePath = backupConfigs["mms_sim1_channel"];
123         conf.messageSub1 = backupConfigs["mms_sim2_channel"];
124     } else {
125         RINGTONE_INFO_LOG("Load configurations for RestoreSceneType::RESTORE_SCENE_TYPE_DUAL_UPGRADE");
126         conf.notificationSoundPath = GetConf("notification_sound_path");
127         conf.ringtonePath = GetConf("ringtone_path");
128         conf.ringtone2Path = GetConf("ringtone2_path");
129         conf.alarmAlertPath = GetConf("alarm_alert_path");
130         conf.messagePath = GetConf("message_path");
131         conf.messageSub1 = GetConf("message_sub1");
132     }
133 
134     return E_OK;
135 }
136 
ShowConf(const DualFwkConf &conf)137 void DualFwkConfLoader::ShowConf(const DualFwkConf &conf)
138 {
139     RINGTONE_DEBUG_LOG("===================================================");
140     RINGTONE_DEBUG_LOG("conf.notificationSoundPath  = %{public}s", conf.notificationSoundPath.c_str());
141     RINGTONE_DEBUG_LOG("conf.ringtonePath = %{public}s", conf.ringtonePath.c_str());
142     RINGTONE_DEBUG_LOG("conf.ringtone2Path = %{public}s", conf.ringtone2Path.c_str());
143     RINGTONE_DEBUG_LOG("conf.alarmAlertPath = %{public}s", conf.alarmAlertPath.c_str());
144     RINGTONE_DEBUG_LOG("conf.messagePath = %{public}s", conf.messagePath.c_str());
145     RINGTONE_DEBUG_LOG("conf.messageSub1 = %{public}s", conf.messageSub1.c_str());
146     RINGTONE_DEBUG_LOG("===================================================");
147 }
148 
GetConf(const std::string &key)149 std::string DualFwkConfLoader::GetConf(const std::string &key)
150 {
151     DataShare::DataSharePredicates dataSharePredicates;
152     dataSharePredicates.EqualTo(SETTINGS_DATA_FIELD_KEY, key);
153     Uri uri(settingsDataUri_);
154     auto resultSet = dataShareHelper_->Query(uri, dataSharePredicates, SETTINGS_COLUMNS);
155     if (resultSet == nullptr) {
156         RINGTONE_DEBUG_LOG("resultSet is null, failed to get value of key = %{public}s", key.c_str());
157         return "";
158     }
159 
160     int32_t numRows = 0;
161     resultSet->GetRowCount(numRows);
162     RINGTONE_INFO_LOG("%{public}d records found with key = %{public}s", numRows, key.c_str());
163     if (numRows == 0) {
164         RINGTONE_DEBUG_LOG("no record at key = %{public}s, returning an empty string.", key.c_str());
165         return "";
166     }
167     int32_t columnIndex = 0;
168     int32_t rowNumber = 0;
169     resultSet->GoToRow(rowNumber);
170     std::string valueResult = "";
171     int32_t ret = resultSet->GetString(columnIndex, valueResult);
172     if (ret != 0) {
173         RINGTONE_DEBUG_LOG("failed to get string, returning an empty string.");
174     } else {
175         RINGTONE_DEBUG_LOG("valueResult = %{public}s", valueResult.c_str());
176     }
177     return valueResult;
178 }
179 } // namespace Media
180 } // namespace OHOS