1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <condition_variable>
17 #include <cstdint>
18 #include <mutex>
19 #include "camera_app_manager_utils.h"
20 #include "camera_privacy.h"
21 #include "camera_log.h"
22 #include "hcamera_device.h"
23 #include "hcapture_session.h"
24 #include "ipc_skeleton.h"
25 #include "types.h"
26 
27 namespace OHOS {
28 namespace CameraStandard {
29 using OHOS::Security::AccessToken::PrivacyKit;
30 using OHOS::Security::AccessToken::AccessTokenKit;
31 
CastToSession(sptr<IStreamOperatorCallback> streamOpCb)32 sptr<HCaptureSession> CastToSession(sptr<IStreamOperatorCallback> streamOpCb)
33 {
34     if (streamOpCb == nullptr) {
35         return nullptr;
36     }
37     return static_cast<HCaptureSession*>(streamOpCb.GetRefPtr());
38 }
39 
PermStateChangeCallback(Security::AccessToken::PermStateChangeInfo & result)40 void PermissionStatusChangeCb::PermStateChangeCallback(Security::AccessToken::PermStateChangeInfo& result)
41 {
42     MEDIA_INFO_LOG("enter PermissionStatusChangeNotify permStateChangeType:%{public}d"
43         " permissionName:%{public}s", result.permStateChangeType, result.permissionName.c_str());
44     auto device = cameraDevice_.promote();
45     if ((result.permStateChangeType == 0) && (device != nullptr)) {
46         auto session = CastToSession(device->GetStreamOperatorCallback());
47         if (session) {
48             session->ReleaseStreams();
49             session->StopMovingPhoto();
50         }
51         device->CloseDevice();
52         device->OnError(DEVICE_PREEMPT, 0);
53     }
54 }
55 
StateChangeNotify(Security::AccessToken::AccessTokenID tokenId,bool isShowing)56 void CameraUseStateChangeCb::StateChangeNotify(Security::AccessToken::AccessTokenID tokenId, bool isShowing)
57 {
58     MEDIA_INFO_LOG("enter CameraUseStateChangeNotify");
59     auto device = cameraDevice_.promote();
60     CHECK_ERROR_RETURN_LOG((isShowing == true) || (device == nullptr), "abnormal callback from privacy.");
61     auto cameraPrivacy = device->GetCameraPrivacy();
62     CHECK_ERROR_RETURN_LOG(cameraPrivacy == nullptr, "cameraPrivacy is nullptr.");
63     if (cameraPrivacy->WaitFor() == std::cv_status::timeout) {
64         MEDIA_INFO_LOG("CameraUseStateChangeCb::StateChangeNotify wait timeout");
65         device = cameraDevice_.promote();
66         bool isForeground = CameraAppManagerUtils::IsForegroundApplication(tokenId);
67         if ((isShowing == false) && (device != nullptr) && !isForeground) {
68             auto session = CastToSession(device->GetStreamOperatorCallback());
69             if (session) {
70                 session->ReleaseStreams();
71                 session->StopMovingPhoto();
72             }
73             device->CloseDevice();
74         }
75     }
76 }
77 
~CameraPrivacy()78 CameraPrivacy::~CameraPrivacy()
79 {
80     cameraUseCallbackPtr_ = nullptr;
81     permissionCallbackPtr_ = nullptr;
82 }
83 
IsAllowUsingCamera()84 bool CameraPrivacy::IsAllowUsingCamera()
85 {
86     return PrivacyKit::IsAllowedUsingPermission(callerToken_, OHOS_PERMISSION_CAMERA);
87 }
88 
RegisterPermissionCallback()89 bool CameraPrivacy::RegisterPermissionCallback()
90 {
91     Security::AccessToken::PermStateChangeScope scopeInfo;
92     scopeInfo.permList = {OHOS_PERMISSION_CAMERA};
93     scopeInfo.tokenIDs = {callerToken_};
94     int32_t res;
95     {
96         std::lock_guard<std::mutex> lock(permissionCbMutex_);
97         permissionCallbackPtr_ = std::make_shared<PermissionStatusChangeCb>(cameraDevice_, scopeInfo);
98         res = AccessTokenKit::RegisterPermStateChangeCallback(permissionCallbackPtr_);
99     }
100     MEDIA_INFO_LOG("CameraPrivacy::RegisterPermissionCallback res:%{public}d", res);
101     CHECK_ERROR_PRINT_LOG(res != CAMERA_OK, "RegisterPermissionCallback failed.");
102     return res == CAMERA_OK;
103 }
104 
UnregisterPermissionCallback()105 void CameraPrivacy::UnregisterPermissionCallback()
106 {
107     std::lock_guard<std::mutex> lock(permissionCbMutex_);
108     CHECK_ERROR_RETURN_LOG(permissionCallbackPtr_ == nullptr, "permissionCallbackPtr_ is null.");
109     MEDIA_DEBUG_LOG("UnregisterPermissionCallback unregister");
110     int32_t res = AccessTokenKit::UnRegisterPermStateChangeCallback(permissionCallbackPtr_);
111     MEDIA_INFO_LOG("CameraPrivacy::UnregisterPermissionCallback res:%{public}d", res);
112     CHECK_ERROR_PRINT_LOG(res != CAMERA_OK, "UnregisterPermissionCallback failed.");
113     permissionCallbackPtr_ = nullptr;
114 }
115 
AddCameraPermissionUsedRecord()116 bool CameraPrivacy::AddCameraPermissionUsedRecord()
117 {
118     int32_t successCout = 1;
119     int32_t failCount = 0;
120     int32_t res = PrivacyKit::AddPermissionUsedRecord(callerToken_, OHOS_PERMISSION_CAMERA, successCout, failCount);
121     MEDIA_INFO_LOG("CameraPrivacy::AddCameraPermissionUsedRecord res:%{public}d", res);
122     CHECK_ERROR_PRINT_LOG(res != CAMERA_OK, "AddCameraPermissionUsedRecord failed.");
123     return res == CAMERA_OK;
124 }
125 
StartUsingPermissionCallback()126 bool CameraPrivacy::StartUsingPermissionCallback()
127 {
128     int32_t res;
129     {
130         std::lock_guard<std::mutex> lock(cameraUseCbMutex_);
131         CHECK_ERROR_RETURN_RET_LOG(cameraUseCallbackPtr_, true, "has StartUsingPermissionCallback!");
132         cameraUseCallbackPtr_ = std::make_shared<CameraUseStateChangeCb>(cameraDevice_);
133         res = PrivacyKit::StartUsingPermission(callerToken_, OHOS_PERMISSION_CAMERA, cameraUseCallbackPtr_, pid_);
134     }
135     MEDIA_INFO_LOG("CameraPrivacy::StartUsingPermissionCallback res:%{public}d", res);
136     bool ret = (res == CAMERA_OK || res == Security::AccessToken::ERR_EDM_POLICY_CHECK_FAILED ||
137         res == Security::AccessToken::ERR_PRIVACY_POLICY_CHECK_FAILED);
138     CHECK_ERROR_PRINT_LOG(!ret, "StartUsingPermissionCallback failed.");
139     return ret;
140 }
141 
StopUsingPermissionCallback()142 void CameraPrivacy::StopUsingPermissionCallback()
143 {
144     {
145         std::lock_guard<std::mutex> lock(cameraUseCbMutex_);
146         int32_t res = PrivacyKit::StopUsingPermission(callerToken_, OHOS_PERMISSION_CAMERA, pid_);
147         MEDIA_INFO_LOG("CameraPrivacy::StopUsingPermissionCallback res:%{public}d", res);
148         CHECK_ERROR_PRINT_LOG(res != CAMERA_OK, "StopUsingPermissionCallback failed.");
149         cameraUseCallbackPtr_ = nullptr;
150     }
151     Notify();
152 }
153 } // namespace CameraStandard
154 } // namespace OHOS