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