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