1/*
2 * Copyright (c) 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 "surface_tunnel_handle.h"
17#include <securec.h>
18#include "buffer_log.h"
19
20namespace OHOS {
21GraphicExtDataHandle *AllocExtDataHandle(uint32_t reserveInts)
22{
23    if (static_cast<size_t>(reserveInts) > (SIZE_MAX - sizeof(GraphicExtDataHandle)) / sizeof(int32_t)) {
24        BLOGE("reserveInts: %{public}u is too large", reserveInts);
25        return nullptr;
26    }
27    size_t handleSize = sizeof(GraphicExtDataHandle) + (sizeof(int32_t) * reserveInts);
28    GraphicExtDataHandle *handle = static_cast<GraphicExtDataHandle *>(malloc(handleSize));
29    if (handle == nullptr) {
30        BLOGE("malloc %{public}zu failed", handleSize);
31        return nullptr;
32    }
33    auto ret = memset_s(handle, handleSize, 0, handleSize);
34    if (ret != EOK) {
35        free(handle);
36        BLOGE("memset_s failed, ret: %{public}d", ret);
37        return nullptr;
38    }
39    handle->fd = -1;
40    handle->reserveInts = reserveInts;
41    for (uint32_t i = 0; i < reserveInts; i++) {
42        handle->reserve[i] = -1;
43    }
44    return handle;
45}
46
47void FreeExtDataHandle(GraphicExtDataHandle *handle)
48{
49    if (handle == nullptr) {
50        BLOGW("FreeExtDataHandle with nullptr handle");
51        return;
52    }
53    if (handle->fd >= 0) {
54        close(handle->fd);
55        handle->fd = -1;
56    }
57    free(handle);
58}
59
60SurfaceTunnelHandle::SurfaceTunnelHandle()
61{
62    BLOGD("SurfaceTunnelHandle ctor");
63}
64
65SurfaceTunnelHandle::~SurfaceTunnelHandle()
66{
67    std::lock_guard<std::mutex> lock(mutex_);
68    BLOGD("~SurfaceTunnelHandle dtor tunnelHandle_");
69    FreeExtDataHandle(tunnelHandle_);
70}
71
72GSError SurfaceTunnelHandle::SetHandle(const GraphicExtDataHandle *handle)
73{
74    if (handle == nullptr) {  // handle is nullptr, which is valid and tunnelHandle_ is nullptr now
75        BLOGW("SetHandle with nullptr");
76        return GSERROR_OK;
77    }
78    std::lock_guard<std::mutex> lock(mutex_);
79    FreeExtDataHandle(tunnelHandle_);
80    tunnelHandle_ = AllocExtDataHandle(handle->reserveInts);
81    if (tunnelHandle_ == nullptr) {
82        BLOGE("AllocExtDataHandle failed");
83        return GSERROR_INVALID_OPERATING;
84    }
85    tunnelHandle_->fd = handle->fd;
86    for (uint32_t index = 0; index < handle->reserveInts; index++) {
87        tunnelHandle_->reserve[index] = handle->reserve[index];
88    }
89    return GSERROR_OK;
90}
91
92GraphicExtDataHandle *SurfaceTunnelHandle::GetHandle()
93{
94    std::lock_guard<std::mutex> lock(mutex_);
95    return tunnelHandle_;
96}
97
98bool SurfaceTunnelHandle::Different(const sptr<SurfaceTunnelHandle> &handle)
99{
100    std::lock_guard<std::mutex> lock(mutex_);
101    if (tunnelHandle_ == nullptr) {
102        return false;
103    }
104    if (handle == nullptr || handle->GetHandle() == nullptr) {
105        return true;
106    }
107
108    bool diffHandle = tunnelHandle_->fd != handle->GetHandle()->fd ||
109                      tunnelHandle_->reserveInts != handle->GetHandle()->reserveInts;
110    if (diffHandle) {
111        return diffHandle;
112    }
113    for (uint32_t index = 0; index < handle->GetHandle()->reserveInts; index++) {
114        diffHandle = diffHandle || tunnelHandle_->reserve[index] != handle->GetHandle()->reserve[index];
115    }
116    return diffHandle;
117}
118} // namespace OHOS
119