gralloc1: Import ion handle into registering process
Importing the ion handle when retain() is called validates the
incoming ion fd and holds the client process accountable for
releasing the handle once it's done.
CRs-Fixed: 2020175
Change-Id: I3a169983b6d6b201d044e1c777a631aa16f9cb9a
diff --git a/libgralloc1/gr_buf_mgr.cpp b/libgralloc1/gr_buf_mgr.cpp
index e2cfdd4..04afd35 100644
--- a/libgralloc1/gr_buf_mgr.cpp
+++ b/libgralloc1/gr_buf_mgr.cpp
@@ -155,6 +155,7 @@
void BufferManager::CreateSharedHandle(buffer_handle_t inbuffer, const BufferDescriptor &descriptor,
buffer_handle_t *outbuffer) {
+ // TODO(user): This path is not verified
private_handle_t const *input = reinterpret_cast<private_handle_t const *>(inbuffer);
// Get Buffer attributes or dimension
@@ -182,8 +183,7 @@
descriptor.GetConsumerUsage());
out_hnd->id = ++next_id_;
// TODO(user): Base address of shared handle and ion handles
- auto buffer = std::make_shared<Buffer>(out_hnd);
- handles_map_.emplace(std::make_pair(out_hnd, buffer));
+ RegisterHandle(out_hnd, -1, -1);
*outbuffer = out_hnd;
}
@@ -205,6 +205,42 @@
return GRALLOC1_ERROR_NONE;
}
+void BufferManager::RegisterHandle(const private_handle_t *hnd,
+ int ion_handle,
+ int ion_handle_meta) {
+ auto buffer = std::make_shared<Buffer>(hnd, ion_handle, ion_handle_meta);
+ handles_map_.emplace(std::make_pair(hnd, buffer));
+}
+
+gralloc1_error_t BufferManager::ImportHandle(private_handle_t* hnd) {
+ int ion_handle = allocator_->ImportBuffer(hnd->fd);
+ if (ion_handle < 0) {
+ ALOGE("Failed to import ion buffer: hnd: %p, fd:%d, id:%" PRIu64, hnd, hnd->fd, hnd->id);
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+ int ion_handle_meta = allocator_->ImportBuffer(hnd->fd_metadata);
+ if (ion_handle_meta < 0) {
+ ALOGE("Failed to import ion metadata buffer: hnd: %p, fd:%d, id:%" PRIu64, hnd,
+ hnd->fd, hnd->id);
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+ // Set base pointers to NULL since the data here was received over binder
+ hnd->base = 0;
+ hnd->base_metadata = 0;
+ RegisterHandle(hnd, ion_handle, ion_handle_meta);
+ return GRALLOC1_ERROR_NONE;
+}
+
+std::shared_ptr<BufferManager::Buffer>
+BufferManager::GetBufferFromHandle(const private_handle_t *hnd) {
+ auto it = handles_map_.find(hnd);
+ if (it != handles_map_.end()) {
+ return it->second;
+ } else {
+ return nullptr;
+ }
+}
+
gralloc1_error_t BufferManager::MapBuffer(private_handle_t const *handle) {
private_handle_t *hnd = const_cast<private_handle_t *>(handle);
@@ -215,7 +251,7 @@
return GRALLOC1_ERROR_BAD_HANDLE;
}
- unsigned int size = ALIGN((unsigned int)sizeof(MetaData_t), PAGE_SIZE);
+ unsigned int size = ALIGN((unsigned int)sizeof(MetaData_t), getpagesize());
if (allocator_->MapBuffer(reinterpret_cast<void **>(&hnd->base_metadata), size,
hnd->offset_metadata, hnd->fd_metadata) != 0) {
return GRALLOC1_ERROR_BAD_HANDLE;
@@ -227,39 +263,32 @@
gralloc1_error_t BufferManager::RetainBuffer(private_handle_t const *hnd) {
std::lock_guard<std::mutex> lock(locker_);
ALOGD_IF(DEBUG, "Retain buffer handle:%p id: %" PRIu64, hnd, hnd->id);
-
- // find if this handle is already in map
- auto it = handles_map_.find(hnd);
- if (it != handles_map_.end()) {
- // It's already in map, Just increment refcnt
- // No need to mmap the memory.
- auto buf = it->second;
- buf->ref_count++;
+ gralloc1_error_t err = GRALLOC1_ERROR_NONE;
+ auto buf = GetBufferFromHandle(hnd);
+ if (buf != nullptr) {
+ buf->IncRef();
} else {
- // not present in the map. mmap and then add entry to map
- if (MapBuffer(hnd) == GRALLOC1_ERROR_NONE) {
- auto buffer = std::make_shared<Buffer>(hnd);
- handles_map_.emplace(std::make_pair(hnd, buffer));
+ private_handle_t *handle = const_cast<private_handle_t *>(hnd);
+ err = ImportHandle(handle);
+ if (err == GRALLOC1_ERROR_NONE) {
+ // TODO(user): Do not map here, map should be in lock()
+ err = MapBuffer(hnd);
}
}
-
- return GRALLOC1_ERROR_NONE;
+ return err;
}
gralloc1_error_t BufferManager::ReleaseBuffer(private_handle_t const *hnd) {
std::lock_guard<std::mutex> lock(locker_);
ALOGD_IF(DEBUG, "Release buffer handle:%p id: %" PRIu64, hnd, hnd->id);
- // find if this handle is already in map
- auto it = handles_map_.find(hnd);
- if (it == handles_map_.end()) {
- // Corrupt handle or map.
- ALOGE("Could not find handle");
+ auto buf = GetBufferFromHandle(hnd);
+ if (buf == nullptr) {
+ ALOGE("Could not find handle: %p id: %" PRIu64, hnd, hnd->id);
return GRALLOC1_ERROR_BAD_HANDLE;
} else {
- auto buf = it->second;
- buf->ref_count--;
- if (buf->ref_count == 0) {
- handles_map_.erase(it);
+ if (buf->DecRef()) {
+ handles_map_.erase(hnd);
+ // Unmap, close ion handle and close fd
FreeBuffer(buf);
}
}
@@ -269,6 +298,7 @@
gralloc1_error_t BufferManager::LockBuffer(const private_handle_t *hnd,
gralloc1_producer_usage_t prod_usage,
gralloc1_consumer_usage_t cons_usage) {
+ std::lock_guard<std::mutex> lock(locker_);
gralloc1_error_t err = GRALLOC1_ERROR_NONE;
// If buffer is not meant for CPU return err
@@ -278,18 +308,23 @@
if (hnd->base == 0) {
// we need to map for real
- locker_.lock();
err = MapBuffer(hnd);
- locker_.unlock();
+ }
+
+ auto buf = GetBufferFromHandle(hnd);
+ if (buf == nullptr) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
}
// Invalidate if CPU reads in software and there are non-CPU
// writers. No need to do this for the metadata buffer as it is
// only read/written in software.
+
+ // todo use handle here
if (!err && (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) &&
(hnd->flags & private_handle_t::PRIV_FLAGS_CACHED)) {
if (allocator_->CleanBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
- hnd->fd, CACHE_INVALIDATE)) {
+ buf->ion_handle_main, CACHE_INVALIDATE)) {
return GRALLOC1_ERROR_BAD_HANDLE;
}
}
@@ -304,20 +339,23 @@
}
gralloc1_error_t BufferManager::UnlockBuffer(const private_handle_t *handle) {
+ std::lock_guard<std::mutex> lock(locker_);
gralloc1_error_t status = GRALLOC1_ERROR_NONE;
- locker_.lock();
private_handle_t *hnd = const_cast<private_handle_t *>(handle);
+ auto buf = GetBufferFromHandle(hnd);
+ if (buf == nullptr) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
if (allocator_->CleanBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
- hnd->fd, CACHE_CLEAN) != 0) {
+ buf->ion_handle_main, CACHE_CLEAN) != 0) {
status = GRALLOC1_ERROR_BAD_HANDLE;
}
hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
}
- locker_.unlock();
return status;
}
@@ -459,8 +497,7 @@
ColorSpace_t colorSpace = ITU_R_601;
setMetaData(hnd, UPDATE_COLOR_SPACE, reinterpret_cast<void *>(&colorSpace));
*handle = hnd;
- auto buffer = std::make_shared<Buffer>(hnd, data.ion_handle, e_data.ion_handle);
- handles_map_.emplace(std::make_pair(hnd, buffer));
+ RegisterHandle(hnd, data.ion_handle, e_data.ion_handle);
ALOGD_IF(DEBUG, "Allocated buffer handle: %p id: %" PRIu64, hnd, hnd->id);
if (DEBUG) {
private_handle_t::Dump(hnd);