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 #include "location_data_rdb_manager.h"
16 
17 #include "common_utils.h"
18 #include "location_data_rdb_helper.h"
19 #include "parameter.h"
20 #include <nlohmann/json.hpp>
21 
22 namespace OHOS {
23 namespace Location {
24 const int DEFAULT_USERID = 100;
25 const int MAX_SIZE = 100;
26 
27 const std::string LOCATION_ENHANCE_STATUS = "location_enhance_status";
28 std::mutex LocationDataRdbManager::locationSwitchModeMutex_;
29 std::mutex LocationDataRdbManager::locationWorkingStateMutex_;
30 std::mutex LocationDataRdbManager::gnssSessionStateMutex_;
GetLocationDataUriByCurrentUserId(std::string key)31 std::string LocationDataRdbManager::GetLocationDataUriByCurrentUserId(std::string key)
32 {
33     int userId = 0;
34     if (!CommonUtils::GetCurrentUserId(userId)) {
35         userId = DEFAULT_USERID;
36     }
37     std::string uri = "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_" +
38         std::to_string(userId) +
39         "?Proxy=true&key=" + key;
40     return uri;
41 }
42 
GetLocationDataUriForUser(std::string key,int32_t userId)43 std::string LocationDataRdbManager::GetLocationDataUriForUser(std::string key, int32_t userId)
44 {
45     std::string uri = "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_" +
46         std::to_string(userId) +
47         "?Proxy=true&key=" + key;
48     return uri;
49 }
50 
GetLocationDataSecureUri(std::string key)51 std::string LocationDataRdbManager::GetLocationDataSecureUri(std::string key)
52 {
53     int userId = 0;
54     if (!CommonUtils::GetCurrentUserId(userId)) {
55         userId = DEFAULT_USERID;
56     }
57     std::string uri = "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_SECURE_" +
58         std::to_string(userId) +
59         "?Proxy=true&key=" + key;
60     return uri;
61 }
62 
QuerySwitchState()63 int LocationDataRdbManager::QuerySwitchState()
64 {
65     int res = LocationDataRdbManager::GetSwitchStateFromSysparaForCurrentUser();
66     if (res == DISABLED || res == ENABLED) {
67         return res;
68     }
69     int32_t state = DEFAULT_SWITCH_STATE;
70     Uri locationDataEnableUri(GetLocationDataUriByCurrentUserId("location_enable"));
71     LocationErrCode errCode = LocationDataRdbHelper::GetInstance()->
72         GetValue(locationDataEnableUri, LOCATION_DATA_COLUMN_ENABLE, state);
73     if (errCode != ERRCODE_SUCCESS) {
74         LBSLOGE(COMMON_UTILS, "%{public}s: query state failed, errcode = %{public}d", __func__, errCode);
75         return DEFAULT_SWITCH_STATE;
76     }
77     if (res == DEFAULT_SWITCH_STATE && state != DEFAULT_SWITCH_STATE) {
78         LocationDataRdbManager::SetSwitchStateToSysparaForCurrentUser(state);
79     }
80     return state;
81 }
82 
SetSwitchStateToDb(int modeValue)83 LocationErrCode LocationDataRdbManager::SetSwitchStateToDb(int modeValue)
84 {
85     Uri locationDataEnableUri(GetLocationDataUriByCurrentUserId("location_enable"));
86     return LocationDataRdbHelper::GetInstance()->
87         SetValue(locationDataEnableUri, LOCATION_DATA_COLUMN_ENABLE, modeValue);
88 }
89 
SetSwitchStateToDbForUser(int modeValue,int32_t userId)90 LocationErrCode LocationDataRdbManager::SetSwitchStateToDbForUser(int modeValue, int32_t userId)
91 {
92     Uri locationDataEnableUri(GetLocationDataUriForUser("location_enable", userId));
93     return LocationDataRdbHelper::GetInstance()->
94         SetValue(locationDataEnableUri, LOCATION_DATA_COLUMN_ENABLE, modeValue);
95 }
96 
GetSwitchStateFromDbForUser(int32_t & state,int32_t userId)97 LocationErrCode LocationDataRdbManager::GetSwitchStateFromDbForUser(int32_t& state, int32_t userId)
98 {
99     Uri locationDataEnableUri(GetLocationDataUriForUser("location_enable", userId));
100     return LocationDataRdbHelper::GetInstance()->
101         GetValue(locationDataEnableUri, LOCATION_DATA_COLUMN_ENABLE, state);
102 }
103 
SetLocationWorkingState(int32_t state)104 bool LocationDataRdbManager::SetLocationWorkingState(int32_t state)
105 {
106     std::unique_lock<std::mutex> lock(locationWorkingStateMutex_);
107     Uri locationWorkingStateUri(GetLocationDataUriByCurrentUserId(LOCATION_WORKING_STATE));
108     LocationErrCode errCode = LocationDataRdbHelper::GetInstance()->
109         SetValue(locationWorkingStateUri, LOCATION_WORKING_STATE, state);
110     if (errCode != ERRCODE_SUCCESS) {
111         LBSLOGE(COMMON_UTILS, "%{public}s: can not set value to db, errcode = %{public}d", __func__, errCode);
112         return false;
113     }
114     return true;
115 }
116 
GetLocationWorkingState(int32_t & state)117 bool LocationDataRdbManager::GetLocationWorkingState(int32_t& state)
118 {
119     std::unique_lock<std::mutex> lock(locationWorkingStateMutex_);
120     Uri locationWorkingStateUri(GetLocationDataUriByCurrentUserId(LOCATION_WORKING_STATE));
121     LocationErrCode errCode = LocationDataRdbHelper::GetInstance()->
122         GetValue(locationWorkingStateUri, LOCATION_WORKING_STATE, state);
123     if (errCode != ERRCODE_SUCCESS) {
124         LBSLOGE(COMMON_UTILS, "%{public}s: can not get value, errcode = %{public}d", __func__, errCode);
125         return false;
126     }
127     return true;
128 }
129 
SetGnssSessionState(int32_t state,std::string uri,std::string colName)130 bool LocationDataRdbManager::SetGnssSessionState(int32_t state, std::string uri, std::string colName)
131 {
132     std::unique_lock<std::mutex> lock(gnssSessionStateMutex_);
133     Uri gnssSessionStateUri(uri);
134     LocationErrCode errCode = LocationDataRdbHelper::GetInstance()->
135         SetValue(gnssSessionStateUri, colName, state);
136     if (errCode != ERRCODE_SUCCESS) {
137         LBSLOGE(COMMON_UTILS, "%{public}s: can not set value to db, errcode = %{public}d", __func__, errCode);
138         return false;
139     }
140     return true;
141 }
142 
GetSwitchStateFromSysparaForCurrentUser()143 int LocationDataRdbManager::GetSwitchStateFromSysparaForCurrentUser()
144 {
145     int32_t userId = 0;
146     if (!CommonUtils::GetCurrentUserId(userId)) {
147         userId = DEFAULT_USERID;
148     }
149     return GetSwitchStateFromSysparaForUser(userId);
150 }
151 
SetSwitchStateToSysparaForCurrentUser(int value)152 bool LocationDataRdbManager::SetSwitchStateToSysparaForCurrentUser(int value)
153 {
154     int32_t userId = 0;
155     if (!CommonUtils::GetCurrentUserId(userId)) {
156         userId = DEFAULT_USERID;
157     }
158     return SetSwitchStateToSysparaForUser(value, userId);
159 }
160 
GetSwitchStateFromSysparaForUser(int32_t userId)161 int LocationDataRdbManager::GetSwitchStateFromSysparaForUser(int32_t userId)
162 {
163     char result[MAX_SIZE] = {0};
164     std::string value = "";
165     std::unique_lock<std::mutex> lock(locationSwitchModeMutex_);
166     auto res = GetParameter(LOCATION_SWITCH_MODE, "", result, MAX_SIZE);
167     if (res < 0 || strlen(result) == 0) {
168         LBSLOGE(COMMON_UTILS, "%{public}s get para value failed, res: %{public}d", __func__, res);
169         return DEFAULT_SWITCH_STATE;
170     }
171     value = result;
172     nlohmann::json switchInfo = nlohmann::json::parse(value, nullptr, false);
173     if (switchInfo.is_discarded()) {
174         LBSLOGE(COMMON_UTILS, "switchInfo parse failed");
175         return DEFAULT_SWITCH_STATE;
176     }
177     if (!switchInfo.contains(std::to_string(userId))) {
178         LBSLOGE(COMMON_UTILS, "userId switch %{public}d is not exist", userId);
179         return DEFAULT_SWITCH_STATE;
180     }
181     auto jsonItem = switchInfo.at(std::to_string(userId));
182     if (!jsonItem.is_number()) {
183         LBSLOGE(COMMON_UTILS, "switch state is invalid");
184         return DEFAULT_SWITCH_STATE;
185     }
186     auto state = jsonItem.get<int>();
187     return state;
188 }
189 
SetSwitchStateToSysparaForUser(int value,int32_t userId)190 bool LocationDataRdbManager::SetSwitchStateToSysparaForUser(int value, int32_t userId)
191 {
192     char result[MAX_SIZE] = {0};
193     std::unique_lock<std::mutex> lock(locationSwitchModeMutex_);
194     nlohmann::json oldSwitchInfo;
195     auto res = GetParameter(LOCATION_SWITCH_MODE, "", result, MAX_SIZE);
196     if (res < 0 || strlen(result) == 0) {
197         // If there is no value in sysparam, go on and write it.
198         LBSLOGI(COMMON_UTILS, "%{public}s get para value failed, res: %{public}d", __func__, res);
199     } else {
200         std::string SwitchStr = result;
201         oldSwitchInfo = nlohmann::json::parse(SwitchStr, nullptr, false);
202         if (oldSwitchInfo.is_discarded()) {
203             LBSLOGI(COMMON_UTILS, "switchInfo parse failed");
204             // If there is no valid value in sysparam, go on and overwrite it.
205         }
206     }
207     nlohmann::json newSwitchInfo;
208     std::vector<int> activeIds;
209     // copy oldSwitchInfo to newSwitchInfo
210     if (CommonUtils::GetAllUserId(activeIds)) {
211         for (auto && [key, state] : oldSwitchInfo.items()) {
212             if (IsUserIdInActiveIds(activeIds, key)) {
213                 newSwitchInfo[key] = state;
214             }
215         }
216     }
217     newSwitchInfo[std::to_string(userId)] = value;
218     std::string newSwitchStr = newSwitchInfo.dump();
219     char valueArray[MAX_SIZE] = {0};
220     auto ret = sprintf_s(valueArray, sizeof(valueArray), "%s", newSwitchStr.c_str());
221     if (ret <= 0) {
222         LBSLOGE(COMMON_UTILS, "sprintf_s failed, ret: %{public}d", ret);
223         return false;
224     }
225     res = SetParameter(LOCATION_SWITCH_MODE, valueArray);
226     if (res < 0) {
227         LBSLOGE(COMMON_UTILS, "%{public}s failed, res: %{public}d", __func__, res);
228         return false;
229     }
230     return true;
231 }
232 
SyncSwitchStatus()233 void LocationDataRdbManager::SyncSwitchStatus()
234 {
235     int dbState = DEFAULT_SWITCH_STATE;
236     Uri locationDataEnableUri(GetLocationDataUriByCurrentUserId("location_enable"));
237     LocationErrCode errCode = LocationDataRdbHelper::GetInstance()->
238         GetValue(locationDataEnableUri, LOCATION_DATA_COLUMN_ENABLE, dbState);
239     if (errCode != ERRCODE_SUCCESS) {
240         // It needs to be updated when it is the default, and there is no need to return.
241         LBSLOGE(COMMON_UTILS, "%{public}s: query state failed, errcode = %{public}d", __func__, errCode);
242     }
243     int sysparaState = LocationDataRdbManager::GetSwitchStateFromSysparaForCurrentUser();
244     if (sysparaState == DEFAULT_SWITCH_STATE && dbState != DEFAULT_SWITCH_STATE) {
245         LocationDataRdbManager::SetSwitchStateToSysparaForCurrentUser(dbState);
246     } else if (sysparaState != DEFAULT_SWITCH_STATE && dbState != sysparaState) {
247         LocationDataRdbManager::SetSwitchStateToDb(sysparaState);
248     }
249 }
250 
SetLocationEnhanceStatus(int32_t state)251 bool LocationDataRdbManager::SetLocationEnhanceStatus(int32_t state)
252 {
253     Uri locationWorkingStateUri(GetLocationDataSecureUri(LOCATION_ENHANCE_STATUS));
254     LocationErrCode errCode = LocationDataRdbHelper::GetInstance()->
255         SetValue(locationWorkingStateUri, LOCATION_ENHANCE_STATUS, state);
256     if (errCode != ERRCODE_SUCCESS) {
257         LBSLOGE(COMMON_UTILS,
258             "can not set value, key = %{public}s, errcode = %{public}d", LOCATION_ENHANCE_STATUS.c_str(), errCode);
259         return false;
260     }
261     return true;
262 }
263 
GetLocationEnhanceStatus(int32_t & state)264 bool LocationDataRdbManager::GetLocationEnhanceStatus(int32_t& state)
265 {
266     Uri locationWorkingStateUri(GetLocationDataSecureUri(LOCATION_ENHANCE_STATUS));
267     LocationErrCode errCode = LocationDataRdbHelper::GetInstance()->
268         GetValue(locationWorkingStateUri, LOCATION_ENHANCE_STATUS, state);
269     if (errCode != ERRCODE_SUCCESS) {
270         LBSLOGE(COMMON_UTILS,
271             "can not get value, key = %{public}s, errcode = %{public}d", LOCATION_ENHANCE_STATUS.c_str(), errCode);
272         return false;
273     }
274     return true;
275 }
276 
IsUserIdInActiveIds(std::vector<int> activeIds,std::string userId)277 bool LocationDataRdbManager::IsUserIdInActiveIds(std::vector<int> activeIds, std::string userId)
278 {
279     for (auto id : activeIds) {
280         if (std::to_string(id).compare(userId) == 0) {
281             return true;
282         }
283     }
284     return false;
285 }
286 } // namespace Location
287 } // namespace OHOS