• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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