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 "remote_command_manager.h"
17 #include "device_info_manager.h"
18 #include "sync_remote_native_token_command.h"
19 #include "remote_command_factory.h"
20 #include "token_sync_event_handler.h"
21 #include "token_sync_manager_service.h"
22 #include "accesstoken_kit.h"
23
24 #include <thread>
25
26
27 namespace OHOS {
28 namespace Security {
29 namespace AccessToken {
30 namespace {
31 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "RemoteCommandManager"};
32 }
RemoteCommandManager()33 RemoteCommandManager::RemoteCommandManager() : executors_(), mutex_()
34 {
35 ACCESSTOKEN_LOG_DEBUG(LABEL, "RemoteCommandManager()");
36 }
37
~RemoteCommandManager()38 RemoteCommandManager::~RemoteCommandManager()
39 {
40 ACCESSTOKEN_LOG_DEBUG(LABEL, "~RemoteCommandManager()");
41 }
42
GetInstance()43 RemoteCommandManager &RemoteCommandManager::GetInstance()
44 {
45 static RemoteCommandManager instance;
46 return instance;
47 }
48
Init()49 void RemoteCommandManager::Init()
50 {
51 ACCESSTOKEN_LOG_DEBUG(LABEL, "Init()");
52 }
53
AddCommand(const std::string & udid,const std::shared_ptr<BaseRemoteCommand> & command)54 int RemoteCommandManager::AddCommand(const std::string &udid, const std::shared_ptr<BaseRemoteCommand> &command)
55 {
56 if (udid.empty() || command == nullptr) {
57 ACCESSTOKEN_LOG_WARN(LABEL, "invalid udid, or null command");
58 return Constant::FAILURE;
59 }
60 std::string uniqueId = command->remoteProtocol_.uniqueId;
61 ACCESSTOKEN_LOG_INFO(LABEL, "add uniqueId");
62
63 std::shared_ptr<RemoteCommandExecutor> executor = GetOrCreateRemoteCommandExecutor(udid);
64 if (executor == nullptr) {
65 ACCESSTOKEN_LOG_ERROR(LABEL, "cannot get or create remote command executor");
66 return Constant::FAILURE;
67 }
68
69 int result = executor->AddCommand(command);
70 ACCESSTOKEN_LOG_INFO(LABEL, "add command result: %{public}d ", result);
71 return result;
72 }
73
RemoveCommand(const std::string & udid)74 void RemoteCommandManager::RemoveCommand(const std::string &udid)
75 {
76 ACCESSTOKEN_LOG_INFO(LABEL, "remove command");
77 executors_.erase(udid);
78 }
79
ExecuteCommand(const std::string & udid,const std::shared_ptr<BaseRemoteCommand> & command)80 int RemoteCommandManager::ExecuteCommand(const std::string &udid, const std::shared_ptr<BaseRemoteCommand> &command)
81 {
82 if (udid.empty() || command == nullptr) {
83 ACCESSTOKEN_LOG_WARN(LABEL, "invalid udid or null command");
84 return Constant::FAILURE;
85 }
86 std::string uniqueId = command->remoteProtocol_.uniqueId;
87 ACCESSTOKEN_LOG_INFO(LABEL, "start with udid");
88
89 std::shared_ptr<RemoteCommandExecutor> executor = GetOrCreateRemoteCommandExecutor(udid);
90 if (executor == nullptr) {
91 ACCESSTOKEN_LOG_ERROR(LABEL, "cannot get or create remote command executor");
92 return Constant::FAILURE;
93 }
94
95 int result = executor->ProcessOneCommand(command);
96 ACCESSTOKEN_LOG_INFO(LABEL, "remoteCommandExecutor processOneCommand result:%{public}d ", result);
97 return result;
98 }
99
ProcessDeviceCommandImmediately(const std::string & udid)100 int RemoteCommandManager::ProcessDeviceCommandImmediately(const std::string &udid)
101 {
102 if (udid.empty()) {
103 ACCESSTOKEN_LOG_WARN(LABEL, "invalid udid");
104 return Constant::FAILURE;
105 }
106 ACCESSTOKEN_LOG_INFO(LABEL, "start with udid");
107 auto executorIt = executors_.find(udid);
108 if (executorIt == executors_.end()) {
109 ACCESSTOKEN_LOG_ERROR(LABEL, "no executor found");
110 return Constant::FAILURE;
111 }
112
113 auto executor = executorIt->second;
114 if (executor == nullptr) {
115 ACCESSTOKEN_LOG_INFO(LABEL, "RemoteCommandExecutor is null for udid");
116 return Constant::FAILURE;
117 }
118
119 int result = executor->ProcessBufferedCommands();
120 ACCESSTOKEN_LOG_INFO(LABEL, "processBufferedCommands result: %{public}d", result);
121 return result;
122 }
123
Loop()124 int RemoteCommandManager::Loop()
125 {
126 ACCESSTOKEN_LOG_INFO(LABEL, "start");
127 for (auto it = executors_.begin(); it != executors_.end(); it++) {
128 ACCESSTOKEN_LOG_INFO(LABEL, "udid:%{public}s", it->first.c_str());
129 (*it).second->ProcessBufferedCommandsWithThread();
130 }
131 return Constant::SUCCESS;
132 }
133
134 /**
135 * caller: service connection listener
136 */
Clear()137 void RemoteCommandManager::Clear()
138 {
139 ACCESSTOKEN_LOG_INFO(LABEL, "remove all remote command executors.");
140
141 std::map<std::string, std::shared_ptr<RemoteCommandExecutor>> dummy;
142 executors_.swap(dummy);
143 executors_.clear();
144 }
145
146 /**
147 * caller: device listener
148 */
NotifyDeviceOnline(const std::string & nodeId)149 int RemoteCommandManager::NotifyDeviceOnline(const std::string &nodeId)
150 {
151 if (!DataValidator::IsDeviceIdValid(nodeId)) {
152 ACCESSTOKEN_LOG_INFO(LABEL, "invalid nodeId");
153 return Constant::FAILURE;
154 }
155 ACCESSTOKEN_LOG_INFO(LABEL, "operation start with nodeId");
156
157 auto executor = GetOrCreateRemoteCommandExecutor(nodeId);
158 std::unique_lock<std::mutex> lock(mutex_);
159 if (executor == nullptr) {
160 ACCESSTOKEN_LOG_ERROR(LABEL, "cannot get or create remote command executor");
161 return Constant::FAILURE;
162 }
163
164 if (executor->GetChannel() == nullptr) {
165 auto channel = RemoteCommandExecutor::CreateChannel(nodeId);
166 if (channel == nullptr) {
167 ACCESSTOKEN_LOG_ERROR(LABEL, "create channel failed.");
168 return Constant::FAILURE;
169 }
170 executor->SetChannel(channel);
171 }
172
173 lock.unlock();
174
175 std::function<void()> delayed = ([=]() {
176 const std::shared_ptr<SyncRemoteNativeTokenCommand> syncRemoteNativeTokenCommand =
177 RemoteCommandFactory::GetInstance().NewSyncRemoteNativeTokenCommand(Constant::GetLocalDeviceId(),
178 nodeId);
179
180 const int32_t resultCode = RemoteCommandManager::GetInstance().ExecuteCommand(
181 nodeId, syncRemoteNativeTokenCommand);
182 if (resultCode != Constant::SUCCESS) {
183 ACCESSTOKEN_LOG_INFO(LABEL,
184 "%{public}s: RemoteExecutorManager executeCommand syncRemoteNativeTokenCommand failed, return %d",
185 __func__, resultCode);
186 return;
187 }
188 });
189
190 std::shared_ptr<TokenSyncEventHandler> handler =
191 DelayedSingleton<TokenSyncManagerService>::GetInstance()->GetSendEventHandler();
192 if (handler == nullptr) {
193 ACCESSTOKEN_LOG_ERROR(LABEL, "fail to get EventHandler");
194 return Constant::FAILURE;
195 }
196 handler->ProxyPostTask(delayed, "HandleDeviceOnline", Constant::DELAY_SYNC_TOKEN_MS);
197
198 return Constant::SUCCESS;
199 }
200
201 /**
202 * caller: device listener
203 */
NotifyDeviceOffline(const std::string & nodeId)204 int RemoteCommandManager::NotifyDeviceOffline(const std::string &nodeId)
205 {
206 if (!DataValidator::IsDeviceIdValid(nodeId)) {
207 ACCESSTOKEN_LOG_INFO(LABEL, "invalid nodeId");
208 return Constant::FAILURE;
209 }
210 ACCESSTOKEN_LOG_INFO(LABEL, "operation start with nodeId");
211
212 auto channel = GetExecutorChannel(nodeId);
213 if (channel != nullptr) {
214 channel->Release();
215 }
216
217 std::unique_lock<std::mutex> lock(mutex_);
218 RemoveCommand(nodeId);
219 lock.unlock();
220
221 DeviceInfo devInfo;
222 bool result = DeviceInfoManager::GetInstance().GetDeviceInfo(nodeId, DeviceIdType::UNKNOWN, devInfo);
223 if (!result) {
224 ACCESSTOKEN_LOG_INFO(LABEL, "get remote networkId failed");
225 return Constant::FAILURE;
226 }
227 std::string networkId = devInfo.deviceId.networkId;
228 std::function<void()> delayed = ([=]() {
229 AccessTokenKit::DeleteRemoteDeviceTokens(networkId);
230 });
231
232 std::shared_ptr<TokenSyncEventHandler> handler =
233 DelayedSingleton<TokenSyncManagerService>::GetInstance()->GetSendEventHandler();
234 if (handler == nullptr) {
235 ACCESSTOKEN_LOG_ERROR(LABEL, "fail to get EventHandler");
236 return Constant::FAILURE;
237 }
238 handler->ProxyPostTask(delayed, "HandleDeviceOffline");
239
240 ACCESSTOKEN_LOG_INFO(LABEL, "complete");
241 return Constant::SUCCESS;
242 }
243
GetOrCreateRemoteCommandExecutor(const std::string & nodeId)244 std::shared_ptr<RemoteCommandExecutor> RemoteCommandManager::GetOrCreateRemoteCommandExecutor(const std::string &nodeId)
245 {
246 ACCESSTOKEN_LOG_DEBUG(LABEL, "begin, nodeId");
247
248 std::unique_lock<std::mutex> lock(mutex_);
249 auto executorIter = executors_.find(nodeId);
250 if (executorIter != executors_.end()) {
251 return executorIter->second;
252 }
253
254 auto executor = std::make_shared<RemoteCommandExecutor>(nodeId);
255 if (executor == nullptr) {
256 ACCESSTOKEN_LOG_INFO(LABEL, "cannot create remote command executor, nodeId");
257 return nullptr;
258 }
259
260 executors_.insert(std::pair<std::string, std::shared_ptr<RemoteCommandExecutor>>(nodeId, executor));
261 ACCESSTOKEN_LOG_DEBUG(LABEL, "executor added, nodeId");
262 return executor;
263 }
264
265 /**
266 * caller: session listener(onBytesReceived), device listener(offline)
267 */
GetExecutorChannel(const std::string & nodeId)268 std::shared_ptr<RpcChannel> RemoteCommandManager::GetExecutorChannel(const std::string &nodeId)
269 {
270 ACCESSTOKEN_LOG_DEBUG(LABEL, "convert udid start, nodeId");
271 std::string udid = DeviceInfoManager::GetInstance().ConvertToUniqueDeviceIdOrFetch(nodeId);
272 if (!DataValidator::IsDeviceIdValid(udid)) {
273 ACCESSTOKEN_LOG_WARN(
274 LABEL, "converted udid is invalid, nodeId");
275 return nullptr;
276 }
277 std::map<std::string, std::shared_ptr<RemoteCommandExecutor>>::iterator iter = executors_.find(udid);
278 if (iter == executors_.end()) {
279 ACCESSTOKEN_LOG_INFO(LABEL, "executor not found");
280 return nullptr;
281 }
282 std::shared_ptr<RemoteCommandExecutor> executor = iter->second;
283 if (executor == nullptr) {
284 ACCESSTOKEN_LOG_INFO(LABEL, "executor is null");
285 return nullptr;
286 }
287 return executor->GetChannel();
288 }
289 } // namespace AccessToken
290 } // namespace Security
291 } // namespace OHOS
292