Merge "Revert "Transfer large bitmaps using ashmem. Bug: 5224703""
This commit is contained in:
@@ -392,20 +392,10 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
|
|||||||
SkSafeUnref(ctable);
|
SkSafeUnref(ctable);
|
||||||
|
|
||||||
size_t size = bitmap->getSize();
|
size_t size = bitmap->getSize();
|
||||||
|
|
||||||
android::Parcel::ReadableBlob blob;
|
|
||||||
android::status_t status = p->readBlob(size, &blob);
|
|
||||||
if (status) {
|
|
||||||
doThrowRE(env, "Could not read bitmap from parcel blob.");
|
|
||||||
delete bitmap;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bitmap->lockPixels();
|
bitmap->lockPixels();
|
||||||
memcpy(bitmap->getPixels(), blob.data(), size);
|
memcpy(bitmap->getPixels(), p->readInplace(size), size);
|
||||||
bitmap->unlockPixels();
|
bitmap->unlockPixels();
|
||||||
|
|
||||||
blob.release();
|
|
||||||
return GraphicsJNI::createBitmap(env, bitmap, buffer, isMutable, NULL, density);
|
return GraphicsJNI::createBitmap(env, bitmap, buffer, isMutable, NULL, density);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,24 +431,17 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t size = bitmap->getSize();
|
size_t size = bitmap->getSize();
|
||||||
|
|
||||||
android::Parcel::WritableBlob blob;
|
|
||||||
android::status_t status = p->writeBlob(size, &blob);
|
|
||||||
if (status) {
|
|
||||||
doThrowRE(env, "Could not write bitmap to parcel blob.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bitmap->lockPixels();
|
bitmap->lockPixels();
|
||||||
|
void* pDst = p->writeInplace(size);
|
||||||
|
|
||||||
const void* pSrc = bitmap->getPixels();
|
const void* pSrc = bitmap->getPixels();
|
||||||
|
|
||||||
if (pSrc == NULL) {
|
if (pSrc == NULL) {
|
||||||
memset(blob.data(), 0, size);
|
memset(pDst, 0, size);
|
||||||
} else {
|
} else {
|
||||||
memcpy(blob.data(), pSrc, size);
|
memcpy(pDst, pSrc, size);
|
||||||
}
|
}
|
||||||
bitmap->unlockPixels();
|
bitmap->unlockPixels();
|
||||||
|
|
||||||
blob.release();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1061,7 +1061,7 @@ public final class Bitmap implements Parcelable {
|
|||||||
* No special parcel contents.
|
* No special parcel contents.
|
||||||
*/
|
*/
|
||||||
public int describeContents() {
|
public int describeContents() {
|
||||||
return Parcelable.CONTENTS_FILE_DESCRIPTOR; // uses parcel blobs
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -38,9 +38,6 @@ struct flat_binder_object; // defined in support_p/binder_module.h
|
|||||||
class Parcel
|
class Parcel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
class ReadableBlob;
|
|
||||||
class WritableBlob;
|
|
||||||
|
|
||||||
Parcel();
|
Parcel();
|
||||||
~Parcel();
|
~Parcel();
|
||||||
|
|
||||||
@@ -112,13 +109,7 @@ public:
|
|||||||
// Place a file descriptor into the parcel. A dup of the fd is made, which
|
// Place a file descriptor into the parcel. A dup of the fd is made, which
|
||||||
// will be closed once the parcel is destroyed.
|
// will be closed once the parcel is destroyed.
|
||||||
status_t writeDupFileDescriptor(int fd);
|
status_t writeDupFileDescriptor(int fd);
|
||||||
|
|
||||||
// Writes a blob to the parcel.
|
|
||||||
// If the blob is small, then it is stored in-place, otherwise it is
|
|
||||||
// transferred by way of an anonymous shared memory region.
|
|
||||||
// The caller should call release() on the blob after writing its contents.
|
|
||||||
status_t writeBlob(size_t len, WritableBlob* outBlob);
|
|
||||||
|
|
||||||
status_t writeObject(const flat_binder_object& val, bool nullMetaData);
|
status_t writeObject(const flat_binder_object& val, bool nullMetaData);
|
||||||
|
|
||||||
// Like Parcel.java's writeNoException(). Just writes a zero int32.
|
// Like Parcel.java's writeNoException(). Just writes a zero int32.
|
||||||
@@ -166,11 +157,7 @@ public:
|
|||||||
// Retrieve a file descriptor from the parcel. This returns the raw fd
|
// Retrieve a file descriptor from the parcel. This returns the raw fd
|
||||||
// in the parcel, which you do not own -- use dup() to get your own copy.
|
// in the parcel, which you do not own -- use dup() to get your own copy.
|
||||||
int readFileDescriptor() const;
|
int readFileDescriptor() const;
|
||||||
|
|
||||||
// Reads a blob from the parcel.
|
|
||||||
// The caller should call release() on the blob after reading its contents.
|
|
||||||
status_t readBlob(size_t len, ReadableBlob* outBlob) const;
|
|
||||||
|
|
||||||
const flat_binder_object* readObject(bool nullMetaData) const;
|
const flat_binder_object* readObject(bool nullMetaData) const;
|
||||||
|
|
||||||
// Explicitly close all file descriptors in the parcel.
|
// Explicitly close all file descriptors in the parcel.
|
||||||
@@ -190,7 +177,7 @@ public:
|
|||||||
release_func relFunc, void* relCookie);
|
release_func relFunc, void* relCookie);
|
||||||
|
|
||||||
void print(TextOutput& to, uint32_t flags = 0) const;
|
void print(TextOutput& to, uint32_t flags = 0) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Parcel(const Parcel& o);
|
Parcel(const Parcel& o);
|
||||||
Parcel& operator=(const Parcel& o);
|
Parcel& operator=(const Parcel& o);
|
||||||
@@ -228,36 +215,6 @@ private:
|
|||||||
|
|
||||||
release_func mOwner;
|
release_func mOwner;
|
||||||
void* mOwnerCookie;
|
void* mOwnerCookie;
|
||||||
|
|
||||||
class Blob {
|
|
||||||
public:
|
|
||||||
Blob();
|
|
||||||
~Blob();
|
|
||||||
|
|
||||||
void release();
|
|
||||||
inline size_t size() const { return mSize; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void init(bool mapped, void* data, size_t size);
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
bool mMapped;
|
|
||||||
void* mData;
|
|
||||||
size_t mSize;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
class ReadableBlob : public Blob {
|
|
||||||
friend class Parcel;
|
|
||||||
public:
|
|
||||||
inline const void* data() const { return mData; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class WritableBlob : public Blob {
|
|
||||||
friend class Parcel;
|
|
||||||
public:
|
|
||||||
inline void* data() { return mData; }
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -30,14 +30,12 @@
|
|||||||
#include <utils/TextOutput.h>
|
#include <utils/TextOutput.h>
|
||||||
#include <utils/misc.h>
|
#include <utils/misc.h>
|
||||||
#include <utils/Flattenable.h>
|
#include <utils/Flattenable.h>
|
||||||
#include <cutils/ashmem.h>
|
|
||||||
|
|
||||||
#include <private/binder/binder_module.h>
|
#include <private/binder/binder_module.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/mman.h>
|
|
||||||
|
|
||||||
#ifndef INT32_MAX
|
#ifndef INT32_MAX
|
||||||
#define INT32_MAX ((int32_t)(2147483647))
|
#define INT32_MAX ((int32_t)(2147483647))
|
||||||
@@ -56,9 +54,6 @@
|
|||||||
// Note: must be kept in sync with android/os/Parcel.java's EX_HAS_REPLY_HEADER
|
// Note: must be kept in sync with android/os/Parcel.java's EX_HAS_REPLY_HEADER
|
||||||
#define EX_HAS_REPLY_HEADER -128
|
#define EX_HAS_REPLY_HEADER -128
|
||||||
|
|
||||||
// Maximum size of a blob to transfer in-place.
|
|
||||||
static const size_t IN_PLACE_BLOB_LIMIT = 40 * 1024;
|
|
||||||
|
|
||||||
// XXX This can be made public if we want to provide
|
// XXX This can be made public if we want to provide
|
||||||
// support for typed data.
|
// support for typed data.
|
||||||
struct small_flat_data
|
struct small_flat_data
|
||||||
@@ -711,47 +706,6 @@ status_t Parcel::writeDupFileDescriptor(int fd)
|
|||||||
return writeObject(obj, true);
|
return writeObject(obj, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t Parcel::writeBlob(size_t len, WritableBlob* outBlob)
|
|
||||||
{
|
|
||||||
if (len <= IN_PLACE_BLOB_LIMIT) {
|
|
||||||
LOGV("writeBlob: write in place");
|
|
||||||
void* ptr = writeInplace(len);
|
|
||||||
if (!ptr) return NO_MEMORY;
|
|
||||||
|
|
||||||
outBlob->init(false /*mapped*/, ptr, len);
|
|
||||||
return NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGV("writeBlob: write to ashmem");
|
|
||||||
int fd = ashmem_create_region("Parcel Blob", len);
|
|
||||||
if (fd < 0) return NO_MEMORY;
|
|
||||||
|
|
||||||
status_t status;
|
|
||||||
int result = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
|
|
||||||
if (result < 0) {
|
|
||||||
status = -result;
|
|
||||||
} else {
|
|
||||||
void* ptr = ::mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
|
||||||
if (ptr == MAP_FAILED) {
|
|
||||||
status = -errno;
|
|
||||||
} else {
|
|
||||||
result = ashmem_set_prot_region(fd, PROT_READ);
|
|
||||||
if (result < 0) {
|
|
||||||
status = -result;
|
|
||||||
} else {
|
|
||||||
status = writeFileDescriptor(fd);
|
|
||||||
if (!status) {
|
|
||||||
outBlob->init(true /*mapped*/, ptr, len);
|
|
||||||
return NO_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
::munmap(ptr, len);
|
|
||||||
}
|
|
||||||
::close(fd);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t Parcel::write(const Flattenable& val)
|
status_t Parcel::write(const Flattenable& val)
|
||||||
{
|
{
|
||||||
status_t err;
|
status_t err;
|
||||||
@@ -1071,28 +1025,6 @@ int Parcel::readFileDescriptor() const
|
|||||||
return BAD_TYPE;
|
return BAD_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const
|
|
||||||
{
|
|
||||||
if (len <= IN_PLACE_BLOB_LIMIT) {
|
|
||||||
LOGV("readBlob: read in place");
|
|
||||||
const void* ptr = readInplace(len);
|
|
||||||
if (!ptr) return BAD_VALUE;
|
|
||||||
|
|
||||||
outBlob->init(false /*mapped*/, const_cast<void*>(ptr), len);
|
|
||||||
return NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGV("readBlob: read from ashmem");
|
|
||||||
int fd = readFileDescriptor();
|
|
||||||
if (fd == int(BAD_TYPE)) return BAD_VALUE;
|
|
||||||
|
|
||||||
void* ptr = ::mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
|
|
||||||
if (!ptr) return NO_MEMORY;
|
|
||||||
|
|
||||||
outBlob->init(true /*mapped*/, ptr, len);
|
|
||||||
return NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t Parcel::read(Flattenable& val) const
|
status_t Parcel::read(Flattenable& val) const
|
||||||
{
|
{
|
||||||
// size
|
// size
|
||||||
@@ -1520,33 +1452,4 @@ void Parcel::scanForFds() const
|
|||||||
mFdsKnown = true;
|
mFdsKnown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Parcel::Blob ---
|
|
||||||
|
|
||||||
Parcel::Blob::Blob() :
|
|
||||||
mMapped(false), mData(NULL), mSize(0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
Parcel::Blob::~Blob() {
|
|
||||||
release();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parcel::Blob::release() {
|
|
||||||
if (mMapped && mData) {
|
|
||||||
::munmap(mData, mSize);
|
|
||||||
}
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parcel::Blob::init(bool mapped, void* data, size_t size) {
|
|
||||||
mMapped = mapped;
|
|
||||||
mData = data;
|
|
||||||
mSize = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parcel::Blob::clear() {
|
|
||||||
mMapped = false;
|
|
||||||
mData = NULL;
|
|
||||||
mSize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // namespace android
|
}; // namespace android
|
||||||
|
|||||||
Reference in New Issue
Block a user