blob: 26638126d34d2276a91d56c4daf744ea468a0051 [file] [log] [blame]
Jiwen 'Steve' Caid9f2abe2018-10-20 17:03:13 -07001/*
2 * Copyright (C) 2018 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
Fan Xu93c94902018-11-01 12:22:05 -070017#include <android/hardware_buffer.h>
Jiwen 'Steve' Caid9f2abe2018-10-20 17:03:13 -070018#include <bufferhub/BufferHubService.h>
Fan Xu18d90ea2018-11-06 15:46:44 -080019#include <cutils/native_handle.h>
Fan Xu93c94902018-11-01 12:22:05 -070020#include <log/log.h>
Jiwen 'Steve' Caid9f2abe2018-10-20 17:03:13 -070021
22namespace android {
23namespace frameworks {
24namespace bufferhub {
25namespace V1_0 {
26namespace implementation {
27
Fan Xuca70b7b2018-10-31 13:20:12 -070028using hardware::Void;
Jiwen 'Steve' Caid9f2abe2018-10-20 17:03:13 -070029
Fan Xu93c94902018-11-01 12:22:05 -070030Return<void> BufferHubService::allocateBuffer(const HardwareBufferDescription& description,
31 const uint32_t userMetadataSize,
Fan Xuca70b7b2018-10-31 13:20:12 -070032 allocateBuffer_cb _hidl_cb) {
Fan Xu93c94902018-11-01 12:22:05 -070033 AHardwareBuffer_Desc desc;
34 memcpy(&desc, &description, sizeof(AHardwareBuffer_Desc));
35
36 std::shared_ptr<BufferNode> node =
37 std::make_shared<BufferNode>(desc.width, desc.height, desc.layers, desc.format,
Fan Xu1c16df52018-11-19 16:27:27 -080038 desc.usage, userMetadataSize,
39 BufferHubIdGenerator::getInstance().getId());
Fan Xu93c94902018-11-01 12:22:05 -070040 if (node == nullptr || !node->IsValid()) {
41 ALOGE("%s: creating BufferNode failed.", __FUNCTION__);
Fan Xuf8f4a452018-11-29 16:26:30 -080042 _hidl_cb(/*status=*/BufferHubStatus::ALLOCATION_FAILED, /*bufferClient=*/nullptr,
43 /*bufferTraits=*/{});
Fan Xu93c94902018-11-01 12:22:05 -070044 return Void();
45 }
46
Fan Xu18d90ea2018-11-06 15:46:44 -080047 sp<BufferClient> client = BufferClient::create(this, node);
Fan Xu93c94902018-11-01 12:22:05 -070048 // Add it to list for bookkeeping and dumpsys.
Fan Xucd74d782018-11-26 13:51:25 -080049 std::lock_guard<std::mutex> lock(mClientSetMutex);
50 mClientSet.emplace(client);
Fan Xu93c94902018-11-01 12:22:05 -070051
Fan Xuf8f4a452018-11-29 16:26:30 -080052 BufferTraits bufferTraits = {/*bufferDesc=*/description,
53 /*bufferHandle=*/hidl_handle(node->buffer_handle()),
54 // TODO(b/116681016): return real data to client
55 /*bufferInfo=*/hidl_handle()};
56
57 _hidl_cb(/*status=*/BufferHubStatus::NO_ERROR, /*bufferClient=*/client,
58 /*bufferTraits=*/bufferTraits);
Jiwen 'Steve' Caid9f2abe2018-10-20 17:03:13 -070059 return Void();
60}
61
Fan Xu467e08f2018-11-09 15:58:51 -080062Return<void> BufferHubService::importBuffer(const hidl_handle& tokenHandle,
Fan Xuca70b7b2018-10-31 13:20:12 -070063 importBuffer_cb _hidl_cb) {
Fan Xu467e08f2018-11-09 15:58:51 -080064 if (!tokenHandle.getNativeHandle() || tokenHandle->numFds != 0 || tokenHandle->numInts != 1) {
65 // nullptr handle or wrong format
Fan Xuf8f4a452018-11-29 16:26:30 -080066 _hidl_cb(/*status=*/BufferHubStatus::INVALID_TOKEN, /*bufferClient=*/nullptr,
67 /*bufferTraits=*/{});
Fan Xu467e08f2018-11-09 15:58:51 -080068 return Void();
69 }
70
71 uint32_t token = tokenHandle->data[0];
72
73 wp<BufferClient> originClientWp;
74 {
75 std::lock_guard<std::mutex> lock(mTokenMapMutex);
76 auto iter = mTokenMap.find(token);
77 if (iter == mTokenMap.end()) {
78 // Invalid token
Fan Xuf8f4a452018-11-29 16:26:30 -080079 _hidl_cb(/*status=*/BufferHubStatus::INVALID_TOKEN, /*bufferClient=*/nullptr,
80 /*bufferTraits=*/{});
Fan Xu467e08f2018-11-09 15:58:51 -080081 return Void();
82 }
83
84 originClientWp = iter->second;
85 mTokenMap.erase(iter);
86 }
87
88 // Check if original client is dead
89 sp<BufferClient> originClient = originClientWp.promote();
90 if (!originClient) {
91 // Should not happen since token should be removed if already gone
92 ALOGE("%s: original client %p gone!", __FUNCTION__, originClientWp.unsafe_get());
Fan Xuf8f4a452018-11-29 16:26:30 -080093 _hidl_cb(/*status=*/BufferHubStatus::BUFFER_FREED, /*bufferClient=*/nullptr,
94 /*bufferTraits=*/{});
Fan Xu467e08f2018-11-09 15:58:51 -080095 return Void();
96 }
97
98 sp<BufferClient> client = new BufferClient(*originClient);
Fan Xuf8f4a452018-11-29 16:26:30 -080099 uint32_t clientStateMask = client->getBufferNode()->AddNewActiveClientsBitToMask();
100 if (clientStateMask == 0U) {
101 // Reach max client count
102 ALOGE("%s: import failed, BufferNode#%u reached maximum clients.", __FUNCTION__,
103 client->getBufferNode()->id());
104 _hidl_cb(/*status=*/BufferHubStatus::MAX_CLIENT, /*bufferClient=*/nullptr,
105 /*bufferTraits=*/{});
106 return Void();
107 }
Fan Xu467e08f2018-11-09 15:58:51 -0800108
Fan Xucd74d782018-11-26 13:51:25 -0800109 std::lock_guard<std::mutex> lock(mClientSetMutex);
110 mClientSet.emplace(client);
Fan Xuf8f4a452018-11-29 16:26:30 -0800111
112 std::shared_ptr<BufferNode> node = client->getBufferNode();
113
114 HardwareBufferDescription bufferDesc;
115 memcpy(&bufferDesc, &node->buffer_desc(), sizeof(HardwareBufferDescription));
116
117 BufferTraits bufferTraits = {/*bufferDesc=*/bufferDesc,
118 /*bufferHandle=*/hidl_handle(node->buffer_handle()),
119 // TODO(b/116681016): return real data to client
120 /*bufferInfo=*/hidl_handle()};
121
122 _hidl_cb(/*status=*/BufferHubStatus::NO_ERROR, /*bufferClient=*/client,
123 /*bufferTraits=*/bufferTraits);
Fan Xuca70b7b2018-10-31 13:20:12 -0700124 return Void();
Jiwen 'Steve' Caid9f2abe2018-10-20 17:03:13 -0700125}
126
Fan Xud6cd6ba2018-11-15 16:46:55 -0800127hidl_handle BufferHubService::registerToken(const wp<BufferClient>& client) {
Fan Xu18d90ea2018-11-06 15:46:44 -0800128 uint32_t token;
129 std::lock_guard<std::mutex> lock(mTokenMapMutex);
130 do {
131 token = mTokenEngine();
132 } while (mTokenMap.find(token) != mTokenMap.end());
133
134 // native_handle_t use int[], so here need one slots to fit in uint32_t
135 native_handle_t* handle = native_handle_create(/*numFds=*/0, /*numInts=*/1);
136 handle->data[0] = token;
137
138 // returnToken owns the native_handle_t* thus doing lifecycle management
139 hidl_handle returnToken;
140 returnToken.setTo(handle, /*shoudOwn=*/true);
141
142 mTokenMap.emplace(token, client);
143 return returnToken;
144}
145
Fan Xua7422fe2018-11-19 15:21:32 -0800146void BufferHubService::onClientClosed(const BufferClient* client) {
147 removeTokenByClient(client);
148
Fan Xucd74d782018-11-26 13:51:25 -0800149 std::lock_guard<std::mutex> lock(mClientSetMutex);
150 auto iter = std::find(mClientSet.begin(), mClientSet.end(), client);
151 if (iter != mClientSet.end()) {
152 mClientSet.erase(iter);
Fan Xua7422fe2018-11-19 15:21:32 -0800153 }
154}
155
156void BufferHubService::removeTokenByClient(const BufferClient* client) {
157 std::lock_guard<std::mutex> lock(mTokenMapMutex);
158 auto iter = mTokenMap.begin();
159 while (iter != mTokenMap.end()) {
160 if (iter->second == client) {
161 auto oldIter = iter;
162 ++iter;
163 mTokenMap.erase(oldIter);
164 } else {
165 ++iter;
166 }
167 }
168}
169
Jiwen 'Steve' Caid9f2abe2018-10-20 17:03:13 -0700170} // namespace implementation
171} // namespace V1_0
172} // namespace bufferhub
173} // namespace frameworks
174} // namespace android