1 // Copyright 2018 The Android Open Source Project
2 //
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 #include <cutils/ashmem.h>
15
16 #include "base/Lookup.h"
17 #include "base/SharedMemory.h"
18
19 #include "AndroidHostCommon.h"
20 #include "Ashmem.h"
21
22 #include <atomic>
23 #include <memory>
24 #include <sstream>
25 #include <unordered_map>
26
27 #include <errno.h>
28
29 using android::base::SharedMemory;
30
31 class SharedMemoryStore {
32 public:
33 SharedMemoryStore() = default;
34
create(const char * name,size_t size)35 int create(const char* name, size_t size) {
36 std::unique_ptr<SharedMemory> mem =
37 std::make_unique<SharedMemory>(name, size);
38
39 mem->createNoMapping(0755);
40
41 int fd = mem->getFd();
42 if (fd >= 0) {
43 mMemories[fd] = std::move(mem);
44 } else {
45 fprintf(stderr, "%s: SharedMemory creation failed! errno: %d\n",
46 __func__, errno);
47 }
48 return fd;
49 }
50
clear()51 void clear() {
52 mMemories.clear();
53 }
54
close(int fd)55 void close(int fd) {
56 mMemories.erase(fd);
57 }
58
nextUniqueId()59 int nextUniqueId() {
60 return std::atomic_fetch_add(&mNextId, 1);
61 }
62
63 private:
64 std::atomic<int> mNextId = { 0 };
65 std::unordered_map<int, std::unique_ptr<SharedMemory>> mMemories;
66 };
67
sStore()68 static SharedMemoryStore* sStore() {
69 static SharedMemoryStore* s = new SharedMemoryStore;
70 return s;
71 }
72
73 extern "C" {
74
ashmem_valid(int fd)75 EXPORT int ashmem_valid(int fd) {
76 // TODO: distinguish ashmem from others
77 return true;
78 }
79
80 // ashmem_create_region seems to mean to create a new
81 // subregion associated with |name|, not necessarily share
82 // the region named |name|. So we implement it in terms of
83 // the name + a number counting from 0.
ashmem_create_region(const char * name,size_t size)84 EXPORT int ashmem_create_region(const char *name, size_t size) {
85 std::stringstream ss;
86 ss << name;
87 ss << sStore()->nextUniqueId();
88
89 std::string nameWithHash = ss.str();
90
91 return sStore()->create(nameWithHash.c_str(), size);
92 }
93
ashmem_teardown()94 EXPORT void ashmem_teardown() {
95 sStore()->clear();
96 }
97
98 // TODO
99 int ashmem_set_prot_region(int fd, int prot);
100 int ashmem_pin_region(int fd, size_t offset, size_t len);
101 int ashmem_unpin_region(int fd, size_t offset, size_t len);
102 int ashmem_get_size_region(int fd);
103
104 }
105