1/*
2 * Copyright (C) 2021 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#include "video_control_manager.h"
16
17#include <algorithm>
18
19#include "call_ability_report_proxy.h"
20#include "cellular_call_connection.h"
21#include "file_ex.h"
22#include "telephony_errors.h"
23#include "telephony_log_wrapper.h"
24
25#ifdef ABILITY_CAMERA_SUPPORT
26#include "input/camera_manager.h"
27#endif
28
29namespace OHOS {
30namespace Telephony {
31namespace {
32const int16_t CAMERA_ROTATION_0 = 0;
33const int16_t CAMERA_ROTATION_90 = 90;
34const int16_t CAMERA_ROTATION_180 = 180;
35const int16_t CAMERA_ROTATION_270 = 270;
36const int16_t VIDEO_WINDOWS_Z_BOTTOM = 0;
37const int16_t VIDEO_WINDOWS_Z_TOP = 1;
38const float MIN_CAMERA_ZOOM = 0.1;
39const float MAX_CAMERA_ZOOM = 10.0;
40const std::string SUPPORT_PICTURE_EXT = "png";
41} // namespace
42
43VideoControlManager::VideoControlManager() : isOpenCamera_(false) {}
44
45VideoControlManager::~VideoControlManager() {}
46
47int32_t VideoControlManager::ControlCamera(
48    int32_t callId, std::u16string &cameraId, int32_t callingUid, int32_t callingPid)
49{
50    if (cameraId.empty()) {
51        return CloseCamera(callId, cameraId, callingUid, callingPid);
52    } else {
53        return OpenCamera(callId, cameraId, callingUid, callingPid);
54    }
55}
56
57int32_t VideoControlManager::SetPreviewWindow(int32_t callId, std::string &surfaceId, sptr<Surface> surface)
58{
59    int32_t ret = TELEPHONY_ERR_FAIL;
60    ret = CallPolicy::VideoCallPolicy(callId);
61    if (ret != TELEPHONY_SUCCESS) {
62        TELEPHONY_LOGE("check prerequisites failed !");
63        return ret;
64    }
65    sptr<CallBase> callPtr = CallObjectManager::GetOneCallObject(callId);
66    if (callPtr == nullptr) {
67        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
68        return TELEPHONY_ERR_LOCAL_PTR_NULL;
69    }
70    if (callPtr->GetCallType() == CallType::TYPE_IMS) {
71        sptr<IMSCall> netCall = reinterpret_cast<IMSCall *>(callPtr.GetRefPtr());
72        ret = netCall->SetPreviewWindow(surfaceId, surface);
73        if (ret != TELEPHONY_SUCCESS) {
74            TELEPHONY_LOGE("SetPreviewWindow failed!");
75            return ret;
76        }
77    }
78    return TELEPHONY_SUCCESS;
79}
80
81int32_t VideoControlManager::SetDisplayWindow(int32_t callId, std::string &surfaceId, sptr<Surface> surface)
82{
83    int32_t ret = TELEPHONY_ERR_FAIL;
84    ret = CallPolicy::VideoCallPolicy(callId);
85    if (ret != TELEPHONY_SUCCESS) {
86        TELEPHONY_LOGE("check prerequisites failed !");
87        return ret;
88    }
89    sptr<CallBase> callPtr = CallObjectManager::GetOneCallObject(callId);
90    if (callPtr == nullptr) {
91        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
92        return TELEPHONY_ERR_LOCAL_PTR_NULL;
93    }
94    if (callPtr->GetCallType() == CallType::TYPE_IMS) {
95        sptr<IMSCall> netCall = reinterpret_cast<IMSCall *>(callPtr.GetRefPtr());
96        ret = netCall->SetDisplayWindow(surfaceId, surface);
97        if (ret != TELEPHONY_SUCCESS) {
98            TELEPHONY_LOGE("SetDisplayWindow failed!");
99            return ret;
100        }
101    }
102    return TELEPHONY_SUCCESS;
103}
104
105int32_t VideoControlManager::SetCameraZoom(float zoomRatio)
106{
107    // param check
108    if (zoomRatio < MIN_CAMERA_ZOOM || zoomRatio > MAX_CAMERA_ZOOM) {
109        TELEPHONY_LOGE("camera zoom error!!");
110        return CALL_ERR_VIDEO_INVALID_ZOOM;
111    }
112    return DelayedSingleton<CellularCallConnection>::GetInstance()->SetCameraZoom(zoomRatio);
113}
114
115int32_t VideoControlManager::SetPausePicture(int32_t callId, std::u16string &path)
116{
117    int32_t ret = TELEPHONY_ERR_FAIL;
118    ret = CallPolicy::VideoCallPolicy(callId);
119    if (ret != TELEPHONY_SUCCESS) {
120        TELEPHONY_LOGE("check prerequisites failed !");
121        return ret;
122    }
123    std::string tempPath(Str16ToStr8(path));
124    sptr<CallBase> callPtr = CallObjectManager::GetOneCallObject(callId);
125    if (callPtr == nullptr) {
126        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
127        return TELEPHONY_ERR_LOCAL_PTR_NULL;
128    }
129    if (callPtr->GetCallType() == CallType::TYPE_IMS) {
130        sptr<IMSCall> netCall = reinterpret_cast<IMSCall *>(callPtr.GetRefPtr());
131        ret = netCall->SetPausePicture(tempPath);
132        if (ret != TELEPHONY_SUCCESS) {
133            TELEPHONY_LOGE("SetPausePicture failed!");
134            return ret;
135        }
136    }
137    return TELEPHONY_SUCCESS;
138}
139
140int32_t VideoControlManager::SetDeviceDirection(int32_t callId, int32_t rotation)
141{
142    int32_t ret = TELEPHONY_ERR_FAIL;
143    ret = CallPolicy::VideoCallPolicy(callId);
144    if (ret != TELEPHONY_SUCCESS) {
145        TELEPHONY_LOGE("check prerequisites failed !");
146        return ret;
147    }
148    // param check
149    if (rotation == CAMERA_ROTATION_0 || rotation == CAMERA_ROTATION_90 || rotation == CAMERA_ROTATION_180 ||
150        rotation == CAMERA_ROTATION_270) {
151        sptr<CallBase> callPtr = CallObjectManager::GetOneCallObject(callId);
152        if (callPtr == nullptr) {
153            TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
154            return TELEPHONY_ERR_LOCAL_PTR_NULL;
155        }
156        if (callPtr->GetCallType() == CallType::TYPE_IMS) {
157            sptr<IMSCall> netCall = reinterpret_cast<IMSCall *>(callPtr.GetRefPtr());
158            ret = netCall->SetDeviceDirection(rotation);
159            if (ret != TELEPHONY_SUCCESS) {
160                TELEPHONY_LOGE("SetDeviceDirection failed!");
161                return ret;
162            }
163        }
164        return TELEPHONY_SUCCESS;
165    }
166    TELEPHONY_LOGE("error rotation:%{public}d", rotation);
167    return CALL_ERR_VIDEO_INVALID_ROTATION;
168}
169
170int32_t VideoControlManager::UpdateImsCallMode(int32_t callId, ImsCallMode callMode)
171{
172    int32_t ret = TELEPHONY_ERR_FAIL;
173    ret = CallPolicy::VideoCallPolicy(callId);
174    if (ret != TELEPHONY_SUCCESS) {
175        TELEPHONY_LOGE("check prerequisites failed !");
176        return ret;
177    }
178    sptr<CallBase> callPtr = CallObjectManager::GetOneCallObject(callId);
179    if (callPtr == nullptr) {
180        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
181        return TELEPHONY_ERR_LOCAL_PTR_NULL;
182    }
183    if (callPtr->GetCallType() == CallType::TYPE_IMS) {
184        // only netcall type support update call media mode
185        sptr<IMSCall> netCall = reinterpret_cast<IMSCall *>(callPtr.GetRefPtr());
186        TELEPHONY_LOGI("ims call update media request");
187        ret = netCall->UpdateImsCallMode(callMode);
188        if (ret != TELEPHONY_SUCCESS) {
189            TELEPHONY_LOGE("UpdateImsCallMode failed!. %{public}d", ret);
190        }
191    }
192    return ret;
193}
194
195int32_t VideoControlManager::ReportImsCallModeInfo(CallMediaModeInfo &imsCallModeInfo)
196{
197    return DelayedSingleton<CallAbilityReportProxy>::GetInstance()->ReportImsCallModeChange(imsCallModeInfo);
198}
199
200int32_t VideoControlManager::OpenCamera(
201    int32_t callId, std::u16string &cameraId, int32_t callingUid, int32_t callingPid)
202{
203    // cameraId check
204    std::string id(Str16ToStr8(cameraId));
205    int32_t ret = TELEPHONY_ERR_FAIL;
206    ret = CallPolicy::VideoCallPolicy(callId);
207    if (ret != TELEPHONY_SUCCESS) {
208        TELEPHONY_LOGE("check prerequisites failed !");
209        return ret;
210    }
211    sptr<CallBase> callPtr = CallObjectManager::GetOneCallObject(callId);
212    if (callPtr == nullptr || callPtr.GetRefPtr() == nullptr) {
213        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
214        return TELEPHONY_ERR_LOCAL_PTR_NULL;
215    }
216    if (callPtr->GetCallType() == CallType::TYPE_IMS) {
217        sptr<IMSCall> netCall = reinterpret_cast<IMSCall *>(callPtr.GetRefPtr());
218        if (netCall == nullptr) {
219            TELEPHONY_LOGE("the netCall is nullptr, callId:%{public}d", callId);
220            return TELEPHONY_ERR_LOCAL_PTR_NULL;
221        }
222        ret = netCall->ControlCamera(id, callingUid, callingPid);
223        if (ret == TELEPHONY_SUCCESS) {
224            isOpenCamera_ = true;
225        }
226        ret = netCall->RequestCameraCapabilities();
227        if (ret != TELEPHONY_SUCCESS) {
228            TELEPHONY_LOGE("RequestCameraCapabilities failed!");
229            return ret;
230        }
231    }
232    return ret;
233}
234
235int32_t VideoControlManager::CloseCamera(
236    int32_t callId, std::u16string &cameraId, int32_t callingUid, int32_t callingPid)
237{
238    std::string id(Str16ToStr8(cameraId));
239    int32_t ret = TELEPHONY_ERR_FAIL;
240    ret = CallPolicy::VideoCallPolicy(callId);
241    if (ret != TELEPHONY_SUCCESS) {
242        TELEPHONY_LOGE("check prerequisites failed !");
243        return ret;
244    }
245    if (isOpenCamera_) {
246        sptr<CallBase> callPtr = CallObjectManager::GetOneCallObject(callId);
247        if (callPtr == nullptr) {
248            TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
249            return TELEPHONY_ERR_LOCAL_PTR_NULL;
250        }
251        if (callPtr->GetCallType() == CallType::TYPE_IMS) {
252            sptr<IMSCall> netCall = reinterpret_cast<IMSCall *>(callPtr.GetRefPtr());
253            ret = netCall->ControlCamera(id, callingUid, callingPid);
254            if (ret == TELEPHONY_SUCCESS) {
255                isOpenCamera_ = true;
256            }
257        }
258        return ret;
259    }
260    TELEPHONY_LOGE("Camera not turned on");
261    return CALL_ERR_CAMERA_NOT_TURNED_ON;
262}
263
264bool VideoControlManager::ContainCameraID(std::string id)
265{
266    bool bRet = false;
267#ifdef ABILITY_CAMERA_SUPPORT
268    using namespace OHOS::CameraStandard;
269    sptr<CameraManager> camManagerObj = CameraManager::GetInstance();
270    std::vector<sptr<CameraStandard::CameraDevice>> cameraObjList = camManagerObj->GetSupportedCameras();
271
272    for (auto &it : cameraObjList) {
273        if (id.compare(it->GetID()) == 0) {
274            bRet = true;
275            TELEPHONY_LOGI("Contain Camera ID:  : %{public}s", id.c_str());
276            break;
277        }
278    }
279#endif
280    return bRet;
281}
282
283int32_t VideoControlManager::CancelCallUpgrade(int32_t callId)
284{
285    int32_t ret = TELEPHONY_ERR_FAIL;
286    ret = CallPolicy::VideoCallPolicy(callId);
287    if (ret != TELEPHONY_SUCCESS) {
288        TELEPHONY_LOGE("check prerequisites failed !");
289        return ret;
290    }
291    sptr<CallBase> callPtr = CallObjectManager::GetOneCallObject(callId);
292    if (callPtr == nullptr) {
293        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
294        return TELEPHONY_ERR_LOCAL_PTR_NULL;
295    }
296    if (callPtr->GetCallType() == CallType::TYPE_IMS) {
297        sptr<IMSCall> netCall = reinterpret_cast<IMSCall *>(callPtr.GetRefPtr());
298        ret = netCall->CancelCallUpgrade();
299        if (ret != TELEPHONY_SUCCESS) {
300            TELEPHONY_LOGE("CancelCallUpgrade failed!");
301            return ret;
302        }
303    }
304    return TELEPHONY_SUCCESS;
305}
306
307int32_t VideoControlManager::RequestCameraCapabilities(int32_t callId)
308{
309    int32_t ret = TELEPHONY_ERR_FAIL;
310    ret = CallPolicy::VideoCallPolicy(callId);
311    if (ret != TELEPHONY_SUCCESS) {
312        TELEPHONY_LOGE("check prerequisites failed !");
313        return ret;
314    }
315    sptr<CallBase> callPtr = CallObjectManager::GetOneCallObject(callId);
316    if (callPtr == nullptr) {
317        TELEPHONY_LOGE("the call object is nullptr, callId:%{public}d", callId);
318        return TELEPHONY_ERR_LOCAL_PTR_NULL;
319    }
320    if (callPtr->GetCallType() == CallType::TYPE_IMS) {
321        sptr<IMSCall> netCall = reinterpret_cast<IMSCall *>(callPtr.GetRefPtr());
322        ret = netCall->RequestCameraCapabilities();
323        if (ret != TELEPHONY_SUCCESS) {
324            TELEPHONY_LOGE("RequestCameraCapabilities failed!");
325            return ret;
326        }
327    }
328    return TELEPHONY_SUCCESS;
329}
330
331bool VideoControlManager::CheckWindow(VideoWindow &window)
332{
333    if (window.width <= 0 || window.height <= 0) {
334        TELEPHONY_LOGE("width or height value error");
335        return false;
336    }
337    if (window.z != VIDEO_WINDOWS_Z_BOTTOM && window.z != VIDEO_WINDOWS_Z_TOP) {
338        TELEPHONY_LOGE("z value error %{public}d", window.z);
339        return false;
340    }
341    return true;
342}
343} // namespace Telephony
344} // namespace OHOS
345