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