blob: 5dd83f4349ef9b0ada1e99df2cb69c078badec12 [file] [log] [blame]
Ytai Ben-Tsvi37934a22020-08-11 15:53:04 -07001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "media/ShmemCompat.h"
17
18#include "binder/MemoryBase.h"
19#include "binder/MemoryHeapBase.h"
20#include "media/ShmemUtil.h"
21
22namespace android {
23namespace media {
24
25bool convertSharedFileRegionToIMemory(const SharedFileRegion& shmem,
26 sp<IMemory>* result) {
27 if (!validateSharedFileRegion(shmem)) {
28 return false;
29 }
30
31 if (shmem.fd.get() < 0) {
32 *result = nullptr;
33 return true;
34 }
35
36 // Heap offset and size must be page aligned.
37 const size_t pageSize = getpagesize();
38 const size_t pageMask = ~(pageSize - 1);
39
40 // OK if this wraps.
41 const uint64_t endOffset = static_cast<uint64_t>(shmem.offset) +
42 static_cast<uint64_t>(shmem.size);
43
44 // Round down to page boundary.
45 const uint64_t heapStartOffset = shmem.offset & pageMask;
46 // Round up to page boundary.
47 const uint64_t heapEndOffset = (endOffset + pageSize - 1) & pageMask;
48 const uint64_t heapSize = heapEndOffset - heapStartOffset;
49
50 if (heapStartOffset > std::numeric_limits<size_t>::max() ||
51 heapSize > std::numeric_limits<size_t>::max()) {
52 return false;
53 }
54
55 const sp<MemoryHeapBase> heap =
56 new MemoryHeapBase(shmem.fd.get(), heapSize, 0, heapStartOffset);
57 *result = sp<MemoryBase>::make(heap,
58 shmem.offset - heapStartOffset,
59 shmem.size);
60 return true;
61}
62
63bool convertIMemoryToSharedFileRegion(const sp<IMemory>& mem,
64 SharedFileRegion* result) {
65 *result = SharedFileRegion();
66 if (mem == nullptr) {
67 return true;
68 }
69
70 ssize_t offset;
71 size_t size;
72
73 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
74 if (heap != nullptr) {
75 // Make sure the offset and size do not overflow from int64 boundaries.
76 if (size > std::numeric_limits<int64_t>::max() ||
77 offset > std::numeric_limits<int64_t>::max() ||
78 heap->getOffset() > std::numeric_limits<int64_t>::max() ||
79 static_cast<uint64_t>(heap->getOffset()) +
80 static_cast<uint64_t>(offset)
81 > std::numeric_limits<int64_t>::max()) {
82 return false;
83 }
84
85 const int fd = fcntl(heap->getHeapID(), F_DUPFD_CLOEXEC, 0);
86 if (fd < 0) {
87 return false;
88 }
89 result->fd.reset(base::unique_fd(fd));
90 result->size = size;
91 result->offset = heap->getOffset() + offset;
92 }
93
94 return true;
95}
96
97} // namespace media
98} // namespace android