1 /*
2 * Copyright (c) 2021-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 "distributed_screen_status_manager.h"
17
18 #include "ans_inner_errors.h"
19 #include "ans_log_wrapper.h"
20
21 namespace OHOS {
22 namespace Notification {
23 namespace {
24 const std::string APP_ID = "notification_service";
25 const std::string STORE_ID = "distributed_screen_status";
26 const std::string DELIMITER = "|";
27 const std::string SCREEN_STATUS_LABEL = "screen_status";
28 const std::string SCREEN_STATUS_VALUE_ON = "on";
29 const std::string SCREEN_STATUS_VALUE_OFF = "off";
30 constexpr char KV_STORE_PATH[] = "/data/service/el1/public/database/notification_service";
31 } // namespace
32
DistributedScreenStatusManager()33 DistributedScreenStatusManager::DistributedScreenStatusManager() : DistributedFlowControl()
34 {
35 DistributedDeviceCallback::IDeviceChange callback = {
36 .OnConnected = std::bind(&DistributedScreenStatusManager::OnDeviceConnected, this, std::placeholders::_1),
37 .OnDisconnected = std::bind(&DistributedScreenStatusManager::OnDeviceDisconnected, this, std::placeholders::_1),
38 };
39 deviceCb_ = std::make_shared<DistributedDeviceCallback>(callback);
40 GetKvDataManager();
41 }
42
~DistributedScreenStatusManager()43 DistributedScreenStatusManager::~DistributedScreenStatusManager()
44 {}
45
OnDeviceConnected(const std::string & deviceId)46 void DistributedScreenStatusManager::OnDeviceConnected(const std::string &deviceId)
47 {
48 ANS_LOGD("deviceId:%{public}s", deviceId.c_str());
49 std::lock_guard<std::recursive_mutex> lock(mutex_);
50 CheckKvStore();
51 }
52
OnDeviceDisconnected(const std::string & deviceId)53 void DistributedScreenStatusManager::OnDeviceDisconnected(const std::string &deviceId)
54 {
55 std::lock_guard<std::recursive_mutex> lock(mutex_);
56 if (!CheckKvDataManager()) {
57 return;
58 }
59
60 std::vector<DistributedKv::DeviceInfo> devInfoList;
61 DistributedKv::Status status =
62 kvDataManager_->GetDeviceList(devInfoList, DistributedKv::DeviceFilterStrategy::NO_FILTER);
63 if (status != DistributedKv::Status::SUCCESS) {
64 ANS_LOGE("kvDataManager GetDeviceList() failed ret = 0x%{public}x", status);
65 kvDataManager_.reset();
66 return;
67 }
68
69 if (!devInfoList.empty()) {
70 return;
71 }
72
73 kvStore_.reset();
74
75 DistributedKv::AppId appId = {.appId = APP_ID};
76 DistributedKv::StoreId storeId = {.storeId = STORE_ID};
77 kvDataManager_->DeleteKvStore(appId, storeId, KV_STORE_PATH);
78
79 if (!CheckKvStore()) {
80 return;
81 }
82
83 SetLocalScreenStatus(localScreenOn_);
84 }
85
GetKvDataManager(void)86 void DistributedScreenStatusManager::GetKvDataManager(void)
87 {
88 kvDataManager_ = std::make_unique<DistributedKv::DistributedKvDataManager>();
89 if (kvDataManager_ != nullptr) {
90 DistributedKv::Status status = kvDataManager_->StartWatchDeviceChange(deviceCb_);
91 if (status != DistributedKv::Status::SUCCESS) {
92 ANS_LOGW("kvDataManager StartWatchDeviceChange failed ret = 0x%{public}x", status);
93 kvDataManager_.reset();
94 }
95 }
96
97 KvManagerFlowControlClear();
98 }
99
CheckKvDataManager(void)100 bool DistributedScreenStatusManager::CheckKvDataManager(void)
101 {
102 if (kvDataManager_ == nullptr) {
103 GetKvDataManager();
104 }
105 if (kvDataManager_ == nullptr) {
106 ANS_LOGE("kvDataManager is nullptr.");
107 return false;
108 }
109 return true;
110 }
111
GetKvStore(void)112 void DistributedScreenStatusManager::GetKvStore(void)
113 {
114 if (!CheckKvDataManager()) {
115 return;
116 }
117 DistributedKv::Options options = {
118 .createIfMissing = true,
119 .autoSync = true,
120 .area = DistributedKv::EL1,
121 .kvStoreType = DistributedKv::KvStoreType::SINGLE_VERSION,
122 .baseDir = KV_STORE_PATH
123 };
124 DistributedKv::AppId appId = {.appId = APP_ID};
125 DistributedKv::StoreId storeId = {.storeId = STORE_ID};
126 DistributedKv::Status status = kvDataManager_->GetSingleKvStore(options, appId, storeId, kvStore_);
127 if (status != DistributedKv::Status::SUCCESS) {
128 ANS_LOGE("kvDataManager GetSingleKvStore failed ret = 0x%{public}x", status);
129 kvStore_.reset();
130 kvDataManager_->StopWatchDeviceChange(deviceCb_);
131 kvDataManager_.reset();
132 return;
133 }
134
135 KvStoreFlowControlClear();
136 }
137
CheckKvStore(void)138 bool DistributedScreenStatusManager::CheckKvStore(void)
139 {
140 if (kvStore_ == nullptr) {
141 GetKvStore();
142 }
143 if (kvStore_ == nullptr) {
144 ANS_LOGE("kvStore is nullptr.");
145 return false;
146 }
147 return true;
148 }
149
GenerateDistributedKey(const std::string & deviceId)150 std::string DistributedScreenStatusManager::GenerateDistributedKey(const std::string &deviceId)
151 {
152 return deviceId + DELIMITER + SCREEN_STATUS_LABEL;
153 }
154
CheckRemoteDevicesIsUsing(bool & isUsing)155 ErrCode DistributedScreenStatusManager::CheckRemoteDevicesIsUsing(bool &isUsing)
156 {
157 std::lock_guard<std::recursive_mutex> lock(mutex_);
158 if (!CheckKvDataManager() || kvStore_ == nullptr) {
159 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
160 }
161
162 if (!KvManagerFlowControl() || !KvStoreFlowControl()) {
163 ANS_LOGE("flow control.");
164 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
165 }
166
167 std::vector<DistributedKv::DeviceInfo> devInfoList;
168 DistributedKv::Status status =
169 kvDataManager_->GetDeviceList(devInfoList, DistributedKv::DeviceFilterStrategy::NO_FILTER);
170 if (status != DistributedKv::Status::SUCCESS) {
171 ANS_LOGE("kvDataManager GetDeviceList() failed ret = 0x%{public}x", status);
172 kvDataManager_.reset();
173 return ERR_ANS_DISTRIBUTED_GET_INFO_FAILED;
174 }
175
176 DistributedKv::Key prefixKey("");
177 std::vector<DistributedKv::Entry> entries;
178 status = kvStore_->GetEntries(prefixKey, entries);
179 if (status != DistributedKv::Status::SUCCESS) {
180 ANS_LOGE("kvStore GetEntries() failed ret = 0x%{public}x", status);
181 kvStore_.reset();
182 return ERR_ANS_DISTRIBUTED_GET_INFO_FAILED;
183 }
184
185 for (auto entry : entries) {
186 std::string key = entry.key.ToString();
187 std::string deviceId = key.substr(0, key.find_first_of(DELIMITER));
188 ANS_LOGD("value:%{public}s", entry.value.ToString().c_str());
189 for (auto devInfo : devInfoList) {
190 if (devInfo.deviceId == deviceId) {
191 isUsing = isUsing || (entry.value.ToString() == SCREEN_STATUS_VALUE_ON);
192 break;
193 }
194 }
195 if (isUsing) {
196 break;
197 }
198 }
199
200 ANS_LOGI("%{public}s, isUsing:%{public}s", __FUNCTION__, isUsing ? "true" : "false");
201 return ERR_OK;
202 }
203
SetLocalScreenStatus(bool screenOn)204 ErrCode DistributedScreenStatusManager::SetLocalScreenStatus(bool screenOn)
205 {
206 std::lock_guard<std::recursive_mutex> lock(mutex_);
207 ANS_LOGI("%{public}s, screenOn:%{public}s", __FUNCTION__, screenOn ? "true" : "false");
208 localScreenOn_ = screenOn;
209 if (kvStore_ == nullptr) {
210 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
211 }
212
213 if (!KvManagerFlowControl() || !KvStoreFlowControl()) {
214 ANS_LOGE("flow control.");
215 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
216 }
217
218 DistributedKv::DeviceInfo localDevice;
219 DistributedKv::Status status = kvDataManager_->GetLocalDevice(localDevice);
220 if (status != DistributedKv::Status::SUCCESS) {
221 ANS_LOGE("kvDataManager GetLocalDevice() failed ret = 0x%{public}x", status);
222 return ERR_ANS_DISTRIBUTED_GET_INFO_FAILED;
223 }
224
225 DistributedKv::Key kvStoreKey = GenerateDistributedKey(localDevice.deviceId);
226 DistributedKv::Value kvStoreValue = screenOn ? SCREEN_STATUS_VALUE_ON : SCREEN_STATUS_VALUE_OFF;
227 status = kvStore_->Put(kvStoreKey, kvStoreValue);
228 if (status != DistributedKv::Status::SUCCESS) {
229 ANS_LOGE("kvStore Put() failed ret = 0x%{public}x", status);
230 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
231 }
232
233 return ERR_OK;
234 }
235 } // namespace Notification
236 } // namespace OHOS