1 /*
2 * Copyright (c) 2023-2023 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 "camera_app_manager_client.h"
17 #include "camera_log.h"
18 #include "camera_window_manager_agent.h"
19 #include "camera_window_manager_client.h"
20 #include "ipc_skeleton.h"
21 #include "hcamera_device_manager.h"
22 #include <mutex>
23 #include <regex>
24
25 namespace OHOS {
26 namespace CameraStandard {
27 static const int32_t FOREGROUND_STATE_OF_PROCESS = 0;
28 static const int32_t PIP_STATE_OF_PROCESS = 1;
29 static const int32_t BCAKGROUND_STATE_OF_PROCESS = 2;
30 static const int32_t UNKNOW_STATE_OF_PROCESS = 3;
31 static const std::unordered_map<int32_t, int32_t> APP_MGR_STATE_TO_CAMERA_STATE = {
32 {2, FOREGROUND_STATE_OF_PROCESS},
33 {4, BCAKGROUND_STATE_OF_PROCESS}
34 };
35 static const int32_t FOCUSED_STATE_OF_PROCESS = 1;
36 static const int32_t UNFOCUSED_STATE_OF_PROCESS = 0;
37 sptr<HCameraDeviceManager> HCameraDeviceManager::cameraDeviceManager_;
38 std::mutex HCameraDeviceManager::instanceMutex_;
39
HCameraDeviceManager()40 HCameraDeviceManager::HCameraDeviceManager()
41 {
42 concurrentSelector_ = new CameraConcurrentSelector();
43 }
44
~HCameraDeviceManager()45 HCameraDeviceManager::~HCameraDeviceManager()
46 {
47 HCameraDeviceManager::cameraDeviceManager_ = nullptr;
48 }
49
GetInstance()50 sptr<HCameraDeviceManager> &HCameraDeviceManager::GetInstance()
51 {
52 if (cameraDeviceManager_ == nullptr) {
53 std::unique_lock<std::mutex> lock(instanceMutex_);
54 if (cameraDeviceManager_ == nullptr) {
55 MEDIA_INFO_LOG("Initializing camera device manager instance");
56 cameraDeviceManager_ = new HCameraDeviceManager();
57 CameraWindowManagerClient::GetInstance();
58 }
59 }
60 return cameraDeviceManager_;
61 }
62
GetActiveCamerasCount()63 size_t HCameraDeviceManager::GetActiveCamerasCount()
64 {
65 MEDIA_INFO_LOG("HCameraDeviceManager::GetActiveCamerasCount: %{public}zu", activeCameras_.size());
66 return activeCameras_.size();
67 }
68
AddDevice(pid_t pid,sptr<HCameraDevice> device)69 void HCameraDeviceManager::AddDevice(pid_t pid, sptr<HCameraDevice> device)
70 {
71 MEDIA_INFO_LOG("HCameraDeviceManager::AddDevice start, cameraID: %{public}s", device->GetCameraId().c_str());
72 std::lock_guard<std::mutex> lock(mapMutex_);
73 int32_t cost = 0;
74 std::set<std::string> conflicting;
75 device->GetCameraResourceCost(cost, conflicting);
76 int32_t uidOfRequestProcess = IPCSkeleton::GetCallingUid();
77 int32_t pidOfRequestProcess = IPCSkeleton::GetCallingPid();
78 uint32_t accessTokenIdOfRequestProc = IPCSkeleton::GetCallingTokenID();
79 sptr<HCameraDeviceHolder> cameraHolder = new HCameraDeviceHolder(
80 pidOfRequestProcess, uidOfRequestProcess, FOREGROUND_STATE_OF_PROCESS,
81 FOCUSED_STATE_OF_PROCESS, device, accessTokenIdOfRequestProc, cost, conflicting);
82 pidToCameras_[pid].push_back(cameraHolder);
83 MEDIA_DEBUG_LOG("HCameraDeviceManager::AddDevice pidToCameras_ size: %{public}zu", pidToCameras_.size());
84 activeCameras_.push_back(cameraHolder);
85 MEDIA_INFO_LOG("HCameraDeviceManager::AddDevice end, cameraID: %{public}s", device->GetCameraId().c_str());
86 }
87
RemoveDevice(const std::string & cameraId)88 void HCameraDeviceManager::RemoveDevice(const std::string &cameraId)
89 {
90 MEDIA_INFO_LOG("HCameraDeviceManager::RemoveDevice cameraId=%{public}s start", cameraId.c_str());
91 std::lock_guard<std::mutex> lock(mapMutex_);
92 CHECK_ERROR_RETURN(activeCameras_.empty());
93 auto it = std::find_if(activeCameras_.begin(), activeCameras_.end(), [&](const sptr<HCameraDeviceHolder> &x) {
94 const std::string &curCameraId = x->GetDevice()->GetCameraId();
95 return cameraId == curCameraId;
96 });
97 CHECK_ERROR_RETURN_LOG(it == activeCameras_.end(), "HCameraDeviceManager::RemoveDevice error");
98 int32_t pidNumber = (*it)->GetPid();
99 auto itPid = pidToCameras_.find(pidNumber);
100 if (itPid != pidToCameras_.end()) {
101 auto &camerasOfPid = itPid->second;
102 camerasOfPid.erase(std::remove_if(camerasOfPid.begin(), camerasOfPid.end(),
103 [cameraId](const sptr<HCameraDeviceHolder> &holder) {
104 return holder->GetDevice()->GetCameraId() == cameraId;
105 }),
106 camerasOfPid.end());
107 if (camerasOfPid.empty()) {
108 MEDIA_INFO_LOG("HCameraDeviceManager::RemoveDevice %{public}d "
109 "no active client exists. Clear table records", pidNumber);
110 pidToCameras_.erase(pidNumber);
111 }
112 }
113 activeCameras_.erase(it);
114 MEDIA_DEBUG_LOG("HCameraDeviceManager::RemoveDevice end");
115 }
116
GetCameraHolderByPid(pid_t pidRequest)117 std::vector<sptr<HCameraDeviceHolder>> HCameraDeviceManager::GetCameraHolderByPid(pid_t pidRequest)
118 {
119 MEDIA_INFO_LOG("HCameraDeviceManager::GetCameraHolderByPid start");
120 std::lock_guard<std::mutex> lock(mapMutex_);
121 auto it = pidToCameras_.find(pidRequest);
122 if (it == pidToCameras_.end()) {
123 MEDIA_INFO_LOG("HCameraDeviceManager::GetCameraHolderByPid end, pid: %{public}d not found", pidRequest);
124 return {};
125 }
126 MEDIA_INFO_LOG("HCameraDeviceManager::GetCameraHolderByPid end, pid: %{public}d found", pidRequest);
127 return it->second;
128 }
129
GetCamerasByPid(pid_t pidRequest)130 std::vector<sptr<HCameraDevice>> HCameraDeviceManager::GetCamerasByPid(pid_t pidRequest)
131 {
132 MEDIA_INFO_LOG("HCameraDeviceManager::GetCameraByPid start");
133 std::lock_guard<std::mutex> lock(mapMutex_);
134 auto it = pidToCameras_.find(pidRequest);
135 if (it == pidToCameras_.end()) {
136 MEDIA_INFO_LOG("HCameraDeviceManager::GetCamerasByPid end, pid: %{public}d not found", pidRequest);
137 return {};
138 }
139 std::vector<sptr<HCameraDevice>> cameras = {};
140 if (!it->second.empty()) {
141 for (auto cameraHolder : it->second) {
142 cameras.push_back(cameraHolder->GetDevice());
143 }
144 }
145 MEDIA_INFO_LOG("HCameraDeviceManager::GetCameraByPid end");
146 return cameras;
147 }
148
GetActiveClient()149 std::vector<pid_t> HCameraDeviceManager::GetActiveClient()
150 {
151 MEDIA_INFO_LOG("HCameraDeviceManager::GetActiveClient start");
152 std::lock_guard<std::mutex> lock(mapMutex_);
153 std::vector<pid_t> activeClientPids;
154 if (!pidToCameras_.empty()) {
155 for (auto pair : pidToCameras_) {
156 activeClientPids.emplace_back(pair.first);
157 }
158 }
159 MEDIA_INFO_LOG("HCameraDeviceManager::GetActiveClient end");
160 return activeClientPids;
161 }
162
GetActiveCameraHolders()163 std::vector<sptr<HCameraDeviceHolder>> HCameraDeviceManager::GetActiveCameraHolders()
164 {
165 std::lock_guard<std::mutex> lock(mapMutex_);
166 return activeCameras_;
167 }
168
SetStateOfACamera(std::string cameraId,int32_t state)169 void HCameraDeviceManager::SetStateOfACamera(std::string cameraId, int32_t state)
170 {
171 MEDIA_INFO_LOG("HCameraDeviceManager::SetStateOfACamera start %{public}s, state: %{public}d",
172 cameraId.c_str(), state);\
173 if (state == 0) {
174 stateOfRgmCamera_.EnsureInsert(cameraId, state);
175 } else {
176 stateOfRgmCamera_.Clear();
177 }
178 MEDIA_INFO_LOG("HCameraDeviceManager::SetStateOfACamera end");
179 }
180
GetCameraStateOfASide()181 SafeMap<std::string, int32_t> &HCameraDeviceManager::GetCameraStateOfASide()
182 {
183 return stateOfRgmCamera_;
184 }
185
SetPeerCallback(sptr<ICameraBroker> & callback)186 void HCameraDeviceManager::SetPeerCallback(sptr<ICameraBroker>& callback)
187 {
188 CHECK_ERROR_RETURN_LOG(callback == nullptr, "HCameraDeviceManager::SetPeerCallback failed to set peer callback");
189 std::lock_guard<std::mutex> lock(peerCbMutex_);
190 peerCallback_ = callback;
191 }
192
UnsetPeerCallback()193 void HCameraDeviceManager::UnsetPeerCallback()
194 {
195 std::lock_guard<std::mutex> lock(peerCbMutex_);
196 peerCallback_ = nullptr;
197 }
198
GetConflictDevices(std::vector<sptr<HCameraDevice>> & cameraNeedEvict,sptr<HCameraDevice> cameraRequestOpen,int32_t concurrentTypeOfRequest)199 bool HCameraDeviceManager::GetConflictDevices(std::vector<sptr<HCameraDevice>>& cameraNeedEvict,
200 sptr<HCameraDevice> cameraRequestOpen, int32_t concurrentTypeOfRequest)
201 {
202 std::vector<pid_t> pidOfActiveClients = GetActiveClient();
203 pid_t pidOfOpenRequest = IPCSkeleton::GetCallingPid();
204 pid_t uidOfOpenRequest = IPCSkeleton::GetCallingUid();
205 uint32_t accessTokenIdOfRequestProc = IPCSkeleton::GetCallingTokenID();
206 for (auto pidItem : pidOfActiveClients) {
207 MEDIA_INFO_LOG("GetConflictDevices get active: %{public}d, openRequestPid:%{public}d"
208 "openRequestUid:%{public}d",
209 pidItem, pidOfOpenRequest, uidOfOpenRequest);
210 }
211 // Protecting for mysterious call
212 if (stateOfRgmCamera_.Size() != 0) {
213 CHECK_ERROR_RETURN_RET_LOG(pidOfActiveClients.size() != 0, false,
214 "HCameraDeviceManager::GetConflictDevices Exceptional error occurred before");
215 return IsAllowOpen(pidOfOpenRequest);
216 } else {
217 MEDIA_INFO_LOG("HCameraDeviceManager::GetConflictDevices no rgm camera active");
218 }
219 CHECK_ERROR_RETURN_RET(pidOfActiveClients.size() == 0, true);
220 // Protecting for mysterious call end.
221
222 sptr<HCameraDeviceHolder> requestHolder =
223 GenerateCameraHolder(cameraRequestOpen, pidOfOpenRequest, uidOfOpenRequest, accessTokenIdOfRequestProc);
224
225 // Update each cameraHolder.
226 for (auto pidOfEachClient : pidOfActiveClients) {
227 std::vector<sptr<HCameraDeviceHolder>> activeCameraHolders = GetCameraHolderByPid(pidOfEachClient);
228 if (activeCameraHolders.empty()) {
229 MEDIA_WARNING_LOG("HCameraDeviceManager::GetConflictDevices the current PID has an unknown behavior.");
230 continue;
231 }
232 for (auto holder : activeCameraHolders) {
233 // Device startup requests from different processes.
234 int32_t activeState = CameraAppManagerClient::GetInstance()->GetProcessState(pidOfEachClient);
235 GenerateEachProcessCameraState(activeState, holder->GetAccessTokenId());
236 pid_t focusWindowPid = -1;
237 CameraWindowManagerClient::GetInstance()->GetFocusWindowInfo(focusWindowPid);
238 int32_t focusStateOfActiveProcess = focusWindowPid == pidOfEachClient ? FOCUSED_STATE_OF_PROCESS :
239 UNFOCUSED_STATE_OF_PROCESS;
240 holder->SetState(activeState);
241 holder->SetFocusState(focusStateOfActiveProcess);
242
243 PrintClientInfo(holder, requestHolder);
244 }
245 }
246 concurrentSelector_->SetRequestCameraId(requestHolder);
247 // Active clients that have been sorted by priority. The same priority complies with the LRU rule.
248 holderSortedByProprity_ = SortDeviceByPriority();
249 for (auto it = holderSortedByProprity_.rbegin(); it != holderSortedByProprity_.rend(); ++it) {
250 if (concurrentSelector_->SaveConcurrentCameras(holderSortedByProprity_, *it)) {
251 MEDIA_DEBUG_LOG("HCameraDeviceManager::GetConflictDevices id: %{public}s can open concurrently",
252 (*it)->GetDevice()->GetCameraId().c_str());
253 continue;
254 } else {
255 MEDIA_DEBUG_LOG("HCameraDeviceManager::GetConflictDevices id: %{public}s can not open concurrently",
256 (*it)->GetDevice()->GetCameraId().c_str());
257 cameraNeedEvict.emplace_back((*it)->GetDevice());
258 }
259 }
260
261 // Return Can the cameras that must be left be concurrent.
262 MEDIA_DEBUG_LOG("HCameraDeviceManager::GetConflictDevices reservedCameras size: %{public}zu",
263 concurrentSelector_->GetCamerasRetainable().size());
264 return concurrentSelector_->CanOpenCameraconcurrently(concurrentSelector_->GetCamerasRetainable(),
265 concurrentSelector_->GetConcurrentCameraTable());
266 }
267
HandleCameraEvictions(std::vector<sptr<HCameraDeviceHolder>> & evictedClients,sptr<HCameraDeviceHolder> & cameraRequestOpen)268 bool HCameraDeviceManager::HandleCameraEvictions(std::vector<sptr<HCameraDeviceHolder>> &evictedClients,
269 sptr<HCameraDeviceHolder> &cameraRequestOpen)
270 {
271 std::vector<pid_t> pidOfActiveClients = GetActiveClient();
272 pid_t pidOfOpenRequest = IPCSkeleton::GetCallingPid();
273 sptr<CameraAppManagerClient> amsClientInstance = CameraAppManagerClient::GetInstance();
274 const std::string &cameraId = cameraRequestOpen->GetDevice()->GetCameraId();
275 int32_t requestState = amsClientInstance->GetProcessState(pidOfOpenRequest);
276 for (auto eachClientPid : pidOfActiveClients) {
277 int32_t activeState = amsClientInstance->GetProcessState(eachClientPid);
278 MEDIA_INFO_LOG("Request Open camera ID %{public}s active pid: %{public}d, state: %{public}d,"
279 "request pid: %{public}d, state: %{public}d", cameraId.c_str(), eachClientPid,
280 activeState, pidOfOpenRequest, requestState);
281 }
282
283 pid_t focusWindowPid = -1;
284 CameraWindowManagerClient::GetInstance()->GetFocusWindowInfo(focusWindowPid);
285
286 int32_t focusStateOfRequestProcess = focusWindowPid ==
287 pidOfOpenRequest ? FOCUSED_STATE_OF_PROCESS : UNFOCUSED_STATE_OF_PROCESS;
288 GenerateEachProcessCameraState(requestState, cameraRequestOpen->GetAccessTokenId());
289 cameraRequestOpen->SetState(requestState);
290 cameraRequestOpen->SetFocusState(focusStateOfRequestProcess);
291 MEDIA_INFO_LOG("focusStateOfRequestProcess = %{public}d", focusStateOfRequestProcess);
292 for (const auto &x : activeCameras_) {
293 pid_t curPid = x->GetPid();
294 int32_t curState = amsClientInstance->GetProcessState(curPid);
295 int32_t curFocusState = focusWindowPid == curPid ? FOCUSED_STATE_OF_PROCESS : UNFOCUSED_STATE_OF_PROCESS;
296 x->SetState(curState);
297 x->SetFocusState(curFocusState);
298 }
299
300 // Find Camera Device that would be evicted
301 std::vector<sptr<HCameraDeviceHolder>> evicted = WouldEvict(cameraRequestOpen);
302
303 // If the incoming client was 'evicted,' higher priority clients have the camera in the
304 // background, so we cannot do evictions
305 if (std::find(evicted.begin(), evicted.end(), cameraRequestOpen) != evicted.end()) {
306 MEDIA_INFO_LOG("PID %{public}d) rejected with higher priority", pidOfOpenRequest);
307 return false;
308 }
309 for (auto &x : evicted) {
310 if (x == nullptr) {
311 MEDIA_ERR_LOG("Invalid state: Null client in active client list.");
312 continue;
313 }
314 MEDIA_INFO_LOG("evicting conflicting client for camera ID %s",
315 x->GetDevice()->GetCameraId().c_str());
316 evictedClients.push_back(x);
317 }
318 MEDIA_INFO_LOG("Camera: %{public}s could be opened", cameraId.c_str());
319 return true;
320 }
321
WouldEvict(sptr<HCameraDeviceHolder> & cameraRequestOpen)322 std::vector<sptr<HCameraDeviceHolder>> HCameraDeviceManager::WouldEvict(sptr<HCameraDeviceHolder> &cameraRequestOpen)
323 {
324 std::vector<sptr<HCameraDeviceHolder>> evictList;
325 // Disallow null clients, return input
326 if (cameraRequestOpen == nullptr) {
327 evictList.push_back(cameraRequestOpen);
328 return evictList;
329 }
330 const std::string &cameraId = cameraRequestOpen->GetDevice()->GetCameraId();
331 sptr<CameraProcessPriority> requestPriority = cameraRequestOpen->GetPriority();
332 int32_t owner = cameraRequestOpen->GetPid();
333 int32_t totalCost = GetCurrentCost() + cameraRequestOpen->GetCost();
334
335 // Determine the MRU of the owners tied for having the highest priority
336 int32_t highestPriorityOwner = owner;
337 sptr<CameraProcessPriority> highestPriority = requestPriority;
338 for (const auto &x : activeCameras_) {
339 sptr<CameraProcessPriority> curPriority = x->GetPriority();
340 if (*curPriority > *highestPriority) {
341 highestPriority = curPriority;
342 highestPriorityOwner = x->GetPid();
343 }
344 }
345 // Switch back owner if the incoming client has the highest priority, as it is MRU
346 highestPriorityOwner = (*highestPriority == *requestPriority) ? owner : highestPriorityOwner;
347
348 // Build eviction list of clients to remove
349 for (const auto &x : activeCameras_) {
350 const std::string &curCameraId = x->GetDevice()->GetCameraId();
351 int32_t curCost = x->GetCost();
352 sptr<CameraProcessPriority> curPriority = x->GetPriority();
353 int32_t curOwner = x->GetPid();
354 MEDIA_INFO_LOG("CameraId:[%{public}s, %{public}s], totalCost: %{public}d", curCameraId.c_str(),
355 cameraId.c_str(), totalCost);
356 MEDIA_INFO_LOG("ControlConflict:[%{public}d, %{public}d]", x->IsConflicting(cameraId),
357 cameraRequestOpen->IsConflicting(curCameraId));
358 bool deviceConflict = (curCameraId == cameraId);
359 bool controlConflict = x->IsConflicting(cameraId) || cameraRequestOpen->IsConflicting(curCameraId);
360 if ((deviceConflict || controlConflict) && (*curPriority <= *requestPriority)) {
361 evictList.clear();
362 evictList.push_back(x);
363 MEDIA_INFO_LOG("deviceConflict: requestProcess has higher priority, Evict current CameraClient");
364 return evictList;
365 } else if ((deviceConflict || controlConflict) && (*curPriority > *requestPriority)) {
366 evictList.clear();
367 evictList.push_back(cameraRequestOpen);
368 MEDIA_INFO_LOG(
369 "DeviceConflict or controlConflict, current client has higher priority, Evict request client");
370 return evictList;
371 }
372 if ((totalCost > DEFAULT_MAX_COST && curCost > 0) && (*curPriority <= *requestPriority) &&
373 !(highestPriorityOwner == owner && owner == curOwner)) {
374 MEDIA_INFO_LOG("Evict current camera client");
375 evictList.push_back(x);
376 totalCost -= curCost;
377 }
378 }
379 MEDIA_INFO_LOG("non-conflicting: totalCost:%{public}d", totalCost);
380 // If the total cost is too high, return the input unless the input has the highest priority
381 if (totalCost > DEFAULT_MAX_COST) {
382 MEDIA_INFO_LOG("totalCost > DEFAULT_MAX_COST, Evict ReqCamera");
383 evictList.clear();
384 evictList.push_back(cameraRequestOpen);
385 }
386 return evictList;
387 }
388
GetCurrentCost() const389 int32_t HCameraDeviceManager::GetCurrentCost() const
390 {
391 int32_t totalCost = 0;
392 for (const auto &x : activeCameras_) {
393 totalCost += x->GetCost();
394 }
395 MEDIA_INFO_LOG("HCameraDeviceManager::GetCurrentCost:%{public}d", totalCost);
396 return totalCost;
397 }
398
GetACameraId()399 std::string HCameraDeviceManager::GetACameraId()
400 {
401 MEDIA_INFO_LOG("HCameraDeviceManager::GetActiveClient start");
402 std::string cameraId;
403 if (!stateOfRgmCamera_.IsEmpty()) {
404 stateOfRgmCamera_.Iterate([&](const std::string pid, int32_t state) {
405 cameraId = pid;
406 });
407 }
408 MEDIA_INFO_LOG("HCameraDeviceManager::GetActiveClient end");
409 return cameraId;
410 }
411
IsAllowOpen(pid_t pidOfOpenRequest)412 bool HCameraDeviceManager::IsAllowOpen(pid_t pidOfOpenRequest)
413 {
414 MEDIA_INFO_LOG("HCameraDeviceManager::isAllowOpen has a client open in A proxy");
415 CHECK_ERROR_RETURN_RET_LOG(pidOfOpenRequest == -1, false,
416 "HCameraDeviceManager::GetConflictDevices wrong pid of the process whitch is goning to turn on");
417 std::string cameraId = GetACameraId();
418 CHECK_ERROR_RETURN_RET_LOG(peerCallback_ == nullptr, false,
419 "HCameraDeviceManager::isAllowOpen falied to close peer device");
420 peerCallback_->NotifyCloseCamera(cameraId);
421 MEDIA_ERR_LOG("HCameraDeviceManager::isAllowOpen success to close peer device");
422 return true;
423 }
424
GenerateProcessCameraState(int32_t & activeState,int32_t & requestState,uint32_t activeAccessTokenId,uint32_t requestAccessTokenId)425 void HCameraDeviceManager::GenerateProcessCameraState(int32_t& activeState, int32_t& requestState,
426 uint32_t activeAccessTokenId, uint32_t requestAccessTokenId)
427 {
428 GenerateEachProcessCameraState(activeState, activeAccessTokenId);
429 GenerateEachProcessCameraState(requestState, requestAccessTokenId);
430 }
431
GenerateEachProcessCameraState(int32_t & processState,uint32_t processTokenId)432 void HCameraDeviceManager::GenerateEachProcessCameraState(int32_t& processState, uint32_t processTokenId)
433 {
434 sptr<IWindowManagerAgent> winMgrAgent = CameraWindowManagerClient::GetInstance()->GetWindowManagerAgent();
435 uint32_t accessTokenIdInPip = 0;
436 if (winMgrAgent != nullptr) {
437 accessTokenIdInPip =
438 static_cast<CameraWindowManagerAgent*>(winMgrAgent.GetRefPtr())->GetAccessTokenId();
439 MEDIA_DEBUG_LOG("update current pip window accessTokenId");
440 }
441
442 auto updateState = [accessTokenIdInPip](int32_t& state, uint32_t accessTokenId) {
443 auto it = APP_MGR_STATE_TO_CAMERA_STATE.find(state);
444 state = (it != APP_MGR_STATE_TO_CAMERA_STATE.end()) ? it->second : UNKNOW_STATE_OF_PROCESS;
445 if (accessTokenId == accessTokenIdInPip) {
446 state = PIP_STATE_OF_PROCESS;
447 }
448 };
449 updateState(processState, processTokenId);
450 }
451
PrintClientInfo(sptr<HCameraDeviceHolder> activeCameraHolder,sptr<HCameraDeviceHolder> requestCameraHolder)452 void HCameraDeviceManager::PrintClientInfo(sptr<HCameraDeviceHolder> activeCameraHolder,
453 sptr<HCameraDeviceHolder> requestCameraHolder)
454 {
455 MEDIA_INFO_LOG("activeInfo: uid: %{public}d, pid:%{public}d, processState:%{public}d,"
456 "focusState:%{public}d, cameraId:%{public}s"
457 "requestInfo: uid: %{public}d, pid:%{public}d, processState:%{public}d,"
458 "focusState:%{public}d, cameraId:%{public}s",
459 activeCameraHolder->GetPriority()->GetUid(), activeCameraHolder->GetPid(),
460 activeCameraHolder->GetPriority()->GetState(), activeCameraHolder->GetPriority()->GetFocusState(),
461 activeCameraHolder->GetDevice()->GetCameraId().c_str(), requestCameraHolder->GetPriority()->GetUid(),
462 requestCameraHolder->GetPid(), requestCameraHolder->GetPriority()->GetState(),
463 requestCameraHolder->GetPriority()->GetFocusState(),
464 requestCameraHolder->GetDevice()->GetCameraId().c_str());
465 }
466
IsMultiCameraActive(int32_t pid)467 bool HCameraDeviceManager::IsMultiCameraActive(int32_t pid)
468 {
469 std::lock_guard<std::mutex> lock(mapMutex_);
470 uint8_t count = 0;
471 for (const auto &x : activeCameras_) {
472 if (pid == x->GetPid()) {
473 count++;
474 }
475 }
476
477 MEDIA_INFO_LOG("pid(%{public}d) has activated %{public}d camera.", pid, count);
478 return count > 0;
479 }
480
481
GenerateCameraHolder(sptr<HCameraDevice> device,pid_t pid,int32_t uid,uint32_t accessTokenId)482 sptr<HCameraDeviceHolder> HCameraDeviceManager::GenerateCameraHolder(sptr<HCameraDevice> device, pid_t pid, int32_t uid,
483 uint32_t accessTokenId)
484 {
485 pid_t focusWindowPid = -1;
486 CameraWindowManagerClient::GetInstance()->GetFocusWindowInfo(focusWindowPid);
487 int32_t requestState = CameraAppManagerClient::GetInstance()->GetProcessState(pid);
488 GenerateEachProcessCameraState(requestState, accessTokenId);
489 if (focusWindowPid == -1) {
490 MEDIA_INFO_LOG("GetFocusWindowInfo faild");
491 }
492 int32_t focusStateOfRequestProcess = focusWindowPid == pid ? FOCUSED_STATE_OF_PROCESS : UNFOCUSED_STATE_OF_PROCESS;
493
494 int32_t cost = 0;
495 std::set<std::string> conflicting;
496 sptr<HCameraDeviceHolder> requestCameraHolder = new HCameraDeviceHolder(
497 pid, uid, requestState, focusStateOfRequestProcess, device, accessTokenId, cost, conflicting);
498 return requestCameraHolder;
499 }
500
IsProcessHasConcurrentDevice(pid_t pid)501 bool HCameraDeviceManager::IsProcessHasConcurrentDevice(pid_t pid)
502 {
503 std::lock_guard<std::mutex> lock(mapMutex_);
504 auto mapIt = pidToCameras_.find(pid);
505 if (mapIt == pidToCameras_.end()) {
506 return false;
507 }
508 for (auto& holder : mapIt->second) {
509 auto device = holder->GetDevice();
510 if (device == nullptr) {
511 continue;
512 }
513 if (device->IsDeviceOpenedByConcurrent()) {
514 return true;
515 }
516 }
517 return false;
518 }
519
SetRequestCameraId(sptr<HCameraDeviceHolder> requestCameraHolder)520 void CameraConcurrentSelector::SetRequestCameraId(sptr<HCameraDeviceHolder> requestCameraHolder)
521 {
522 requestCameraHolder_ = requestCameraHolder;
523 concurrentCameraTable_ = requestCameraHolder->GetDevice()->GetConcurrentDevicesTable();
524 listOfCameraRetainable_ = {};
525 }
526
SortDeviceByPriority()527 std::vector<sptr<HCameraDeviceHolder>> HCameraDeviceManager::SortDeviceByPriority()
528 {
529 std::vector<sptr<HCameraDeviceHolder>> sortedList = activeCameras_;
530 std::sort(sortedList.begin(), sortedList.end(),
531 [](const sptr<HCameraDeviceHolder> &a, const sptr<HCameraDeviceHolder> &b) {
532 return a->GetPriority() < b->GetPriority();
533 });
534 return sortedList;
535 }
536
CanOpenCameraconcurrently(std::vector<sptr<HCameraDeviceHolder>> reservedCameras,std::vector<std::vector<std::int32_t>> concurrentCameraTable)537 bool CameraConcurrentSelector::CanOpenCameraconcurrently(std::vector<sptr<HCameraDeviceHolder>> reservedCameras,
538 std::vector<std::vector<std::int32_t>> concurrentCameraTable)
539 {
540 for (const auto& row : concurrentCameraTable) {
541 std::stringstream ss;
542 for (size_t i = 0; i < row.size(); ++i) {
543 ss << row[i];
544 if (i < row.size() - 1) {
545 ss << ", "; // 使用逗号分隔元素
546 }
547 }
548 MEDIA_DEBUG_LOG("CameraConcurrentSelector::canOpenCameraconcurrently "
549 "concurrentCameraTable_ current group: %{public}s", ss.str().c_str());
550 }
551 if (reservedCameras.size() == 0) {
552 return true;
553 }
554 std::vector<int32_t> cameraIds;
555 for (const auto& camera : reservedCameras) {
556 cameraIds.push_back(GetCameraIdNumber(camera->GetDevice()->GetCameraId()));
557 }
558 for (const auto& group : concurrentCameraTable) {
559 bool allCamerasInGroup = true;
560 for (int32_t cameraId : cameraIds) {
561 if (std::find(group.begin(), group.end(), cameraId) == group.end()) {
562 allCamerasInGroup = false;
563 break;
564 }
565 }
566 if (allCamerasInGroup) return true;
567 }
568 return false;
569 }
570
SaveConcurrentCameras(std::vector<sptr<HCameraDeviceHolder>> holdersSortedByProprity,sptr<HCameraDeviceHolder> holderWaitToConfirm)571 bool CameraConcurrentSelector::SaveConcurrentCameras(std::vector<sptr<HCameraDeviceHolder>> holdersSortedByProprity,
572 sptr<HCameraDeviceHolder> holderWaitToConfirm)
573 {
574 // Same pid
575 if (holderWaitToConfirm->GetPid() == requestCameraHolder_->GetPid()) {
576 if (!holderWaitToConfirm->GetDevice()->GetCameraId().compare(
577 requestCameraHolder_->GetDevice()->GetCameraId())) {
578 // The current device can never be concurrent with itself, the latter one always turns on
579 return false;
580 } else {
581 listOfCameraRetainable_.emplace_back(holderWaitToConfirm);
582 return true;
583 }
584 }
585
586 for (const auto& row : concurrentCameraTable_) {
587 std::stringstream ss;
588 for (size_t i = 0; i < row.size(); ++i) {
589 ss << row[i];
590 if (i < row.size() - 1) {
591 ss << ", "; // 使用逗号分隔元素
592 }
593 }
594 MEDIA_DEBUG_LOG("CameraConcurrentSelector::SaveConcurrentCameras"
595 "concurrentCameraTable_ current group: %{public}s", ss.str().c_str());
596 }
597
598 // This device cannot be opened concurrently. Pure priority is preferred.
599 if (concurrentCameraTable_.size() == 0) {
600 if ((*holderWaitToConfirm->GetPriority()) <= (*requestCameraHolder_->GetPriority())) {
601 return false;
602 } else {
603 // A higher priority, which needs to be reserved
604 listOfCameraRetainable_.emplace_back(holderWaitToConfirm);
605 return true;
606 }
607 }
608
609 // Devices can be opened concurrently.
610 bool canConcurrentOpen = ConcurrentWithRetainedDevicesOrNot(holderWaitToConfirm);
611 if (canConcurrentOpen) {
612 listOfCameraRetainable_.emplace_back(holderWaitToConfirm);
613 return true;
614 } else {
615 if ((*holderWaitToConfirm->GetPriority()) <= (*requestCameraHolder_->GetPriority())) {
616 return false;
617 } else {
618 // A higher priority, which needs to be reserved
619 listOfCameraRetainable_.emplace_back(holderWaitToConfirm);
620 return true;
621 }
622 }
623 MEDIA_WARNING_LOG("CameraConcurrentSelector::ConfirmAndInsertRetainableCamera Unknown concurrency type");
624 return false;
625 }
626
GetCameraIdNumber(std::string cameraId)627 int32_t CameraConcurrentSelector::GetCameraIdNumber(std::string cameraId)
628 {
629 const int32_t ILLEGAL_ID = -1;
630 std::regex regex("\\d+$");
631 std::smatch match;
632 if (std::regex_search(cameraId, match, regex)) {
633 std::string numberStr = match[0];
634 std::stringstream ss(numberStr);
635 int number;
636 ss >> number;
637 return number;
638 } else {
639 return ILLEGAL_ID;
640 }
641 }
642
ConcurrentWithRetainedDevicesOrNot(sptr<HCameraDeviceHolder> cameraIdNeedConfirm)643 bool CameraConcurrentSelector::ConcurrentWithRetainedDevicesOrNot(sptr<HCameraDeviceHolder> cameraIdNeedConfirm)
644 {
645 std::vector<int32_t> tempListToCheck;
646 for (auto each : listOfCameraRetainable_) {
647 tempListToCheck.emplace_back(GetCameraIdNumber(each->GetDevice()->GetCameraId()));
648 }
649 tempListToCheck.emplace_back(GetCameraIdNumber(cameraIdNeedConfirm->GetDevice()->GetCameraId()));
650 bool canOpenConcurrent = std::any_of(
651 concurrentCameraTable_.begin(), concurrentCameraTable_.end(), [&](const std::vector<int32_t> &innerVec) {
652 return std::all_of(tempListToCheck.begin(), tempListToCheck.end(), [&](int32_t element) {
653 return std::find(innerVec.begin(), innerVec.end(), element) != innerVec.end();
654 });
655 });
656 int32_t targetConcurrencyType = cameraIdNeedConfirm->GetDevice()->GetTargetConcurrencyType();
657 MEDIA_DEBUG_LOG("CameraConcurrentSelector::ConcurrentWithRetainedDevicesOrNot canOpenConcurrent:%{public}d,"
658 "targetType:%{public}d, confirmType:%{public}d, requestType: %{public}d",
659 canOpenConcurrent, targetConcurrencyType, cameraIdNeedConfirm->GetDevice()->GetTargetConcurrencyType(),
660 requestCameraHolder_->GetDevice()->GetTargetConcurrencyType());
661 return canOpenConcurrent &&
662 (targetConcurrencyType == cameraIdNeedConfirm->GetDevice()->GetTargetConcurrencyType() &&
663 targetConcurrencyType == requestCameraHolder_->GetDevice()->GetTargetConcurrencyType());
664 }
665 } // namespace CameraStandard
666 } // namespace OHOS