1 /*
2  * Copyright (C) 2022 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 "location_data_manager.h"
17 
18 #include "uri.h"
19 
20 #include "switch_callback_proxy.h"
21 #include "constant_definition.h"
22 #include "location_data_rdb_helper.h"
23 #include "location_data_rdb_manager.h"
24 #include "location_log.h"
25 #include "common_hisysevent.h"
26 #include "parameter.h"
27 #include "permission_manager.h"
28 namespace OHOS {
29 namespace Location {
30 const int APP_INFO_SIZE = 3;
31 const int APP_INFO_UID_INDEX = 0;
32 const int APP_INFO_TOKENID_INDEX = 1;
33 const int APP_INFO_LASTSTATE_INDEX = 2;
GetInstance()34 LocationDataManager* LocationDataManager::GetInstance()
35 {
36     static LocationDataManager data;
37     return &data;
38 }
39 
LocationDataManager()40 LocationDataManager::LocationDataManager()
41 {
42 }
43 
~LocationDataManager()44 LocationDataManager::~LocationDataManager()
45 {
46 }
47 
ReportSwitchState(bool isEnabled)48 LocationErrCode LocationDataManager::ReportSwitchState(bool isEnabled)
49 {
50     int state = isEnabled ? ENABLED : DISABLED;
51     std::unique_lock<std::mutex> lock(mutex_);
52     for (auto item : switchCallbackMap_) {
53         auto appInfo = item.second;
54         if (appInfo.size() < APP_INFO_SIZE) {
55             continue;
56         }
57         int uid = appInfo[APP_INFO_UID_INDEX];
58         int tokenId = appInfo[APP_INFO_TOKENID_INDEX];
59         int lastState = appInfo[APP_INFO_LASTSTATE_INDEX];
60         if (!PermissionManager::CheckIsSystemSa(tokenId) &&
61             !CommonUtils::CheckAppForUser(uid)) {
62             LBSLOGE(LOCATOR, "It is not a listener of Current user, no need to report. uid : %{public}d", uid);
63             continue;
64         }
65         if (state == lastState) {
66             // current state is same to before, no need to report
67             continue;
68         }
69         sptr<IRemoteObject> remoteObject = item.first;
70         if (remoteObject == nullptr) {
71             LBSLOGE(LOCATOR, "remoteObject callback is nullptr");
72             continue;
73         }
74         auto callback = std::make_unique<SwitchCallbackProxy>(remoteObject);
75         LBSLOGI(LOCATOR, "ReportSwitchState to uid : %{public}d , state = %{public}d", uid, state);
76         callback->OnSwitchChange(state);
77         appInfo[APP_INFO_LASTSTATE_INDEX] = state;
78         switchCallbackMap_[remoteObject] = appInfo;
79     }
80     return ERRCODE_SUCCESS;
81 }
82 
RegisterSwitchCallback(const sptr<IRemoteObject> & callback,AppIdentity & identity)83 LocationErrCode LocationDataManager::RegisterSwitchCallback(const sptr<IRemoteObject>& callback,
84     AppIdentity& identity)
85 {
86     if (callback == nullptr) {
87         LBSLOGE(LOCATOR, "register an invalid switch callback");
88         return ERRCODE_INVALID_PARAM;
89     }
90     std::unique_lock<std::mutex> lock(mutex_);
91     auto iter = switchCallbackMap_.find(callback);
92     if (iter != switchCallbackMap_.end()) {
93         LBSLOGE(LOCATOR, "callback has registered");
94         return ERRCODE_SUCCESS;
95     }
96     std::vector<int> appInfo;
97     appInfo.push_back(identity.GetUid());
98     appInfo.push_back(identity.GetTokenId());
99     appInfo.push_back(DEFAULT_SWITCH_STATE);
100     switchCallbackMap_[callback] = appInfo;
101     LBSLOGD(LOCATOR, "after uid:%{public}d register, switch callback size:%{public}s",
102         identity.GetUid(), std::to_string(switchCallbackMap_.size()).c_str());
103     if (!IsSwitchObserverReg()) {
104         RegisterLocationSwitchObserver();
105     }
106     return ERRCODE_SUCCESS;
107 }
108 
UnregisterSwitchCallback(const sptr<IRemoteObject> & callback)109 LocationErrCode LocationDataManager::UnregisterSwitchCallback(const sptr<IRemoteObject>& callback)
110 {
111     if (callback == nullptr) {
112         LBSLOGE(LOCATOR, "unregister an invalid switch callback");
113         return ERRCODE_INVALID_PARAM;
114     }
115     std::unique_lock<std::mutex> lock(mutex_);
116     auto iter = switchCallbackMap_.find(callback);
117     if (iter != switchCallbackMap_.end()) {
118         switchCallbackMap_.erase(iter);
119     }
120     LBSLOGD(LOCATOR, "after unregister, switch callback size:%{public}s",
121         std::to_string(switchCallbackMap_.size()).c_str());
122     return ERRCODE_SUCCESS;
123 }
124 
IsSwitchObserverReg()125 bool LocationDataManager::IsSwitchObserverReg()
126 {
127     std::unique_lock<std::mutex> lock(isSwitchObserverRegMutex_);
128     return isSwitchObserverReg_;
129 }
130 
SetIsSwitchObserverReg(bool isSwitchObserverReg)131 void LocationDataManager::SetIsSwitchObserverReg(bool isSwitchObserverReg)
132 {
133     std::unique_lock<std::mutex> lock(isSwitchObserverRegMutex_);
134     isSwitchObserverReg_ = isSwitchObserverReg;
135 }
136 
IsFirstReport()137 bool LocationDataManager::IsFirstReport()
138 {
139     std::unique_lock<std::mutex> lock(isFirstReportMutex_);
140     return isFirstReport_;
141 }
142 
SetIsFirstReport(bool isFirstReport)143 void LocationDataManager::SetIsFirstReport(bool isFirstReport)
144 {
145     std::unique_lock<std::mutex> lock(isFirstReportMutex_);
146     isFirstReport_ = isFirstReport;
147 }
148 
RegisterLocationSwitchObserver()149 void LocationDataManager::RegisterLocationSwitchObserver()
150 {
151     auto eventCallback = [](const char *key, const char *value, void *context) {
152         int32_t state = DEFAULT_SWITCH_STATE;
153         state = LocationDataRdbManager::QuerySwitchState();
154         auto manager = LocationDataManager::GetInstance();
155         if (manager->IsFirstReport()) {
156             LBSLOGI(LOCATOR, "first switch callback, no need to report");
157             manager->SetIsFirstReport(false);
158             return;
159         }
160         if (state == DEFAULT_SWITCH_STATE) {
161             LBSLOGE(LOCATOR, "LOCATION_SWITCH_MODE changed. state %{public}d. do not report", state);
162             return;
163         }
164         bool switchState = (state == ENABLED);
165         LBSLOGI(LOCATOR, "LOCATION_SWITCH_MODE changed. switchState %{public}d", switchState);
166         manager->ReportSwitchState(switchState);
167     };
168 
169     int ret = WatchParameter(LOCATION_SWITCH_MODE, eventCallback, nullptr);
170     if (ret != SUCCESS) {
171         LBSLOGE(LOCATOR, "WatchParameter fail");
172         return;
173     }
174     SetIsSwitchObserverReg(true);
175     return;
176 }
177 }  // namespace Location
178 }  // namespace OHOS
179