diff options
Diffstat (limited to 'libs')
69 files changed, 3169 insertions, 1276 deletions
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp index 61b4f7d..c562c30 100644 --- a/libs/binder/AppOpsManager.cpp +++ b/libs/binder/AppOpsManager.cpp @@ -44,7 +44,7 @@ sp<IAppOpsService> AppOpsManager::getService() int64_t startTime = 0; mLock.lock(); sp<IAppOpsService> service = mService; - while (service == NULL || !service->asBinder()->isBinderAlive()) { + while (service == NULL || !IInterface::asBinder(service)->isBinderAlive()) { sp<IBinder> binder = defaultServiceManager()->checkService(_appops); if (binder == NULL) { // Wait for the app ops service to come back... diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp index 2554351..9d200fb 100644 --- a/libs/binder/Binder.cpp +++ b/libs/binder/Binder.cpp @@ -72,7 +72,7 @@ public: BBinder::BBinder() { - atomic_init(&mExtras, 0); + atomic_init(&mExtras, static_cast<uintptr_t>(0)); } bool BBinder::isBinderAlive() const @@ -160,10 +160,18 @@ void BBinder::attachObject( e->mObjects.attach(objectID, object, cleanupCookie, func); } +// The C11 standard doesn't allow atomic loads from const fields, +// though C++11 does. Fudge it until standards get straightened out. +static inline uintptr_t load_const_atomic(const atomic_uintptr_t* p, + memory_order mo) { + atomic_uintptr_t* non_const_p = const_cast<atomic_uintptr_t*>(p); + return atomic_load_explicit(non_const_p, mo); +} + void* BBinder::findObject(const void* objectID) const { Extras* e = reinterpret_cast<Extras*>( - atomic_load_explicit(&mExtras, memory_order_acquire)); + load_const_atomic(&mExtras, memory_order_acquire)); if (!e) return NULL; AutoMutex _l(e->mLock); diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp index 101de7e..345ba20 100644 --- a/libs/binder/BpBinder.cpp +++ b/libs/binder/BpBinder.cpp @@ -220,7 +220,6 @@ status_t BpBinder::unlinkToDeath( if ((obit.recipient == recipient || (recipient == NULL && obit.cookie == cookie)) && obit.flags == flags) { - const uint32_t allFlags = obit.flags|flags; if (outRecipient != NULL) { *outRecipient = mObituaries->itemAt(i).recipient; } diff --git a/libs/binder/Debug.cpp b/libs/binder/Debug.cpp index 0ffafbb..bdb7182 100644 --- a/libs/binder/Debug.cpp +++ b/libs/binder/Debug.cpp @@ -220,13 +220,8 @@ void printHexData(int32_t indent, const void *buf, size_t length, for (word = 0; word < bytesPerLine; ) { -#ifdef HAVE_LITTLE_ENDIAN const size_t startIndex = word+(alignment-(alignment?1:0)); const ssize_t dir = -1; -#else - const size_t startIndex = word; - const ssize_t dir = 1; -#endif for (index = 0; index < alignment || (alignment == 0 && index < bytesPerLine); index++) { diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp index f58a352..86abdc0 100644 --- a/libs/binder/IAppOpsService.cpp +++ b/libs/binder/IAppOpsService.cpp @@ -91,14 +91,14 @@ public: data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor()); data.writeInt32(op); data.writeString16(packageName); - data.writeStrongBinder(callback->asBinder()); + data.writeStrongBinder(IInterface::asBinder(callback)); remote()->transact(START_WATCHING_MODE_TRANSACTION, data, &reply); } virtual void stopWatchingMode(const sp<IAppOpsCallback>& callback) { Parcel data, reply; data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor()); - data.writeStrongBinder(callback->asBinder()); + data.writeStrongBinder(IInterface::asBinder(callback)); remote()->transact(STOP_WATCHING_MODE_TRANSACTION, data, &reply); } diff --git a/libs/binder/IInterface.cpp b/libs/binder/IInterface.cpp index 29acf5d..8c60dc4 100644 --- a/libs/binder/IInterface.cpp +++ b/libs/binder/IInterface.cpp @@ -27,14 +27,18 @@ IInterface::IInterface() IInterface::~IInterface() { } -sp<IBinder> IInterface::asBinder() +// static +sp<IBinder> IInterface::asBinder(const IInterface* iface) { - return this ? onAsBinder() : NULL; + if (iface == NULL) return NULL; + return const_cast<IInterface*>(iface)->onAsBinder(); } -sp<const IBinder> IInterface::asBinder() const +// static +sp<IBinder> IInterface::asBinder(const sp<IInterface>& iface) { - return this ? const_cast<IInterface*>(this)->onAsBinder() : NULL; + if (iface == NULL) return NULL; + return iface->onAsBinder(); } // --------------------------------------------------------------------------- diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp index d8ed995..e9891a8 100644 --- a/libs/binder/IMemory.cpp +++ b/libs/binder/IMemory.cpp @@ -216,7 +216,7 @@ status_t BnMemory::onTransact( CHECK_INTERFACE(IMemory, data, reply); ssize_t offset; size_t size; - reply->writeStrongBinder( getMemory(&offset, &size)->asBinder() ); + reply->writeStrongBinder( IInterface::asBinder(getMemory(&offset, &size)) ); reply->writeInt32(offset); reply->writeInt32(size); return NO_ERROR; @@ -241,7 +241,7 @@ BpMemoryHeap::~BpMemoryHeap() { if (mRealHeap) { // by construction we're the last one if (mBase != MAP_FAILED) { - sp<IBinder> binder = const_cast<BpMemoryHeap*>(this)->asBinder(); + sp<IBinder> binder = IInterface::asBinder(this); if (VERBOSE) { ALOGD("UNMAPPING binder=%p, heap=%p, size=%zu, fd=%d", @@ -253,7 +253,7 @@ BpMemoryHeap::~BpMemoryHeap() { } } else { // remove from list only if it was mapped before - sp<IBinder> binder = const_cast<BpMemoryHeap*>(this)->asBinder(); + sp<IBinder> binder = IInterface::asBinder(this); free_heap(binder); } } @@ -262,7 +262,7 @@ BpMemoryHeap::~BpMemoryHeap() { void BpMemoryHeap::assertMapped() const { if (mHeapId == -1) { - sp<IBinder> binder(const_cast<BpMemoryHeap*>(this)->asBinder()); + sp<IBinder> binder(IInterface::asBinder(const_cast<BpMemoryHeap*>(this))); sp<BpMemoryHeap> heap(static_cast<BpMemoryHeap*>(find_heap(binder).get())); heap->assertReallyMapped(); if (heap->mBase != MAP_FAILED) { @@ -297,7 +297,8 @@ void BpMemoryHeap::assertReallyMapped() const uint32_t offset = reply.readInt32(); ALOGE_IF(err, "binder=%p transaction failed fd=%d, size=%zd, err=%d (%s)", - asBinder().get(), parcel_fd, size, err, strerror(-err)); + IInterface::asBinder(this).get(), + parcel_fd, size, err, strerror(-err)); int fd = dup( parcel_fd ); ALOGE_IF(fd==-1, "cannot dup fd=%d, size=%zd, err=%d (%s)", @@ -314,7 +315,7 @@ void BpMemoryHeap::assertReallyMapped() const mBase = mmap(0, size, access, MAP_SHARED, fd, offset); if (mBase == MAP_FAILED) { ALOGE("cannot map BpMemoryHeap (binder=%p), size=%zd, fd=%d (%s)", - asBinder().get(), size, fd, strerror(errno)); + IInterface::asBinder(this).get(), size, fd, strerror(errno)); close(fd); } else { mSize = size; diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index dd04dcf..9f68aa8 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -29,21 +29,14 @@ #include <private/binder/binder_module.h> #include <private/binder/Static.h> -#include <sys/ioctl.h> -#include <signal.h> #include <errno.h> -#include <stdio.h> -#include <unistd.h> - -#ifdef HAVE_PTHREADS #include <pthread.h> #include <sched.h> +#include <signal.h> +#include <stdio.h> +#include <sys/ioctl.h> #include <sys/resource.h> -#endif -#ifdef HAVE_WIN32_THREADS -#include <windows.h> -#endif - +#include <unistd.h> #if LOG_NDEBUG @@ -70,13 +63,11 @@ namespace android { static const char* getReturnString(size_t idx); -static const char* getCommandString(size_t idx); static const void* printReturnCommand(TextOutput& out, const void* _cmd); static const void* printCommand(TextOutput& out, const void* _cmd); -// This will result in a missing symbol failure if the IF_LOG_COMMANDS() -// conditionals don't get stripped... but that is probably what we want. -#if !LOG_NDEBUG +// Static const and functions will be optimized out if not used, +// when LOG_NDEBUG and references in IF_LOG_COMMANDS() are optimized out. static const char *kReturnStrings[] = { "BR_ERROR", "BR_OK", @@ -126,14 +117,6 @@ static const char* getReturnString(size_t idx) return "unknown"; } -static const char* getCommandString(size_t idx) -{ - if (idx < sizeof(kCommandStrings) / sizeof(kCommandStrings[0])) - return kCommandStrings[idx]; - else - return "unknown"; -} - static const void* printBinderTransactionData(TextOutput& out, const void* data) { const binder_transaction_data* btd = @@ -145,7 +128,7 @@ static const void* printBinderTransactionData(TextOutput& out, const void* data) out << "target.ptr=" << btd->target.ptr; } out << " (cookie " << btd->cookie << ")" << endl - << "code=" << TypeCode(btd->code) << ", flags=" << (void*)btd->flags << endl + << "code=" << TypeCode(btd->code) << ", flags=" << (void*)(long)btd->flags << endl << "data=" << btd->data.ptr.buffer << " (" << (void*)btd->data_size << " bytes)" << endl << "offsets=" << btd->data.ptr.offsets << " (" << (void*)btd->offsets_size @@ -157,10 +140,10 @@ static const void* printReturnCommand(TextOutput& out, const void* _cmd) { static const size_t N = sizeof(kReturnStrings)/sizeof(kReturnStrings[0]); const int32_t* cmd = (const int32_t*)_cmd; - int32_t code = *cmd++; + uint32_t code = (uint32_t)*cmd++; size_t cmdIndex = code & 0xff; - if (code == (int32_t) BR_ERROR) { - out << "BR_ERROR: " << (void*)(*cmd++) << endl; + if (code == BR_ERROR) { + out << "BR_ERROR: " << (void*)(long)(*cmd++) << endl; return cmd; } else if (cmdIndex >= N) { out << "Unknown reply: " << code << endl; @@ -187,21 +170,21 @@ static const void* printReturnCommand(TextOutput& out, const void* _cmd) case BR_DECREFS: { const int32_t b = *cmd++; const int32_t c = *cmd++; - out << ": target=" << (void*)b << " (cookie " << (void*)c << ")"; + out << ": target=" << (void*)(long)b << " (cookie " << (void*)(long)c << ")"; } break; case BR_ATTEMPT_ACQUIRE: { const int32_t p = *cmd++; const int32_t b = *cmd++; const int32_t c = *cmd++; - out << ": target=" << (void*)b << " (cookie " << (void*)c + out << ": target=" << (void*)(long)b << " (cookie " << (void*)(long)c << "), pri=" << p; } break; case BR_DEAD_BINDER: case BR_CLEAR_DEATH_NOTIFICATION_DONE: { const int32_t c = *cmd++; - out << ": death cookie " << (void*)c; + out << ": death cookie " << (void*)(long)c; } break; default: @@ -218,7 +201,7 @@ static const void* printCommand(TextOutput& out, const void* _cmd) { static const size_t N = sizeof(kCommandStrings)/sizeof(kCommandStrings[0]); const int32_t* cmd = (const int32_t*)_cmd; - int32_t code = *cmd++; + uint32_t code = (uint32_t)*cmd++; size_t cmdIndex = code & 0xff; if (cmdIndex >= N) { @@ -242,7 +225,7 @@ static const void* printCommand(TextOutput& out, const void* _cmd) case BC_FREE_BUFFER: { const int32_t buf = *cmd++; - out << ": buffer=" << (void*)buf; + out << ": buffer=" << (void*)(long)buf; } break; case BC_INCREFS: @@ -257,7 +240,7 @@ static const void* printCommand(TextOutput& out, const void* _cmd) case BC_ACQUIRE_DONE: { const int32_t b = *cmd++; const int32_t c = *cmd++; - out << ": target=" << (void*)b << " (cookie " << (void*)c << ")"; + out << ": target=" << (void*)(long)b << " (cookie " << (void*)(long)c << ")"; } break; case BC_ATTEMPT_ACQUIRE: { @@ -270,12 +253,12 @@ static const void* printCommand(TextOutput& out, const void* _cmd) case BC_CLEAR_DEATH_NOTIFICATION: { const int32_t h = *cmd++; const int32_t c = *cmd++; - out << ": handle=" << h << " (death cookie " << (void*)c << ")"; + out << ": handle=" << h << " (death cookie " << (void*)(long)c << ")"; } break; case BC_DEAD_BINDER_DONE: { const int32_t c = *cmd++; - out << ": death cookie " << (void*)c; + out << ": death cookie " << (void*)(long)c; } break; default: @@ -287,7 +270,6 @@ static const void* printCommand(TextOutput& out, const void* _cmd) out << endl; return cmd; } -#endif static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER; static bool gHaveTLS = false; @@ -361,12 +343,12 @@ status_t IPCThreadState::clearLastError() return err; } -int IPCThreadState::getCallingPid() const +pid_t IPCThreadState::getCallingPid() const { return mCallingPid; } -int IPCThreadState::getCallingUid() const +uid_t IPCThreadState::getCallingUid() const { return mCallingUid; } @@ -682,7 +664,7 @@ status_t IPCThreadState::clearDeathNotification(int32_t handle, BpBinder* proxy) IPCThreadState::IPCThreadState() : mProcess(ProcessState::self()), - mMyThreadId(androidGetTid()), + mMyThreadId(gettid()), mStrictModePolicy(0), mLastTransactionBinderFlags(0) { @@ -708,7 +690,7 @@ status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags) status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) { - int32_t cmd; + uint32_t cmd; int32_t err; while (1) { @@ -717,7 +699,7 @@ status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) if (err < NO_ERROR) break; if (mIn.dataAvail() == 0) continue; - cmd = mIn.readInt32(); + cmd = (uint32_t)mIn.readInt32(); IF_LOG_COMMANDS() { alog << "Processing waitForResponse Command: " @@ -947,7 +929,7 @@ status_t IPCThreadState::executeCommand(int32_t cmd) RefBase::weakref_type* refs; status_t result = NO_ERROR; - switch (cmd) { + switch ((uint32_t)cmd) { case BR_ERROR: result = mIn.readInt32(); break; diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index 7b1b0e7..3c716df 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -87,7 +87,7 @@ bool checkPermission(const String16& permission, pid_t pid, uid_t uid) } // Is this a permission failure, or did the controller go away? - if (pc->asBinder()->isBinderAlive()) { + if (IInterface::asBinder(pc)->isBinderAlive()) { ALOGW("Permission failure: %s from uid=%d pid=%d", String8(permission).string(), uid, pid); return false; diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 87ce5d0..d769caa 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -57,7 +57,7 @@ #define PAD_SIZE(s) (((s)+3)&~3) // Note: must be kept in sync with android/os/StrictMode.java's PENALTY_GATHER -#define STRICT_MODE_PENALTY_GATHER 0x100 +#define STRICT_MODE_PENALTY_GATHER (0x40 << 16) // Note: must be kept in sync with android/os/Parcel.java's EX_HAS_REPLY_HEADER #define EX_HAS_REPLY_HEADER -128 @@ -645,6 +645,12 @@ status_t Parcel::writeInt32(int32_t val) { return writeAligned(val); } + +status_t Parcel::writeUint32(uint32_t val) +{ + return writeAligned(val); +} + status_t Parcel::writeInt32Array(size_t len, const int32_t *val) { if (!val) { return writeAligned(-1); @@ -1033,6 +1039,15 @@ int32_t Parcel::readInt32() const return readAligned<int32_t>(); } +status_t Parcel::readUint32(uint32_t *pArg) const +{ + return readAligned(pArg); +} + +uint32_t Parcel::readUint32() const +{ + return readAligned<uint32_t>(); +} status_t Parcel::readInt64(int64_t *pArg) const { @@ -1442,7 +1457,7 @@ void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, for (size_t i = 0; i < mObjectsSize; i++) { binder_size_t offset = mObjects[i]; if (offset < minOffset) { - ALOGE("%s: bad object offset %"PRIu64" < %"PRIu64"\n", + ALOGE("%s: bad object offset %" PRIu64 " < %" PRIu64 "\n", __func__, (uint64_t)offset, (uint64_t)minOffset); mObjectsSize = 0; break; diff --git a/libs/binder/tests/Android.mk b/libs/binder/tests/Android.mk new file mode 100644 index 0000000..3668729 --- /dev/null +++ b/libs/binder/tests/Android.mk @@ -0,0 +1,34 @@ +# +# Copyright (C) 2014 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) +ifneq ($(TARGET_USES_64_BIT_BINDER),true) +ifneq ($(TARGET_IS_64_BIT),true) +LOCAL_CFLAGS += -DBINDER_IPC_32BIT=1 +endif +endif + +LOCAL_MODULE := binderDriverInterfaceTest +LOCAL_SRC_FILES := binderDriverInterfaceTest.cpp +include $(BUILD_NATIVE_TEST) + +include $(CLEAR_VARS) +LOCAL_MODULE := binderLibTest +LOCAL_SRC_FILES := binderLibTest.cpp +LOCAL_SHARED_LIBRARIES := libbinder libutils +include $(BUILD_NATIVE_TEST) diff --git a/libs/binder/tests/binderDriverInterfaceTest.cpp b/libs/binder/tests/binderDriverInterfaceTest.cpp new file mode 100644 index 0000000..315f349 --- /dev/null +++ b/libs/binder/tests/binderDriverInterfaceTest.cpp @@ -0,0 +1,353 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> + +#include <gtest/gtest.h> +#include <linux/binder.h> +#include <binder/IBinder.h> +#include <sys/mman.h> +#include <poll.h> + +#define BINDER_DEV_NAME "/dev/binder" + +testing::Environment* binder_env; + +class BinderDriverInterfaceTestEnv : public ::testing::Environment { + virtual void SetUp() { + int ret; + uint32_t max_threads = 0; + + m_binderFd = open(BINDER_DEV_NAME, O_RDWR | O_NONBLOCK); + ASSERT_GE(m_binderFd, 0); + m_buffer = mmap(NULL, 64*1024, PROT_READ, MAP_SHARED, m_binderFd, 0); + ASSERT_NE(m_buffer, (void *)NULL); + ret = ioctl(m_binderFd, BINDER_SET_MAX_THREADS, &max_threads); + EXPECT_EQ(0, ret); + EnterLooper(); + } + virtual void TearDown() { + close(m_binderFd); + } + private: + int m_binderFd; + void *m_buffer; + public: + int getBinderFd(void) { + return m_binderFd; + } + void EnterLooper(void) { + int ret; + const uint32_t bc[] = { + BC_ENTER_LOOPER, + }; + struct binder_write_read bwr = binder_write_read(); + bwr.write_buffer = (uintptr_t)bc; + bwr.write_size = sizeof(bc); + ret = ioctl(m_binderFd, BINDER_WRITE_READ, &bwr); + EXPECT_EQ(0, ret); + if (ret < 0) { + EXPECT_EQ(0, errno); + } + EXPECT_EQ(sizeof(bc), bwr.write_consumed); + } +}; + +class BinderDriverInterfaceTest : public ::testing::Test { + public: + virtual void SetUp() { + m_binderFd = static_cast<BinderDriverInterfaceTestEnv *>(binder_env)->getBinderFd(); + } + virtual void TearDown() { + } + protected: + void binderTestIoctlRetErr2(int cmd, void *arg, int expect_ret, int expect_errno, int accept_errno) { + int ret; + + ret = ioctl(m_binderFd, cmd, arg); + EXPECT_EQ(expect_ret, ret); + if (ret < 0) { + if (errno != accept_errno) + EXPECT_EQ(expect_errno, errno); + } + } + void binderTestIoctlErr2(int cmd, void *arg, int expect_errno, int accept_errno) { + binderTestIoctlRetErr2(cmd, arg, -1, expect_errno, accept_errno); + } + void binderTestIoctlErr1(int cmd, void *arg, int expect_errno) { + binderTestIoctlErr2(cmd, arg, expect_errno, expect_errno); + } + void binderTestIoctl(int cmd, void *arg) { + binderTestIoctlRetErr2(cmd, arg, 0, 0, 0); + } + void binderTestIoctlUnimplemented(int cmd, void *arg) { + int ret; + + ret = ioctl(m_binderFd, cmd, arg); + if (ret < 0) { + /* Not currently implmented. Allow ret == -1, errno == EINVAL */ + EXPECT_EQ(-1, ret); + EXPECT_EQ(EINVAL, errno); + } + } + void binderTestReadEmpty(void) { + size_t i; + uint32_t br[32]; + struct binder_write_read bwr = binder_write_read(); + SCOPED_TRACE("TestReadEmpty"); + bwr.read_buffer = (uintptr_t)br; + bwr.read_size = sizeof(br); + binderTestIoctlErr1(BINDER_WRITE_READ, &bwr, EAGAIN); + EXPECT_EQ(0u, bwr.read_consumed); + for (i = 0; i * sizeof(uint32_t) < bwr.read_consumed; i++) { + SCOPED_TRACE(testing::Message() << "i = " << i); + EXPECT_EQ(BR_NOOP, br[i]); + } + } + void binderWaitForReadData(int timeout_ms) { + int ret; + pollfd pfd = pollfd(); + + pfd.fd = m_binderFd; + pfd.events = POLLIN; + ret = poll(&pfd, 1, timeout_ms); + EXPECT_EQ(1, ret); + } + private: + int m_binderFd; +}; + +TEST_F(BinderDriverInterfaceTest, Version) { + struct binder_version version; + binderTestIoctl(BINDER_VERSION, &version); + ASSERT_EQ(BINDER_CURRENT_PROTOCOL_VERSION, version.protocol_version); +} + +TEST_F(BinderDriverInterfaceTest, WriteReadNull) { + binderTestIoctlErr1(BINDER_WRITE_READ, NULL, EFAULT); +} + +TEST_F(BinderDriverInterfaceTest, SetIdleTimeoutNull) { + binderTestIoctlErr2(BINDER_SET_IDLE_TIMEOUT, NULL, EFAULT, EINVAL); +} + +TEST_F(BinderDriverInterfaceTest, SetMaxThreadsNull) { + binderTestIoctlErr2(BINDER_SET_MAX_THREADS, NULL, EFAULT, EINVAL); /* TODO: don't accept EINVAL */ +} + +TEST_F(BinderDriverInterfaceTest, SetIdlePriorityNull) { + binderTestIoctlErr2(BINDER_SET_IDLE_PRIORITY, NULL, EFAULT, EINVAL); +} + +TEST_F(BinderDriverInterfaceTest, VersionNull) { + binderTestIoctlErr2(BINDER_VERSION, NULL, EFAULT, EINVAL); /* TODO: don't accept EINVAL */ +} + +TEST_F(BinderDriverInterfaceTest, SetIdleTimeoutNoTest) { + int64_t idle_timeout = 100000; + binderTestIoctlUnimplemented(BINDER_SET_IDLE_TIMEOUT, &idle_timeout); +} + +TEST_F(BinderDriverInterfaceTest, SetMaxThreads) { + uint32_t max_threads = 0; + binderTestIoctl(BINDER_SET_MAX_THREADS, &max_threads); +} + +TEST_F(BinderDriverInterfaceTest, SetIdlePriorityNoTest) { + int idle_priority = 0; + binderTestIoctlUnimplemented(BINDER_SET_IDLE_PRIORITY, &idle_priority); +} + +TEST_F(BinderDriverInterfaceTest, SetContextMgrBusy) { + int32_t dummy = 0; + binderTestIoctlErr1(BINDER_SET_CONTEXT_MGR, &dummy, EBUSY); +} + +TEST_F(BinderDriverInterfaceTest, ThreadExit) { + int32_t dummy = 0; + binderTestIoctl(BINDER_THREAD_EXIT, &dummy); + static_cast<BinderDriverInterfaceTestEnv *>(binder_env)->EnterLooper(); +} + +TEST_F(BinderDriverInterfaceTest, WriteReadEmpty) { + struct binder_write_read bwr = binder_write_read(); + binderTestIoctl(BINDER_WRITE_READ, &bwr); +} + +TEST_F(BinderDriverInterfaceTest, Read) { + binderTestReadEmpty(); +} + +TEST_F(BinderDriverInterfaceTest, IncRefsAcquireReleaseDecRefs) { + const uint32_t bc[] = { + BC_INCREFS, + 0, + BC_ACQUIRE, + 0, + BC_RELEASE, + 0, + BC_DECREFS, + 0, + }; + struct binder_write_read bwr = binder_write_read(); + bwr.write_buffer = (uintptr_t)bc; + bwr.write_size = sizeof(bc); + binderTestIoctl(BINDER_WRITE_READ, &bwr); + EXPECT_EQ(sizeof(bc), bwr.write_consumed); + binderTestReadEmpty(); +} + +TEST_F(BinderDriverInterfaceTest, Transaction) { + binder_uintptr_t cookie = 1234; + struct { + uint32_t cmd1; + struct binder_transaction_data arg1; + } __attribute__((packed)) bc1 = { + .cmd1 = BC_TRANSACTION, + .arg1 = { + .target = { 0 }, + .cookie = 0, + .code = android::IBinder::PING_TRANSACTION, + .flags = 0, + .sender_pid = 0, + .sender_euid = 0, + .data_size = 0, + .offsets_size = 0, + .data = {0, 0}, + }, + }; + struct { + uint32_t cmd0; + uint32_t cmd1; + uint32_t cmd2; + binder_transaction_data arg2; + uint32_t pad[16]; + } __attribute__((packed)) br; + struct binder_write_read bwr = binder_write_read(); + + bwr.write_buffer = (uintptr_t)&bc1; + bwr.write_size = sizeof(bc1); + bwr.read_buffer = (uintptr_t)&br; + bwr.read_size = sizeof(br); + + { + SCOPED_TRACE("1st WriteRead"); + binderTestIoctl(BINDER_WRITE_READ, &bwr); + } + EXPECT_EQ(sizeof(bc1), bwr.write_consumed); + if (bwr.read_consumed < offsetof(typeof(br), pad)) { + SCOPED_TRACE("2nd WriteRead"); + binderWaitForReadData(10000); + binderTestIoctl(BINDER_WRITE_READ, &bwr); + } + EXPECT_EQ(offsetof(typeof(br), pad), bwr.read_consumed); + if (bwr.read_consumed > offsetof(typeof(br), cmd0)) + EXPECT_EQ(BR_NOOP, br.cmd0); + if (bwr.read_consumed > offsetof(typeof(br), cmd1)) + EXPECT_EQ(BR_TRANSACTION_COMPLETE, br.cmd1); + if (bwr.read_consumed > offsetof(typeof(br), cmd2)) + EXPECT_EQ(BR_REPLY, br.cmd2); + if (bwr.read_consumed >= offsetof(typeof(br), pad)) { + EXPECT_EQ(0u, br.arg2.target.ptr); + EXPECT_EQ(0u, br.arg2.cookie); + EXPECT_EQ(0u, br.arg2.code); + EXPECT_EQ(0u, br.arg2.flags); + EXPECT_EQ(0u, br.arg2.data_size); + EXPECT_EQ(0u, br.arg2.offsets_size); + + SCOPED_TRACE("3rd WriteRead"); + + binderTestReadEmpty(); + + struct { + uint32_t cmd1; + binder_uintptr_t arg1; + } __attribute__((packed)) bc2 = { + .cmd1 = BC_FREE_BUFFER, + .arg1 = br.arg2.data.ptr.buffer, + }; + + bwr.write_buffer = (uintptr_t)&bc2; + bwr.write_size = sizeof(bc2); + bwr.write_consumed = 0; + bwr.read_size = 0; + + binderTestIoctl(BINDER_WRITE_READ, &bwr); + EXPECT_EQ(sizeof(bc2), bwr.write_consumed); + } + binderTestReadEmpty(); +} + +TEST_F(BinderDriverInterfaceTest, RequestDeathNotification) { + binder_uintptr_t cookie = 1234; + struct { + uint32_t cmd0; + uint32_t arg0; + uint32_t cmd1; + struct binder_handle_cookie arg1; + uint32_t cmd2; + struct binder_handle_cookie arg2; + uint32_t cmd3; + uint32_t arg3; + } __attribute__((packed)) bc = { + .cmd0 = BC_INCREFS, + .arg0 = 0, + .cmd1 = BC_REQUEST_DEATH_NOTIFICATION, + .arg1 = { + .handle = 0, + .cookie = cookie, + }, + .cmd2 = BC_CLEAR_DEATH_NOTIFICATION, + .arg2 = { + .handle = 0, + .cookie = cookie, + }, + .cmd3 = BC_DECREFS, + .arg3 = 0, + }; + struct { + uint32_t cmd0; + uint32_t cmd1; + binder_uintptr_t arg1; + uint32_t pad[16]; + } __attribute__((packed)) br; + struct binder_write_read bwr = binder_write_read(); + + bwr.write_buffer = (uintptr_t)&bc; + bwr.write_size = sizeof(bc); + bwr.read_buffer = (uintptr_t)&br; + bwr.read_size = sizeof(br); + + binderTestIoctl(BINDER_WRITE_READ, &bwr); + EXPECT_EQ(sizeof(bc), bwr.write_consumed); + EXPECT_EQ(sizeof(br) - sizeof(br.pad), bwr.read_consumed); + EXPECT_EQ(BR_NOOP, br.cmd0); + EXPECT_EQ(BR_CLEAR_DEATH_NOTIFICATION_DONE, br.cmd1); + EXPECT_EQ(cookie, br.arg1); + binderTestReadEmpty(); +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + + binder_env = AddGlobalTestEnvironment(new BinderDriverInterfaceTestEnv()); + + return RUN_ALL_TESTS(); +} + diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp new file mode 100644 index 0000000..3df3acf --- /dev/null +++ b/libs/binder/tests/binderLibTest.cpp @@ -0,0 +1,954 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <errno.h> +#include <fcntl.h> +#include <poll.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> + +#include <gtest/gtest.h> + +#include <binder/Binder.h> +#include <binder/IBinder.h> +#include <binder/IPCThreadState.h> +#include <binder/IServiceManager.h> + +#define ARRAY_SIZE(array) (sizeof array / sizeof array[0]) + +using namespace android; + +static testing::Environment* binder_env; +static char *binderservername; +static char binderserverarg[] = "--binderserver"; + +static String16 binderLibTestServiceName = String16("test.binderLib"); + +enum BinderLibTestTranscationCode { + BINDER_LIB_TEST_NOP_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, + BINDER_LIB_TEST_REGISTER_SERVER, + BINDER_LIB_TEST_ADD_SERVER, + BINDER_LIB_TEST_CALL_BACK, + BINDER_LIB_TEST_NOP_CALL_BACK, + BINDER_LIB_TEST_GET_ID_TRANSACTION, + BINDER_LIB_TEST_INDIRECT_TRANSACTION, + BINDER_LIB_TEST_SET_ERROR_TRANSACTION, + BINDER_LIB_TEST_GET_STATUS_TRANSACTION, + BINDER_LIB_TEST_ADD_STRONG_REF_TRANSACTION, + BINDER_LIB_TEST_LINK_DEATH_TRANSACTION, + BINDER_LIB_TEST_WRITE_FILE_TRANSACTION, + BINDER_LIB_TEST_PROMOTE_WEAK_REF_TRANSACTION, + BINDER_LIB_TEST_EXIT_TRANSACTION, + BINDER_LIB_TEST_DELAYED_EXIT_TRANSACTION, + BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION, +}; + +pid_t start_server_process(int arg2) +{ + int ret; + pid_t pid; + status_t status; + int pipefd[2]; + char stri[16]; + char strpipefd1[16]; + char *childargv[] = { + binderservername, + binderserverarg, + stri, + strpipefd1, + NULL + }; + + ret = pipe(pipefd); + if (ret < 0) + return ret; + + snprintf(stri, sizeof(stri), "%d", arg2); + snprintf(strpipefd1, sizeof(strpipefd1), "%d", pipefd[1]); + + pid = fork(); + if (pid == -1) + return pid; + if (pid == 0) { + close(pipefd[0]); + execv(binderservername, childargv); + status = -errno; + write(pipefd[1], &status, sizeof(status)); + fprintf(stderr, "execv failed, %s\n", strerror(errno)); + _exit(EXIT_FAILURE); + } + close(pipefd[1]); + ret = read(pipefd[0], &status, sizeof(status)); + //printf("pipe read returned %d, status %d\n", ret, status); + close(pipefd[0]); + if (ret == sizeof(status)) { + ret = status; + } else { + kill(pid, SIGKILL); + if (ret >= 0) { + ret = NO_INIT; + } + } + if (ret < 0) { + wait(NULL); + return ret; + } + return pid; +} + +class BinderLibTestEnv : public ::testing::Environment { + public: + BinderLibTestEnv() {} + sp<IBinder> getServer(void) { + return m_server; + } + + private: + virtual void SetUp() { + m_serverpid = start_server_process(0); + //printf("m_serverpid %d\n", m_serverpid); + ASSERT_GT(m_serverpid, 0); + + sp<IServiceManager> sm = defaultServiceManager(); + //printf("%s: pid %d, get service\n", __func__, m_pid); + m_server = sm->getService(binderLibTestServiceName); + ASSERT_TRUE(m_server != NULL); + //printf("%s: pid %d, get service done\n", __func__, m_pid); + } + virtual void TearDown() { + status_t ret; + Parcel data, reply; + int exitStatus; + pid_t pid; + + //printf("%s: pid %d\n", __func__, m_pid); + if (m_server != NULL) { + ret = m_server->transact(BINDER_LIB_TEST_GET_STATUS_TRANSACTION, data, &reply); + EXPECT_EQ(0, ret); + ret = m_server->transact(BINDER_LIB_TEST_EXIT_TRANSACTION, data, &reply, TF_ONE_WAY); + EXPECT_EQ(0, ret); + } + if (m_serverpid > 0) { + //printf("wait for %d\n", m_pids[i]); + pid = wait(&exitStatus); + EXPECT_EQ(m_serverpid, pid); + EXPECT_TRUE(WIFEXITED(exitStatus)); + EXPECT_EQ(0, WEXITSTATUS(exitStatus)); + } + } + + pid_t m_serverpid; + sp<IBinder> m_server; +}; + +class BinderLibTest : public ::testing::Test { + public: + virtual void SetUp() { + m_server = static_cast<BinderLibTestEnv *>(binder_env)->getServer(); + } + virtual void TearDown() { + } + protected: + sp<IBinder> addServer(int32_t *idPtr = NULL) + { + int ret; + int32_t id; + Parcel data, reply; + sp<IBinder> binder; + + ret = m_server->transact(BINDER_LIB_TEST_ADD_SERVER, data, &reply); + EXPECT_EQ(NO_ERROR, ret); + + EXPECT_FALSE(binder != NULL); + binder = reply.readStrongBinder(); + EXPECT_TRUE(binder != NULL); + ret = reply.readInt32(&id); + EXPECT_EQ(NO_ERROR, ret); + if (idPtr) + *idPtr = id; + return binder; + } + void waitForReadData(int fd, int timeout_ms) { + int ret; + pollfd pfd = pollfd(); + + pfd.fd = fd; + pfd.events = POLLIN; + ret = poll(&pfd, 1, timeout_ms); + EXPECT_EQ(1, ret); + } + + sp<IBinder> m_server; +}; + +class BinderLibTestBundle : public Parcel +{ + public: + BinderLibTestBundle(void) {} + BinderLibTestBundle(const Parcel *source) : m_isValid(false) { + int32_t mark; + int32_t bundleLen; + size_t pos; + + if (source->readInt32(&mark)) + return; + if (mark != MARK_START) + return; + if (source->readInt32(&bundleLen)) + return; + pos = source->dataPosition(); + if (Parcel::appendFrom(source, pos, bundleLen)) + return; + source->setDataPosition(pos + bundleLen); + if (source->readInt32(&mark)) + return; + if (mark != MARK_END) + return; + m_isValid = true; + setDataPosition(0); + } + void appendTo(Parcel *dest) { + dest->writeInt32(MARK_START); + dest->writeInt32(dataSize()); + dest->appendFrom(this, 0, dataSize()); + dest->writeInt32(MARK_END); + }; + bool isValid(void) { + return m_isValid; + } + private: + enum { + MARK_START = B_PACK_CHARS('B','T','B','S'), + MARK_END = B_PACK_CHARS('B','T','B','E'), + }; + bool m_isValid; +}; + +class BinderLibTestEvent +{ + public: + BinderLibTestEvent(void) + : m_eventTriggered(false) + { + pthread_mutex_init(&m_waitMutex, NULL); + pthread_cond_init(&m_waitCond, NULL); + } + int waitEvent(int timeout_s) + { + int ret; + pthread_mutex_lock(&m_waitMutex); + if (!m_eventTriggered) { +#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE) + pthread_cond_timeout_np(&m_waitCond, &m_waitMutex, timeout_s * 1000); +#else + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += timeout_s; + pthread_cond_timedwait(&m_waitCond, &m_waitMutex, &ts); +#endif + } + ret = m_eventTriggered ? NO_ERROR : TIMED_OUT; + pthread_mutex_unlock(&m_waitMutex); + return ret; + } + protected: + void triggerEvent(void) { + pthread_mutex_lock(&m_waitMutex); + pthread_cond_signal(&m_waitCond); + m_eventTriggered = true; + pthread_mutex_unlock(&m_waitMutex); + }; + private: + pthread_mutex_t m_waitMutex; + pthread_cond_t m_waitCond; + bool m_eventTriggered; +}; + +class BinderLibTestCallBack : public BBinder, public BinderLibTestEvent +{ + public: + BinderLibTestCallBack() + : m_result(NOT_ENOUGH_DATA) + { + } + status_t getResult(void) + { + return m_result; + } + + private: + virtual status_t onTransact(uint32_t code, + const Parcel& data, Parcel* reply, + uint32_t flags = 0) + { + (void)reply; + (void)flags; + switch(code) { + case BINDER_LIB_TEST_CALL_BACK: + m_result = data.readInt32(); + triggerEvent(); + return NO_ERROR; + default: + return UNKNOWN_TRANSACTION; + } + } + + status_t m_result; +}; + +class TestDeathRecipient : public IBinder::DeathRecipient, public BinderLibTestEvent +{ + private: + virtual void binderDied(const wp<IBinder>& who) { + (void)who; + triggerEvent(); + }; +}; + +TEST_F(BinderLibTest, NopTransaction) { + status_t ret; + Parcel data, reply; + ret = m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply); + EXPECT_EQ(NO_ERROR, ret); +} + +TEST_F(BinderLibTest, SetError) { + int32_t testValue[] = { 0, -123, 123 }; + for (size_t i = 0; i < ARRAY_SIZE(testValue); i++) { + status_t ret; + Parcel data, reply; + data.writeInt32(testValue[i]); + ret = m_server->transact(BINDER_LIB_TEST_SET_ERROR_TRANSACTION, data, &reply); + EXPECT_EQ(testValue[i], ret); + } +} + +TEST_F(BinderLibTest, GetId) { + status_t ret; + int32_t id; + Parcel data, reply; + ret = m_server->transact(BINDER_LIB_TEST_GET_ID_TRANSACTION, data, &reply); + EXPECT_EQ(NO_ERROR, ret); + ret = reply.readInt32(&id); + EXPECT_EQ(NO_ERROR, ret); + EXPECT_EQ(0, id); +} + +TEST_F(BinderLibTest, PtrSize) { + status_t ret; + int32_t ptrsize; + Parcel data, reply; + sp<IBinder> server = addServer(); + ASSERT_TRUE(server != NULL); + ret = server->transact(BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION, data, &reply); + EXPECT_EQ(NO_ERROR, ret); + ret = reply.readInt32(&ptrsize); + EXPECT_EQ(NO_ERROR, ret); + RecordProperty("TestPtrSize", sizeof(void *)); + RecordProperty("ServerPtrSize", sizeof(void *)); +} + +TEST_F(BinderLibTest, IndirectGetId2) +{ + status_t ret; + int32_t id; + int32_t count; + Parcel data, reply; + int32_t serverId[3]; + + data.writeInt32(ARRAY_SIZE(serverId)); + for (size_t i = 0; i < ARRAY_SIZE(serverId); i++) { + sp<IBinder> server; + BinderLibTestBundle datai; + + server = addServer(&serverId[i]); + ASSERT_TRUE(server != NULL); + data.writeStrongBinder(server); + data.writeInt32(BINDER_LIB_TEST_GET_ID_TRANSACTION); + datai.appendTo(&data); + } + + ret = m_server->transact(BINDER_LIB_TEST_INDIRECT_TRANSACTION, data, &reply); + ASSERT_EQ(NO_ERROR, ret); + + ret = reply.readInt32(&id); + ASSERT_EQ(NO_ERROR, ret); + EXPECT_EQ(0, id); + + ret = reply.readInt32(&count); + ASSERT_EQ(NO_ERROR, ret); + EXPECT_EQ(ARRAY_SIZE(serverId), count); + + for (size_t i = 0; i < (size_t)count; i++) { + BinderLibTestBundle replyi(&reply); + EXPECT_TRUE(replyi.isValid()); + ret = replyi.readInt32(&id); + EXPECT_EQ(NO_ERROR, ret); + EXPECT_EQ(serverId[i], id); + EXPECT_EQ(replyi.dataSize(), replyi.dataPosition()); + } + + EXPECT_EQ(reply.dataSize(), reply.dataPosition()); +} + +TEST_F(BinderLibTest, IndirectGetId3) +{ + status_t ret; + int32_t id; + int32_t count; + Parcel data, reply; + int32_t serverId[3]; + + data.writeInt32(ARRAY_SIZE(serverId)); + for (size_t i = 0; i < ARRAY_SIZE(serverId); i++) { + sp<IBinder> server; + BinderLibTestBundle datai; + BinderLibTestBundle datai2; + + server = addServer(&serverId[i]); + ASSERT_TRUE(server != NULL); + data.writeStrongBinder(server); + data.writeInt32(BINDER_LIB_TEST_INDIRECT_TRANSACTION); + + datai.writeInt32(1); + datai.writeStrongBinder(m_server); + datai.writeInt32(BINDER_LIB_TEST_GET_ID_TRANSACTION); + datai2.appendTo(&datai); + + datai.appendTo(&data); + } + + ret = m_server->transact(BINDER_LIB_TEST_INDIRECT_TRANSACTION, data, &reply); + ASSERT_EQ(NO_ERROR, ret); + + ret = reply.readInt32(&id); + ASSERT_EQ(NO_ERROR, ret); + EXPECT_EQ(0, id); + + ret = reply.readInt32(&count); + ASSERT_EQ(NO_ERROR, ret); + EXPECT_EQ(ARRAY_SIZE(serverId), count); + + for (size_t i = 0; i < (size_t)count; i++) { + int32_t counti; + + BinderLibTestBundle replyi(&reply); + EXPECT_TRUE(replyi.isValid()); + ret = replyi.readInt32(&id); + EXPECT_EQ(NO_ERROR, ret); + EXPECT_EQ(serverId[i], id); + + ret = replyi.readInt32(&counti); + ASSERT_EQ(NO_ERROR, ret); + EXPECT_EQ(1, counti); + + BinderLibTestBundle replyi2(&replyi); + EXPECT_TRUE(replyi2.isValid()); + ret = replyi2.readInt32(&id); + EXPECT_EQ(NO_ERROR, ret); + EXPECT_EQ(0, id); + EXPECT_EQ(replyi2.dataSize(), replyi2.dataPosition()); + + EXPECT_EQ(replyi.dataSize(), replyi.dataPosition()); + } + + EXPECT_EQ(reply.dataSize(), reply.dataPosition()); +} + +TEST_F(BinderLibTest, CallBack) +{ + status_t ret; + Parcel data, reply; + sp<BinderLibTestCallBack> callBack = new BinderLibTestCallBack(); + data.writeStrongBinder(callBack); + ret = m_server->transact(BINDER_LIB_TEST_NOP_CALL_BACK, data, &reply, TF_ONE_WAY); + EXPECT_EQ(NO_ERROR, ret); + ret = callBack->waitEvent(5); + EXPECT_EQ(NO_ERROR, ret); + ret = callBack->getResult(); + EXPECT_EQ(NO_ERROR, ret); +} + +TEST_F(BinderLibTest, AddServer) +{ + sp<IBinder> server = addServer(); + ASSERT_TRUE(server != NULL); +} + +TEST_F(BinderLibTest, DeathNotificationNoRefs) +{ + status_t ret; + + sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient(); + + { + sp<IBinder> binder = addServer(); + ASSERT_TRUE(binder != NULL); + ret = binder->linkToDeath(testDeathRecipient); + EXPECT_EQ(NO_ERROR, ret); + } + IPCThreadState::self()->flushCommands(); + ret = testDeathRecipient->waitEvent(5); + EXPECT_EQ(NO_ERROR, ret); +#if 0 /* Is there an unlink api that does not require a strong reference? */ + ret = binder->unlinkToDeath(testDeathRecipient); + EXPECT_EQ(NO_ERROR, ret); +#endif +} + +TEST_F(BinderLibTest, DeathNotificationWeakRef) +{ + status_t ret; + wp<IBinder> wbinder; + + sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient(); + + { + sp<IBinder> binder = addServer(); + ASSERT_TRUE(binder != NULL); + ret = binder->linkToDeath(testDeathRecipient); + EXPECT_EQ(NO_ERROR, ret); + wbinder = binder; + } + IPCThreadState::self()->flushCommands(); + ret = testDeathRecipient->waitEvent(5); + EXPECT_EQ(NO_ERROR, ret); +#if 0 /* Is there an unlink api that does not require a strong reference? */ + ret = binder->unlinkToDeath(testDeathRecipient); + EXPECT_EQ(NO_ERROR, ret); +#endif +} + +TEST_F(BinderLibTest, DeathNotificationStrongRef) +{ + status_t ret; + sp<IBinder> sbinder; + + sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient(); + + { + sp<IBinder> binder = addServer(); + ASSERT_TRUE(binder != NULL); + ret = binder->linkToDeath(testDeathRecipient); + EXPECT_EQ(NO_ERROR, ret); + sbinder = binder; + } + { + Parcel data, reply; + ret = sbinder->transact(BINDER_LIB_TEST_EXIT_TRANSACTION, data, &reply, TF_ONE_WAY); + EXPECT_EQ(0, ret); + } + IPCThreadState::self()->flushCommands(); + ret = testDeathRecipient->waitEvent(5); + EXPECT_EQ(NO_ERROR, ret); + ret = sbinder->unlinkToDeath(testDeathRecipient); + EXPECT_EQ(DEAD_OBJECT, ret); +} + +TEST_F(BinderLibTest, DeathNotificationMultiple) +{ + status_t ret; + const int clientcount = 2; + sp<IBinder> target; + sp<IBinder> linkedclient[clientcount]; + sp<BinderLibTestCallBack> callBack[clientcount]; + sp<IBinder> passiveclient[clientcount]; + + target = addServer(); + ASSERT_TRUE(target != NULL); + for (int i = 0; i < clientcount; i++) { + { + Parcel data, reply; + + linkedclient[i] = addServer(); + ASSERT_TRUE(linkedclient[i] != NULL); + callBack[i] = new BinderLibTestCallBack(); + data.writeStrongBinder(target); + data.writeStrongBinder(callBack[i]); + ret = linkedclient[i]->transact(BINDER_LIB_TEST_LINK_DEATH_TRANSACTION, data, &reply, TF_ONE_WAY); + EXPECT_EQ(NO_ERROR, ret); + } + { + Parcel data, reply; + + passiveclient[i] = addServer(); + ASSERT_TRUE(passiveclient[i] != NULL); + data.writeStrongBinder(target); + ret = passiveclient[i]->transact(BINDER_LIB_TEST_ADD_STRONG_REF_TRANSACTION, data, &reply, TF_ONE_WAY); + EXPECT_EQ(NO_ERROR, ret); + } + } + { + Parcel data, reply; + ret = target->transact(BINDER_LIB_TEST_EXIT_TRANSACTION, data, &reply, TF_ONE_WAY); + EXPECT_EQ(0, ret); + } + + for (int i = 0; i < clientcount; i++) { + ret = callBack[i]->waitEvent(5); + EXPECT_EQ(NO_ERROR, ret); + ret = callBack[i]->getResult(); + EXPECT_EQ(NO_ERROR, ret); + } +} + +TEST_F(BinderLibTest, PassFile) { + int ret; + int pipefd[2]; + uint8_t buf[1] = { 0 }; + uint8_t write_value = 123; + + ret = pipe2(pipefd, O_NONBLOCK); + ASSERT_EQ(0, ret); + + { + Parcel data, reply; + uint8_t writebuf[1] = { write_value }; + + ret = data.writeFileDescriptor(pipefd[1], true); + EXPECT_EQ(NO_ERROR, ret); + + ret = data.writeInt32(sizeof(writebuf)); + EXPECT_EQ(NO_ERROR, ret); + + ret = data.write(writebuf, sizeof(writebuf)); + EXPECT_EQ(NO_ERROR, ret); + + ret = m_server->transact(BINDER_LIB_TEST_WRITE_FILE_TRANSACTION, data, &reply); + EXPECT_EQ(NO_ERROR, ret); + } + + ret = read(pipefd[0], buf, sizeof(buf)); + EXPECT_EQ(sizeof(buf), ret); + EXPECT_EQ(write_value, buf[0]); + + waitForReadData(pipefd[0], 5000); /* wait for other proccess to close pipe */ + + ret = read(pipefd[0], buf, sizeof(buf)); + EXPECT_EQ(0, ret); + + close(pipefd[0]); +} + +TEST_F(BinderLibTest, PromoteLocal) { + sp<IBinder> strong = new BBinder(); + wp<IBinder> weak = strong; + sp<IBinder> strong_from_weak = weak.promote(); + EXPECT_TRUE(strong != NULL); + EXPECT_EQ(strong, strong_from_weak); + strong = NULL; + strong_from_weak = NULL; + strong_from_weak = weak.promote(); + EXPECT_TRUE(strong_from_weak == NULL); +} + +TEST_F(BinderLibTest, PromoteRemote) { + int ret; + Parcel data, reply; + sp<IBinder> strong = new BBinder(); + sp<IBinder> server = addServer(); + + ASSERT_TRUE(server != NULL); + ASSERT_TRUE(strong != NULL); + + ret = data.writeWeakBinder(strong); + EXPECT_EQ(NO_ERROR, ret); + + ret = server->transact(BINDER_LIB_TEST_PROMOTE_WEAK_REF_TRANSACTION, data, &reply); + EXPECT_GE(ret, 0); +} + +class BinderLibTestService : public BBinder +{ + public: + BinderLibTestService(int32_t id) + : m_id(id) + , m_nextServerId(id + 1) + , m_serverStartRequested(false) + { + pthread_mutex_init(&m_serverWaitMutex, NULL); + pthread_cond_init(&m_serverWaitCond, NULL); + } + ~BinderLibTestService() + { + exit(EXIT_SUCCESS); + } + virtual status_t onTransact(uint32_t code, + const Parcel& data, Parcel* reply, + uint32_t flags = 0) { + //printf("%s: code %d\n", __func__, code); + (void)flags; + + if (getuid() != (uid_t)IPCThreadState::self()->getCallingUid()) { + return PERMISSION_DENIED; + } + switch (code) { + case BINDER_LIB_TEST_REGISTER_SERVER: { + int32_t id; + sp<IBinder> binder; + id = data.readInt32(); + binder = data.readStrongBinder(); + if (binder == NULL) { + return BAD_VALUE; + } + + if (m_id != 0) + return INVALID_OPERATION; + + pthread_mutex_lock(&m_serverWaitMutex); + if (m_serverStartRequested) { + m_serverStartRequested = false; + m_serverStarted = binder; + pthread_cond_signal(&m_serverWaitCond); + } + pthread_mutex_unlock(&m_serverWaitMutex); + return NO_ERROR; + } + case BINDER_LIB_TEST_ADD_SERVER: { + int ret; + uint8_t buf[1] = { 0 }; + int serverid; + + if (m_id != 0) { + return INVALID_OPERATION; + } + pthread_mutex_lock(&m_serverWaitMutex); + if (m_serverStartRequested) { + ret = -EBUSY; + } else { + serverid = m_nextServerId++; + m_serverStartRequested = true; + + pthread_mutex_unlock(&m_serverWaitMutex); + ret = start_server_process(serverid); + pthread_mutex_lock(&m_serverWaitMutex); + } + if (ret > 0) { + if (m_serverStartRequested) { +#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE) + ret = pthread_cond_timeout_np(&m_serverWaitCond, &m_serverWaitMutex, 5000); +#else + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 5; + ret = pthread_cond_timedwait(&m_serverWaitCond, &m_serverWaitMutex, &ts); +#endif + } + if (m_serverStartRequested) { + m_serverStartRequested = false; + ret = -ETIMEDOUT; + } else { + reply->writeStrongBinder(m_serverStarted); + reply->writeInt32(serverid); + m_serverStarted = NULL; + ret = NO_ERROR; + } + } else if (ret >= 0) { + m_serverStartRequested = false; + ret = UNKNOWN_ERROR; + } + pthread_mutex_unlock(&m_serverWaitMutex); + return ret; + } + case BINDER_LIB_TEST_NOP_TRANSACTION: + return NO_ERROR; + case BINDER_LIB_TEST_NOP_CALL_BACK: { + Parcel data2, reply2; + sp<IBinder> binder; + binder = data.readStrongBinder(); + if (binder == NULL) { + return BAD_VALUE; + } + reply2.writeInt32(NO_ERROR); + binder->transact(BINDER_LIB_TEST_CALL_BACK, data2, &reply2); + return NO_ERROR; + } + case BINDER_LIB_TEST_GET_ID_TRANSACTION: + reply->writeInt32(m_id); + return NO_ERROR; + case BINDER_LIB_TEST_INDIRECT_TRANSACTION: { + int32_t count; + uint32_t indirect_code; + sp<IBinder> binder; + + count = data.readInt32(); + reply->writeInt32(m_id); + reply->writeInt32(count); + for (int i = 0; i < count; i++) { + binder = data.readStrongBinder(); + if (binder == NULL) { + return BAD_VALUE; + } + indirect_code = data.readInt32(); + BinderLibTestBundle data2(&data); + if (!data2.isValid()) { + return BAD_VALUE; + } + BinderLibTestBundle reply2; + binder->transact(indirect_code, data2, &reply2); + reply2.appendTo(reply); + } + return NO_ERROR; + } + case BINDER_LIB_TEST_SET_ERROR_TRANSACTION: + reply->setError(data.readInt32()); + return NO_ERROR; + case BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION: + reply->writeInt32(sizeof(void *)); + return NO_ERROR; + case BINDER_LIB_TEST_GET_STATUS_TRANSACTION: + return NO_ERROR; + case BINDER_LIB_TEST_ADD_STRONG_REF_TRANSACTION: + m_strongRef = data.readStrongBinder(); + return NO_ERROR; + case BINDER_LIB_TEST_LINK_DEATH_TRANSACTION: { + int ret; + Parcel data2, reply2; + sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient(); + sp<IBinder> target; + sp<IBinder> callback; + + target = data.readStrongBinder(); + if (target == NULL) { + return BAD_VALUE; + } + callback = data.readStrongBinder(); + if (callback == NULL) { + return BAD_VALUE; + } + ret = target->linkToDeath(testDeathRecipient); + if (ret == NO_ERROR) + ret = testDeathRecipient->waitEvent(5); + data2.writeInt32(ret); + callback->transact(BINDER_LIB_TEST_CALL_BACK, data2, &reply2); + return NO_ERROR; + } + case BINDER_LIB_TEST_WRITE_FILE_TRANSACTION: { + int ret; + int32_t size; + const void *buf; + int fd; + + fd = data.readFileDescriptor(); + if (fd < 0) { + return BAD_VALUE; + } + ret = data.readInt32(&size); + if (ret != NO_ERROR) { + return ret; + } + buf = data.readInplace(size); + if (buf == NULL) { + return BAD_VALUE; + } + ret = write(fd, buf, size); + if (ret != size) + return UNKNOWN_ERROR; + return NO_ERROR; + } + case BINDER_LIB_TEST_PROMOTE_WEAK_REF_TRANSACTION: { + int ret; + wp<IBinder> weak; + sp<IBinder> strong; + Parcel data2, reply2; + sp<IServiceManager> sm = defaultServiceManager(); + sp<IBinder> server = sm->getService(binderLibTestServiceName); + + weak = data.readWeakBinder(); + if (weak == NULL) { + return BAD_VALUE; + } + strong = weak.promote(); + + ret = server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data2, &reply2); + if (ret != NO_ERROR) + exit(EXIT_FAILURE); + + if (strong == NULL) { + reply->setError(1); + } + return NO_ERROR; + } + case BINDER_LIB_TEST_DELAYED_EXIT_TRANSACTION: + alarm(10); + return NO_ERROR; + case BINDER_LIB_TEST_EXIT_TRANSACTION: + while (wait(NULL) != -1 || errno != ECHILD) + ; + exit(EXIT_SUCCESS); + default: + return UNKNOWN_TRANSACTION; + }; + } + private: + int32_t m_id; + int32_t m_nextServerId; + pthread_mutex_t m_serverWaitMutex; + pthread_cond_t m_serverWaitCond; + bool m_serverStartRequested; + sp<IBinder> m_serverStarted; + sp<IBinder> m_strongRef; +}; + +int run_server(int index, int readypipefd) +{ + status_t ret; + sp<IServiceManager> sm = defaultServiceManager(); + { + sp<BinderLibTestService> testService = new BinderLibTestService(index); + if (index == 0) { + ret = sm->addService(binderLibTestServiceName, testService); + } else { + sp<IBinder> server = sm->getService(binderLibTestServiceName); + Parcel data, reply; + data.writeInt32(index); + data.writeStrongBinder(testService); + + ret = server->transact(BINDER_LIB_TEST_REGISTER_SERVER, data, &reply); + } + } + write(readypipefd, &ret, sizeof(ret)); + close(readypipefd); + //printf("%s: ret %d\n", __func__, ret); + if (ret) + return 1; + //printf("%s: joinThreadPool\n", __func__); + ProcessState::self()->startThreadPool(); + IPCThreadState::self()->joinThreadPool(); + //printf("%s: joinThreadPool returned\n", __func__); + return 1; /* joinThreadPool should not return */ +} + +int main(int argc, char **argv) { + int ret; + + if (argc == 3 && !strcmp(argv[1], "--servername")) { + binderservername = argv[2]; + } else { + binderservername = argv[0]; + } + + if (argc == 4 && !strcmp(argv[1], binderserverarg)) { + return run_server(atoi(argv[2]), atoi(argv[3])); + } + + ::testing::InitGoogleTest(&argc, argv); + binder_env = AddGlobalTestEnvironment(new BinderLibTestEnv()); + ProcessState::self()->startThreadPool(); + return RUN_ALL_TESTS(); +} + diff --git a/libs/diskusage/dirsize.c b/libs/diskusage/dirsize.c index 24e5af0..7576994 100644 --- a/libs/diskusage/dirsize.c +++ b/libs/diskusage/dirsize.c @@ -18,6 +18,7 @@ #include <dirent.h> #include <fcntl.h> #include <sys/stat.h> +#include <unistd.h> #include <diskusage/dirsize.h> diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk index ca94aa3..8a965dd 100644 --- a/libs/gui/Android.mk +++ b/libs/gui/Android.mk @@ -1,7 +1,42 @@ -LOCAL_PATH:= $(call my-dir) +# Copyright 2010 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES:= \ +LOCAL_CLANG := true +LOCAL_CPPFLAGS := -std=c++1y -Weverything -Werror + +# The static constructors and destructors in this library have not been noted to +# introduce significant overheads +LOCAL_CPPFLAGS += -Wno-exit-time-destructors +LOCAL_CPPFLAGS += -Wno-global-constructors + +# We only care about compiling as C++14 +LOCAL_CPPFLAGS += -Wno-c++98-compat-pedantic + +# We don't need to enumerate every case in a switch as long as a default case +# is present +LOCAL_CPPFLAGS += -Wno-switch-enum + +# Allow calling variadic macros without a __VA_ARGS__ list +LOCAL_CPPFLAGS += -Wno-gnu-zero-variadic-macro-arguments + +# Don't warn about struct padding +LOCAL_CPPFLAGS += -Wno-padded + +LOCAL_SRC_FILES := \ IGraphicBufferConsumer.cpp \ IConsumerListener.cpp \ BitTube.cpp \ @@ -47,7 +82,7 @@ LOCAL_SHARED_LIBRARIES := \ liblog -LOCAL_MODULE:= libgui +LOCAL_MODULE := libgui ifeq ($(TARGET_BOARD_PLATFORM), tegra) LOCAL_CFLAGS += -DDONT_USE_FENCE_SYNC diff --git a/libs/gui/BitTube.cpp b/libs/gui/BitTube.cpp index 3ed1f37..b653c5b 100644 --- a/libs/gui/BitTube.cpp +++ b/libs/gui/BitTube.cpp @@ -149,12 +149,12 @@ ssize_t BitTube::sendObjects(const sp<BitTube>& tube, ssize_t size = tube->write(vaddr, count*objSize); // should never happen because of SOCK_SEQPACKET - LOG_ALWAYS_FATAL_IF((size >= 0) && (size % objSize), + LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)), "BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were sent!)", count, objSize, size); //ALOGE_IF(size<0, "error %d sending %d events", size, count); - return size < 0 ? size : size / objSize; + return size < 0 ? size : size / static_cast<ssize_t>(objSize); } ssize_t BitTube::recvObjects(const sp<BitTube>& tube, @@ -164,12 +164,12 @@ ssize_t BitTube::recvObjects(const sp<BitTube>& tube, ssize_t size = tube->read(vaddr, count*objSize); // should never happen because of SOCK_SEQPACKET - LOG_ALWAYS_FATAL_IF((size >= 0) && (size % objSize), + LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)), "BitTube::recvObjects(count=%zu, size=%zu), res=%zd (partial events were received!)", count, objSize, size); //ALOGE_IF(size<0, "error %d receiving %d events", size, count); - return size < 0 ? size : size / objSize; + return size < 0 ? size : size / static_cast<ssize_t>(objSize); } // ---------------------------------------------------------------------------- diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp index e6fc791..5793d40 100644 --- a/libs/gui/BufferItem.cpp +++ b/libs/gui/BufferItem.cpp @@ -28,6 +28,7 @@ BufferItem::BufferItem() : mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), mTimestamp(0), mIsAutoTimestamp(false), + mDataSpace(HAL_DATASPACE_UNKNOWN), mFrameNumber(0), mSlot(INVALID_BUFFER_SLOT), mIsDroppable(false), @@ -38,66 +39,66 @@ BufferItem::BufferItem() : BufferItem::~BufferItem() {} -BufferItem::operator IGraphicBufferConsumer::BufferItem() const { - IGraphicBufferConsumer::BufferItem bufferItem; - bufferItem.mGraphicBuffer = mGraphicBuffer; - bufferItem.mFence = mFence; - bufferItem.mCrop = mCrop; - bufferItem.mTransform = mTransform; - bufferItem.mScalingMode = mScalingMode; - bufferItem.mTimestamp = mTimestamp; - bufferItem.mIsAutoTimestamp = mIsAutoTimestamp; - bufferItem.mFrameNumber = mFrameNumber; - bufferItem.mBuf = mSlot; - bufferItem.mIsDroppable = mIsDroppable; - bufferItem.mAcquireCalled = mAcquireCalled; - bufferItem.mTransformToDisplayInverse = mTransformToDisplayInverse; - return bufferItem; +template <typename T> +static void addAligned(size_t& size, T /* value */) { + size = FlattenableUtils::align<sizeof(T)>(size); + size += sizeof(T); } size_t BufferItem::getPodSize() const { - size_t c = sizeof(mCrop) + - sizeof(mTransform) + - sizeof(mScalingMode) + - sizeof(mTimestamp) + - sizeof(mIsAutoTimestamp) + - sizeof(mFrameNumber) + - sizeof(mSlot) + - sizeof(mIsDroppable) + - sizeof(mAcquireCalled) + - sizeof(mTransformToDisplayInverse); - return c; + // Must align<8> before writing these fields for this to be correct + size_t size = 0; + addAligned(size, mCrop); + addAligned(size, mTransform); + addAligned(size, mScalingMode); + addAligned(size, mTimestamp); + addAligned(size, mIsAutoTimestamp); + addAligned(size, mDataSpace); + addAligned(size, mFrameNumber); + addAligned(size, mSlot); + addAligned(size, mIsDroppable); + addAligned(size, mAcquireCalled); + addAligned(size, mTransformToDisplayInverse); + return size; } size_t BufferItem::getFlattenedSize() const { - size_t c = 0; + size_t size = sizeof(uint32_t); // Flags if (mGraphicBuffer != 0) { - c += mGraphicBuffer->getFlattenedSize(); - FlattenableUtils::align<4>(c); + size += mGraphicBuffer->getFlattenedSize(); + FlattenableUtils::align<4>(size); } if (mFence != 0) { - c += mFence->getFlattenedSize(); - FlattenableUtils::align<4>(c); + size += mFence->getFlattenedSize(); + FlattenableUtils::align<4>(size); } - return sizeof(int32_t) + c + getPodSize(); + size += mSurfaceDamage.getFlattenedSize(); + size = FlattenableUtils::align<8>(size); + return size + getPodSize(); } size_t BufferItem::getFdCount() const { - size_t c = 0; + size_t count = 0; if (mGraphicBuffer != 0) { - c += mGraphicBuffer->getFdCount(); + count += mGraphicBuffer->getFdCount(); } if (mFence != 0) { - c += mFence->getFdCount(); + count += mFence->getFdCount(); } - return c; + return count; +} + +template <typename T> +static void writeAligned(void*& buffer, size_t& size, T value) { + size -= FlattenableUtils::align<alignof(T)>(buffer); + FlattenableUtils::write(buffer, size, value); } status_t BufferItem::flatten( void*& buffer, size_t& size, int*& fds, size_t& count) const { // make sure we have enough space - if (count < BufferItem::getFlattenedSize()) { + if (size < BufferItem::getFlattenedSize()) { return NO_MEMORY; } @@ -121,30 +122,45 @@ status_t BufferItem::flatten( flags |= 2; } - // check we have enough space (in case flattening the fence/graphicbuffer lied to us) + status_t err = mSurfaceDamage.flatten(buffer, size); + if (err) return err; + FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize()); + + // Must align<8> so that getPodSize returns the correct value + size -= FlattenableUtils::align<8>(buffer); + + // Check we still have enough space if (size < getPodSize()) { return NO_MEMORY; } - FlattenableUtils::write(buffer, size, mCrop); - FlattenableUtils::write(buffer, size, mTransform); - FlattenableUtils::write(buffer, size, mScalingMode); - FlattenableUtils::write(buffer, size, mTimestamp); - FlattenableUtils::write(buffer, size, mIsAutoTimestamp); - FlattenableUtils::write(buffer, size, mFrameNumber); - FlattenableUtils::write(buffer, size, mSlot); - FlattenableUtils::write(buffer, size, mIsDroppable); - FlattenableUtils::write(buffer, size, mAcquireCalled); - FlattenableUtils::write(buffer, size, mTransformToDisplayInverse); + writeAligned(buffer, size, mCrop); + writeAligned(buffer, size, mTransform); + writeAligned(buffer, size, mScalingMode); + writeAligned(buffer, size, mTimestamp); + writeAligned(buffer, size, mIsAutoTimestamp); + writeAligned(buffer, size, mDataSpace); + writeAligned(buffer, size, mFrameNumber); + writeAligned(buffer, size, mSlot); + writeAligned(buffer, size, mIsDroppable); + writeAligned(buffer, size, mAcquireCalled); + writeAligned(buffer, size, mTransformToDisplayInverse); return NO_ERROR; } +template <typename T> +static void readAligned(const void*& buffer, size_t& size, T& value) { + size -= FlattenableUtils::align<alignof(T)>(buffer); + FlattenableUtils::read(buffer, size, value); +} + status_t BufferItem::unflatten( void const*& buffer, size_t& size, int const*& fds, size_t& count) { - if (size < sizeof(uint32_t)) + if (size < sizeof(uint32_t)) { return NO_MEMORY; + } uint32_t flags = 0; FlattenableUtils::read(buffer, size, flags); @@ -163,21 +179,29 @@ status_t BufferItem::unflatten( size -= FlattenableUtils::align<4>(buffer); } - // check we have enough space + status_t err = mSurfaceDamage.unflatten(buffer, size); + if (err) return err; + FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize()); + + // Must align<8> so that getPodSize returns the correct value + size -= FlattenableUtils::align<8>(buffer); + + // Check we still have enough space if (size < getPodSize()) { return NO_MEMORY; } - FlattenableUtils::read(buffer, size, mCrop); - FlattenableUtils::read(buffer, size, mTransform); - FlattenableUtils::read(buffer, size, mScalingMode); - FlattenableUtils::read(buffer, size, mTimestamp); - FlattenableUtils::read(buffer, size, mIsAutoTimestamp); - FlattenableUtils::read(buffer, size, mFrameNumber); - FlattenableUtils::read(buffer, size, mSlot); - FlattenableUtils::read(buffer, size, mIsDroppable); - FlattenableUtils::read(buffer, size, mAcquireCalled); - FlattenableUtils::read(buffer, size, mTransformToDisplayInverse); + readAligned(buffer, size, mCrop); + readAligned(buffer, size, mTransform); + readAligned(buffer, size, mScalingMode); + readAligned(buffer, size, mTimestamp); + readAligned(buffer, size, mIsAutoTimestamp); + readAligned(buffer, size, mDataSpace); + readAligned(buffer, size, mFrameNumber); + readAligned(buffer, size, mSlot); + readAligned(buffer, size, mIsDroppable); + readAligned(buffer, size, mAcquireCalled); + readAligned(buffer, size, mTransformToDisplayInverse); return NO_ERROR; } diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp index fe50c55..194121f 100644 --- a/libs/gui/BufferItemConsumer.cpp +++ b/libs/gui/BufferItemConsumer.cpp @@ -16,16 +16,17 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "BufferItemConsumer" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS +//#define ATRACE_TAG ATRACE_TAG_GRAPHICS #include <utils/Log.h> +#include <gui/BufferItem.h> #include <gui/BufferItemConsumer.h> -#define BI_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__) -#define BI_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__) -#define BI_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__) -#define BI_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__) -#define BI_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__) +//#define BI_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__) +//#define BI_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__) +//#define BI_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__) +//#define BI_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__) +#define BI_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__) namespace android { @@ -44,8 +45,7 @@ BufferItemConsumer::BufferItemConsumer( } } -BufferItemConsumer::~BufferItemConsumer() { -} +BufferItemConsumer::~BufferItemConsumer() {} void BufferItemConsumer::setName(const String8& name) { Mutex::Autolock _l(mMutex); @@ -105,9 +105,15 @@ status_t BufferItemConsumer::setDefaultBufferSize(uint32_t w, uint32_t h) { return mConsumer->setDefaultBufferSize(w, h); } -status_t BufferItemConsumer::setDefaultBufferFormat(uint32_t defaultFormat) { +status_t BufferItemConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) { Mutex::Autolock _l(mMutex); return mConsumer->setDefaultBufferFormat(defaultFormat); } +status_t BufferItemConsumer::setDefaultBufferDataSpace( + android_dataspace defaultDataSpace) { + Mutex::Autolock _l(mMutex); + return mConsumer->setDefaultBufferDataSpace(defaultDataSpace); +} + } // namespace android diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index 61fd8c4..2fcbaf2 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -32,7 +32,7 @@ BufferQueue::ProxyConsumerListener::ProxyConsumerListener( BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {} void BufferQueue::ProxyConsumerListener::onFrameAvailable( - const android::BufferItem& item) { + const BufferItem& item) { sp<ConsumerListener> listener(mConsumerListener.promote()); if (listener != NULL) { listener->onFrameAvailable(item); diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp index 36e3c06..c7d5e00 100644 --- a/libs/gui/BufferQueueConsumer.cpp +++ b/libs/gui/BufferQueueConsumer.cpp @@ -120,6 +120,7 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer, if (mCore->stillTracking(front)) { // Front buffer is still in mSlots, so mark the slot as free mSlots[front->mSlot].mBufferState = BufferSlot::FREE; + mCore->mFreeBuffers.push_back(front->mSlot); } mCore->mQueue.erase(front); front = mCore->mQueue.begin(); @@ -173,6 +174,8 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer, ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size()); + mCore->validateConsistencyLocked(); + return NO_ERROR; } @@ -199,6 +202,7 @@ status_t BufferQueueConsumer::detachBuffer(int slot) { mCore->freeBufferLocked(slot); mCore->mDequeueCondition.broadcast(); + mCore->validateConsistencyLocked(); return NO_ERROR; } @@ -217,18 +221,11 @@ status_t BufferQueueConsumer::attachBuffer(int* outSlot, Mutex::Autolock lock(mCore->mMutex); - // Make sure we don't have too many acquired buffers and find a free slot - // to put the buffer into (the oldest if there are multiple). + // Make sure we don't have too many acquired buffers int numAcquiredBuffers = 0; - int found = BufferQueueCore::INVALID_BUFFER_SLOT; for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) { ++numAcquiredBuffers; - } else if (mSlots[s].mBufferState == BufferSlot::FREE) { - if (found == BufferQueueCore::INVALID_BUFFER_SLOT || - mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) { - found = s; - } } } @@ -238,6 +235,17 @@ status_t BufferQueueConsumer::attachBuffer(int* outSlot, mCore->mMaxAcquiredBufferCount); return INVALID_OPERATION; } + + // Find a free slot to put the buffer into + int found = BufferQueueCore::INVALID_BUFFER_SLOT; + if (!mCore->mFreeSlots.empty()) { + auto slot = mCore->mFreeSlots.begin(); + found = *slot; + mCore->mFreeSlots.erase(slot); + } else if (!mCore->mFreeBuffers.empty()) { + found = mCore->mFreeBuffers.front(); + mCore->mFreeBuffers.remove(found); + } if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { BQ_LOGE("attachBuffer(P): could not find free buffer slot"); return NO_MEMORY; @@ -271,6 +279,8 @@ status_t BufferQueueConsumer::attachBuffer(int* outSlot, // for attached buffers. mSlots[*outSlot].mAcquireCalled = false; + mCore->validateConsistencyLocked(); + return NO_ERROR; } @@ -311,6 +321,7 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber, mSlots[slot].mEglFence = eglFence; mSlots[slot].mFence = releaseFence; mSlots[slot].mBufferState = BufferSlot::FREE; + mCore->mFreeBuffers.push_back(slot); listener = mCore->mConnectedProducerListener; BQ_LOGV("releaseBuffer: releasing slot %d", slot); } else if (mSlots[slot].mNeedsCleanupOnRelease) { @@ -325,6 +336,7 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber, } mCore->mDequeueCondition.broadcast(); + mCore->validateConsistencyLocked(); } // Autolock scope // Call back without lock held @@ -488,7 +500,7 @@ void BufferQueueConsumer::setConsumerName(const String8& name) { mConsumerName = name; } -status_t BufferQueueConsumer::setDefaultBufferFormat(uint32_t defaultFormat) { +status_t BufferQueueConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) { ATRACE_CALL(); BQ_LOGV("setDefaultBufferFormat: %u", defaultFormat); Mutex::Autolock lock(mCore->mMutex); @@ -496,6 +508,15 @@ status_t BufferQueueConsumer::setDefaultBufferFormat(uint32_t defaultFormat) { return NO_ERROR; } +status_t BufferQueueConsumer::setDefaultBufferDataSpace( + android_dataspace defaultDataSpace) { + ATRACE_CALL(); + BQ_LOGV("setDefaultBufferDataSpace: %u", defaultDataSpace); + Mutex::Autolock lock(mCore->mMutex); + mCore->mDefaultBufferDataSpace = defaultDataSpace; + return NO_ERROR; +} + status_t BufferQueueConsumer::setConsumerUsageBits(uint32_t usage) { ATRACE_CALL(); BQ_LOGV("setConsumerUsageBits: %#x", usage); diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp index ec1e631..bc75ca7 100644 --- a/libs/gui/BufferQueueCore.cpp +++ b/libs/gui/BufferQueueCore.cpp @@ -53,6 +53,8 @@ BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) : mConnectedProducerListener(), mSlots(), mQueue(), + mFreeSlots(), + mFreeBuffers(), mOverrideMaxBufferCount(0), mDequeueCondition(), mUseAsyncBuffer(true), @@ -60,13 +62,15 @@ BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) : mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888), mDefaultWidth(1), mDefaultHeight(1), + mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN), mDefaultMaxBufferCount(2), mMaxAcquiredBufferCount(1), mBufferHasBeenQueued(false), mFrameCounter(0), mTransformHint(0), mIsAllocating(false), - mIsAllocatingCondition() + mIsAllocatingCondition(), + mAllowAllocation(true) { if (allocator == NULL) { sp<ISurfaceComposer> composer(ComposerService::getComposerService()); @@ -75,6 +79,9 @@ BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) : BQ_LOGE("createGraphicBufferAlloc failed"); } } + for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) { + mFreeSlots.insert(slot); + } } BufferQueueCore::~BufferQueueCore() {} @@ -189,12 +196,20 @@ status_t BufferQueueCore::setDefaultMaxBufferCountLocked(int count) { void BufferQueueCore::freeBufferLocked(int slot) { BQ_LOGV("freeBufferLocked: slot %d", slot); + bool hadBuffer = mSlots[slot].mGraphicBuffer != NULL; mSlots[slot].mGraphicBuffer.clear(); if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) { mSlots[slot].mNeedsCleanupOnRelease = true; } + if (mSlots[slot].mBufferState != BufferSlot::FREE) { + mFreeSlots.insert(slot); + } else if (hadBuffer) { + // If the slot was FREE, but we had a buffer, we need to move this slot + // from the free buffers list to the the free slots list + mFreeBuffers.remove(slot); + mFreeSlots.insert(slot); + } mSlots[slot].mBufferState = BufferSlot::FREE; - mSlots[slot].mFrameNumber = UINT32_MAX; mSlots[slot].mAcquireCalled = false; // Destroy fence as BufferQueue now takes ownership @@ -203,6 +218,7 @@ void BufferQueueCore::freeBufferLocked(int slot) { mSlots[slot].mEglFence = EGL_NO_SYNC_KHR; } mSlots[slot].mFence = Fence::NO_FENCE; + validateConsistencyLocked(); } void BufferQueueCore::freeAllBuffersLocked() { @@ -235,4 +251,48 @@ void BufferQueueCore::waitWhileAllocatingLocked() const { } } +void BufferQueueCore::validateConsistencyLocked() const { + static const useconds_t PAUSE_TIME = 0; + for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) { + bool isInFreeSlots = mFreeSlots.count(slot) != 0; + bool isInFreeBuffers = + std::find(mFreeBuffers.cbegin(), mFreeBuffers.cend(), slot) != + mFreeBuffers.cend(); + if (mSlots[slot].mBufferState == BufferSlot::FREE) { + if (mSlots[slot].mGraphicBuffer == NULL) { + if (!isInFreeSlots) { + BQ_LOGE("Slot %d is FREE but is not in mFreeSlots", slot); + usleep(PAUSE_TIME); + } + if (isInFreeBuffers) { + BQ_LOGE("Slot %d is in mFreeSlots " + "but is also in mFreeBuffers", slot); + usleep(PAUSE_TIME); + } + } else { + if (!isInFreeBuffers) { + BQ_LOGE("Slot %d is FREE but is not in mFreeBuffers", slot); + usleep(PAUSE_TIME); + } + if (isInFreeSlots) { + BQ_LOGE("Slot %d is in mFreeBuffers " + "but is also in mFreeSlots", slot); + usleep(PAUSE_TIME); + } + } + } else { + if (isInFreeSlots) { + BQ_LOGE("Slot %d is in mFreeSlots but is not FREE (%d)", + slot, mSlots[slot].mBufferState); + usleep(PAUSE_TIME); + } + if (isInFreeBuffers) { + BQ_LOGE("Slot %d is in mFreeBuffers but is not FREE (%d)", + slot, mSlots[slot].mBufferState); + usleep(PAUSE_TIME); + } + } + } +} + } // namespace android diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 16b9747..86e45c8 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -161,8 +161,6 @@ status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller, } } - // Look for a free buffer to give to the client - *found = BufferQueueCore::INVALID_BUFFER_SLOT; int dequeuedCount = 0; int acquiredCount = 0; for (int s = 0; s < maxBufferCount; ++s) { @@ -173,15 +171,6 @@ status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller, case BufferSlot::ACQUIRED: ++acquiredCount; break; - case BufferSlot::FREE: - // We return the oldest of the free buffers to avoid - // stalling the producer if possible, since the consumer - // may still have pending reads of in-flight buffers - if (*found == BufferQueueCore::INVALID_BUFFER_SLOT || - mSlots[s].mFrameNumber < mSlots[*found].mFrameNumber) { - *found = s; - } - break; default: break; } @@ -214,6 +203,8 @@ status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller, } } + *found = BufferQueueCore::INVALID_BUFFER_SLOT; + // If we disconnect and reconnect quickly, we can be in a state where // our slots are empty but we have many buffers in the queue. This can // cause us to run out of memory if we outrun the consumer. Wait here if @@ -223,6 +214,19 @@ status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller, if (tooManyBuffers) { BQ_LOGV("%s: queue size is %zu, waiting", caller, mCore->mQueue.size()); + } else { + if (!mCore->mFreeBuffers.empty()) { + auto slot = mCore->mFreeBuffers.begin(); + *found = *slot; + mCore->mFreeBuffers.erase(slot); + } else if (mCore->mAllowAllocation && !mCore->mFreeSlots.empty()) { + auto slot = mCore->mFreeSlots.begin(); + // Only return free slots up to the max buffer count + if (*slot < maxBufferCount) { + *found = *slot; + mCore->mFreeSlots.erase(slot); + } + } } // If no buffer is found, or if the queue has too many buffers @@ -250,7 +254,7 @@ status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller, status_t BufferQueueProducer::dequeueBuffer(int *outSlot, sp<android::Fence> *outFence, bool async, - uint32_t width, uint32_t height, uint32_t format, uint32_t usage) { + uint32_t width, uint32_t height, PixelFormat format, uint32_t usage) { ATRACE_CALL(); { // Autolock scope Mutex::Autolock lock(mCore->mMutex); @@ -281,17 +285,39 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot, // Enable the usage bits the consumer requested usage |= mCore->mConsumerUsageBits; - int found; - status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async, - &found, &returnFlags); - if (status != NO_ERROR) { - return status; + const bool useDefaultSize = !width && !height; + if (useDefaultSize) { + width = mCore->mDefaultWidth; + height = mCore->mDefaultHeight; } - // This should not happen - if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { - BQ_LOGE("dequeueBuffer: no available buffer slots"); - return -EBUSY; + int found = BufferItem::INVALID_BUFFER_SLOT; + while (found == BufferItem::INVALID_BUFFER_SLOT) { + status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async, + &found, &returnFlags); + if (status != NO_ERROR) { + return status; + } + + // This should not happen + if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { + BQ_LOGE("dequeueBuffer: no available buffer slots"); + return -EBUSY; + } + + const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer); + + // If we are not allowed to allocate new buffers, + // waitForFreeSlotThenRelock must have returned a slot containing a + // buffer. If this buffer would require reallocation to meet the + // requested attributes, we free it and attempt to get another one. + if (!mCore->mAllowAllocation) { + if (buffer->needsReallocation(width, height, format, usage)) { + mCore->freeBufferLocked(found); + found = BufferItem::INVALID_BUFFER_SLOT; + continue; + } + } } *outSlot = found; @@ -299,20 +325,11 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot, attachedByConsumer = mSlots[found].mAttachedByConsumer; - const bool useDefaultSize = !width && !height; - if (useDefaultSize) { - width = mCore->mDefaultWidth; - height = mCore->mDefaultHeight; - } - mSlots[found].mBufferState = BufferSlot::DEQUEUED; const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer); if ((buffer == NULL) || - (static_cast<uint32_t>(buffer->width) != width) || - (static_cast<uint32_t>(buffer->height) != height) || - (static_cast<uint32_t>(buffer->format) != format) || - ((static_cast<uint32_t>(buffer->usage) & usage) != usage)) + buffer->needsReallocation(width, height, format, usage)) { mSlots[found].mAcquireCalled = false; mSlots[found].mGraphicBuffer = NULL; @@ -335,13 +352,15 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot, *outFence = mSlots[found].mFence; mSlots[found].mEglFence = EGL_NO_SYNC_KHR; mSlots[found].mFence = Fence::NO_FENCE; + + mCore->validateConsistencyLocked(); } // Autolock scope if (returnFlags & BUFFER_NEEDS_REALLOCATION) { status_t error; BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot); sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer( - width, height, format, usage, &error)); + width, height, format, usage, &error)); if (graphicBuffer == NULL) { BQ_LOGE("dequeueBuffer: createGraphicBuffer failed"); return error; @@ -355,7 +374,6 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot, return NO_INIT; } - mSlots[*outSlot].mFrameNumber = UINT32_MAX; mSlots[*outSlot].mGraphicBuffer = graphicBuffer; } // Autolock scope } @@ -414,6 +432,7 @@ status_t BufferQueueProducer::detachBuffer(int slot) { mCore->freeBufferLocked(slot); mCore->mDequeueCondition.broadcast(); + mCore->validateConsistencyLocked(); return NO_ERROR; } @@ -438,27 +457,19 @@ status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer, return NO_INIT; } - // Find the oldest valid slot - int found = BufferQueueCore::INVALID_BUFFER_SLOT; - for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - if (mSlots[s].mBufferState == BufferSlot::FREE && - mSlots[s].mGraphicBuffer != NULL) { - if (found == BufferQueueCore::INVALID_BUFFER_SLOT || - mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) { - found = s; - } - } - } - - if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { + if (mCore->mFreeBuffers.empty()) { return NO_MEMORY; } + int found = mCore->mFreeBuffers.front(); + mCore->mFreeBuffers.remove(found); + BQ_LOGV("detachNextBuffer detached slot %d", found); *outBuffer = mSlots[found].mGraphicBuffer; *outFence = mSlots[found].mFence; mCore->freeBufferLocked(found); + mCore->validateConsistencyLocked(); return NO_ERROR; } @@ -506,6 +517,8 @@ status_t BufferQueueProducer::attachBuffer(int* outSlot, mSlots[*outSlot].mFence = Fence::NO_FENCE; mSlots[*outSlot].mRequestBufferCalled = true; + mCore->validateConsistencyLocked(); + return returnFlags; } @@ -516,14 +529,16 @@ status_t BufferQueueProducer::queueBuffer(int slot, int64_t timestamp; bool isAutoTimestamp; + android_dataspace dataSpace; Rect crop; int scalingMode; uint32_t transform; uint32_t stickyTransform; bool async; sp<Fence> fence; - input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode, &transform, - &async, &fence, &stickyTransform); + input.deflate(×tamp, &isAutoTimestamp, &dataSpace, &crop, &scalingMode, + &transform, &async, &fence, &stickyTransform); + Region surfaceDamage = input.getSurfaceDamage(); if (fence == NULL) { BQ_LOGE("queueBuffer: fence is NULL"); @@ -579,11 +594,11 @@ status_t BufferQueueProducer::queueBuffer(int slot, return BAD_VALUE; } - BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 + BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 " dataSpace=%d" " crop=[%d,%d,%d,%d] transform=%#x scale=%s", - slot, mCore->mFrameCounter + 1, timestamp, - crop.left, crop.top, crop.right, crop.bottom, - transform, BufferItem::scalingModeName(scalingMode)); + slot, mCore->mFrameCounter + 1, timestamp, dataSpace, + crop.left, crop.top, crop.right, crop.bottom, transform, + BufferItem::scalingModeName(static_cast<uint32_t>(scalingMode))); const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer); Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight()); @@ -595,6 +610,11 @@ status_t BufferQueueProducer::queueBuffer(int slot, return BAD_VALUE; } + // Override UNKNOWN dataspace with consumer default + if (dataSpace == HAL_DATASPACE_UNKNOWN) { + dataSpace = mCore->mDefaultBufferDataSpace; + } + mSlots[slot].mFence = fence; mSlots[slot].mBufferState = BufferSlot::QUEUED; ++mCore->mFrameCounter; @@ -603,16 +623,19 @@ status_t BufferQueueProducer::queueBuffer(int slot, item.mAcquireCalled = mSlots[slot].mAcquireCalled; item.mGraphicBuffer = mSlots[slot].mGraphicBuffer; item.mCrop = crop; - item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; + item.mTransform = transform & + ~static_cast<uint32_t>(NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY); item.mTransformToDisplayInverse = - bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY); - item.mScalingMode = scalingMode; + (transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0; + item.mScalingMode = static_cast<uint32_t>(scalingMode); item.mTimestamp = timestamp; item.mIsAutoTimestamp = isAutoTimestamp; + item.mDataSpace = dataSpace; item.mFrameNumber = mCore->mFrameCounter; item.mSlot = slot; item.mFence = fence; item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async; + item.mSurfaceDamage = surfaceDamage; mStickyTransform = stickyTransform; @@ -630,9 +653,7 @@ status_t BufferQueueProducer::queueBuffer(int slot, // mark it as freed if (mCore->stillTracking(front)) { mSlots[front->mSlot].mBufferState = BufferSlot::FREE; - // Reset the frame number of the freed buffer so that it is - // the first in line to be dequeued again - mSlots[front->mSlot].mFrameNumber = 0; + mCore->mFreeBuffers.push_front(front->mSlot); } // Overwrite the droppable buffer with the incoming one *front = item; @@ -647,12 +668,15 @@ status_t BufferQueueProducer::queueBuffer(int slot, mCore->mDequeueCondition.broadcast(); output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, - mCore->mTransformHint, mCore->mQueue.size()); + mCore->mTransformHint, + static_cast<uint32_t>(mCore->mQueue.size())); ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size()); // Take a ticket for the callback functions callbackTicket = mNextCallbackTicket++; + + mCore->validateConsistencyLocked(); } // Autolock scope // Wait without lock held @@ -713,10 +737,11 @@ void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) { return; } + mCore->mFreeBuffers.push_front(slot); mSlots[slot].mBufferState = BufferSlot::FREE; - mSlots[slot].mFrameNumber = 0; mSlots[slot].mFence = fence; mCore->mDequeueCondition.broadcast(); + mCore->validateConsistencyLocked(); } int BufferQueueProducer::query(int what, int *outValue) { @@ -736,25 +761,28 @@ int BufferQueueProducer::query(int what, int *outValue) { int value; switch (what) { case NATIVE_WINDOW_WIDTH: - value = mCore->mDefaultWidth; + value = static_cast<int32_t>(mCore->mDefaultWidth); break; case NATIVE_WINDOW_HEIGHT: - value = mCore->mDefaultHeight; + value = static_cast<int32_t>(mCore->mDefaultHeight); break; case NATIVE_WINDOW_FORMAT: - value = mCore->mDefaultBufferFormat; + value = static_cast<int32_t>(mCore->mDefaultBufferFormat); break; case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: value = mCore->getMinUndequeuedBufferCountLocked(false); break; case NATIVE_WINDOW_STICKY_TRANSFORM: - value = static_cast<int>(mStickyTransform); + value = static_cast<int32_t>(mStickyTransform); break; case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: value = (mCore->mQueue.size() > 1); break; case NATIVE_WINDOW_CONSUMER_USAGE_BITS: - value = mCore->mConsumerUsageBits; + value = static_cast<int32_t>(mCore->mConsumerUsageBits); + break; + case NATIVE_WINDOW_DEFAULT_DATASPACE: + value = static_cast<int32_t>(mCore->mDefaultBufferDataSpace); break; default: return BAD_VALUE; @@ -802,13 +830,14 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, case NATIVE_WINDOW_API_CAMERA: mCore->mConnectedApi = api; output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, - mCore->mTransformHint, mCore->mQueue.size()); + mCore->mTransformHint, + static_cast<uint32_t>(mCore->mQueue.size())); // Set up a death notification so that we can disconnect // automatically if the remote producer dies if (listener != NULL && - listener->asBinder()->remoteBinder() != NULL) { - status = listener->asBinder()->linkToDeath( + IInterface::asBinder(listener)->remoteBinder() != NULL) { + status = IInterface::asBinder(listener)->linkToDeath( static_cast<IBinder::DeathRecipient*>(this)); if (status != NO_ERROR) { BQ_LOGE("connect(P): linkToDeath failed: %s (%d)", @@ -857,7 +886,7 @@ status_t BufferQueueProducer::disconnect(int api) { // Remove our death notification callback if we have one if (mCore->mConnectedProducerListener != NULL) { sp<IBinder> token = - mCore->mConnectedProducerListener->asBinder(); + IInterface::asBinder(mCore->mConnectedProducerListener); // This can fail if we're here because of the death // notification, but we just ignore it token->unlinkToDeath( @@ -904,19 +933,25 @@ status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) } void BufferQueueProducer::allocateBuffers(bool async, uint32_t width, - uint32_t height, uint32_t format, uint32_t usage) { + uint32_t height, PixelFormat format, uint32_t usage) { ATRACE_CALL(); while (true) { Vector<int> freeSlots; size_t newBufferCount = 0; uint32_t allocWidth = 0; uint32_t allocHeight = 0; - uint32_t allocFormat = 0; + PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN; uint32_t allocUsage = 0; { // Autolock scope Mutex::Autolock lock(mCore->mMutex); mCore->waitWhileAllocatingLocked(); + if (!mCore->mAllowAllocation) { + BQ_LOGE("allocateBuffers: allocation is not allowed for this " + "BufferQueue"); + return; + } + int currentBufferCount = 0; for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) { if (mSlots[slot].mGraphicBuffer != NULL) { @@ -937,7 +972,8 @@ void BufferQueueProducer::allocateBuffers(bool async, uint32_t width, currentBufferCount, maxBufferCount); if (maxBufferCount <= currentBufferCount) return; - newBufferCount = maxBufferCount - currentBufferCount; + newBufferCount = + static_cast<size_t>(maxBufferCount - currentBufferCount); if (freeSlots.size() < newBufferCount) { BQ_LOGE("allocateBuffers: ran out of free slots"); return; @@ -950,7 +986,7 @@ void BufferQueueProducer::allocateBuffers(bool async, uint32_t width, mCore->mIsAllocating = true; } // Autolock scope - Vector<sp<GraphicBuffer> > buffers; + Vector<sp<GraphicBuffer>> buffers; for (size_t i = 0; i < newBufferCount; ++i) { status_t result = NO_ERROR; sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer( @@ -970,7 +1006,8 @@ void BufferQueueProducer::allocateBuffers(bool async, uint32_t width, Mutex::Autolock lock(mCore->mMutex); uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth; uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight; - uint32_t checkFormat = format != 0 ? format : mCore->mDefaultBufferFormat; + PixelFormat checkFormat = format != 0 ? + format : mCore->mDefaultBufferFormat; uint32_t checkUsage = usage | mCore->mConsumerUsageBits; if (checkWidth != allocWidth || checkHeight != allocHeight || checkFormat != allocFormat || checkUsage != allocUsage) { @@ -992,17 +1029,32 @@ void BufferQueueProducer::allocateBuffers(bool async, uint32_t width, } mCore->freeBufferLocked(slot); // Clean up the slot first mSlots[slot].mGraphicBuffer = buffers[i]; - mSlots[slot].mFrameNumber = 0; mSlots[slot].mFence = Fence::NO_FENCE; + + // freeBufferLocked puts this slot on the free slots list. Since + // we then attached a buffer, move the slot to free buffer list. + mCore->mFreeSlots.erase(slot); + mCore->mFreeBuffers.push_front(slot); + BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot); } mCore->mIsAllocating = false; mCore->mIsAllocatingCondition.broadcast(); + mCore->validateConsistencyLocked(); } // Autolock scope } } +status_t BufferQueueProducer::allowAllocation(bool allow) { + ATRACE_CALL(); + BQ_LOGV("allowAllocation: %s", allow ? "true" : "false"); + + Mutex::Autolock lock(mCore->mMutex); + mCore->mAllowAllocation = allow; + return NO_ERROR; +} + void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) { // If we're here, it means that a producer we were connected to died. // We're guaranteed that we are still connected to it because we remove diff --git a/libs/gui/BufferSlot.cpp b/libs/gui/BufferSlot.cpp index b8877fe..01595de 100644 --- a/libs/gui/BufferSlot.cpp +++ b/libs/gui/BufferSlot.cpp @@ -24,8 +24,8 @@ const char* BufferSlot::bufferStateName(BufferState state) { case BufferSlot::QUEUED: return "QUEUED"; case BufferSlot::FREE: return "FREE"; case BufferSlot::ACQUIRED: return "ACQUIRED"; - default: return "Unknown"; } + return "Unknown"; } } // namespace android diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp index 210e98e..e576018 100644 --- a/libs/gui/ConsumerBase.cpp +++ b/libs/gui/ConsumerBase.cpp @@ -27,6 +27,7 @@ #include <hardware/hardware.h> +#include <gui/BufferItem.h> #include <gui/IGraphicBufferAlloc.h> #include <gui/ISurfaceComposer.h> #include <gui/SurfaceComposerClient.h> @@ -39,11 +40,11 @@ #include <utils/Trace.h> // Macros for including the ConsumerBase name in log messages -#define CB_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__) -#define CB_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__) -#define CB_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__) -#define CB_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__) -#define CB_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__) +#define CB_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__) +//#define CB_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__) +//#define CB_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__) +//#define CB_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__) +#define CB_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__) namespace android { @@ -162,6 +163,21 @@ void ConsumerBase::setFrameAvailableListener( mFrameAvailableListener = listener; } +status_t ConsumerBase::detachBuffer(int slot) { + CB_LOGV("detachBuffer"); + Mutex::Autolock lock(mMutex); + + status_t result = mConsumer->detachBuffer(slot); + if (result != NO_ERROR) { + CB_LOGE("Failed to detach buffer: %d", result); + return result; + } + + freeBufferLocked(slot); + + return result; +} + void ConsumerBase::dump(String8& result) const { dump(result, ""); } @@ -179,7 +195,7 @@ void ConsumerBase::dumpLocked(String8& result, const char* prefix) const { } } -status_t ConsumerBase::acquireBufferLocked(BufferQueue::BufferItem *item, +status_t ConsumerBase::acquireBufferLocked(BufferItem *item, nsecs_t presentWhen) { status_t err = mConsumer->acquireBuffer(item, presentWhen); if (err != NO_ERROR) { diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp index c541ff4..eb39469 100644 --- a/libs/gui/CpuConsumer.cpp +++ b/libs/gui/CpuConsumer.cpp @@ -16,22 +16,23 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "CpuConsumer" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS +//#define ATRACE_TAG ATRACE_TAG_GRAPHICS #include <cutils/compiler.h> #include <utils/Log.h> +#include <gui/BufferItem.h> #include <gui/CpuConsumer.h> -#define CC_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__) -#define CC_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__) -#define CC_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__) -#define CC_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__) -#define CC_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__) +#define CC_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__) +//#define CC_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__) +//#define CC_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__) +#define CC_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__) +#define CC_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__) namespace android { CpuConsumer::CpuConsumer(const sp<IGraphicBufferConsumer>& bq, - uint32_t maxLockedBuffers, bool controlledByApp) : + size_t maxLockedBuffers, bool controlledByApp) : ConsumerBase(bq, controlledByApp), mMaxLockedBuffers(maxLockedBuffers), mCurrentLockedBuffers(0) @@ -40,7 +41,7 @@ CpuConsumer::CpuConsumer(const sp<IGraphicBufferConsumer>& bq, mAcquiredBuffers.insertAt(0, maxLockedBuffers); mConsumer->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN); - mConsumer->setMaxAcquiredBufferCount(maxLockedBuffers); + mConsumer->setMaxAcquiredBufferCount(static_cast<int32_t>(maxLockedBuffers)); } CpuConsumer::~CpuConsumer() { @@ -61,24 +62,29 @@ status_t CpuConsumer::setDefaultBufferSize(uint32_t width, uint32_t height) return mConsumer->setDefaultBufferSize(width, height); } -status_t CpuConsumer::setDefaultBufferFormat(uint32_t defaultFormat) +status_t CpuConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) { Mutex::Autolock _l(mMutex); return mConsumer->setDefaultBufferFormat(defaultFormat); } +status_t CpuConsumer::setDefaultBufferDataSpace( + android_dataspace defaultDataSpace) +{ + Mutex::Autolock _l(mMutex); + return mConsumer->setDefaultBufferDataSpace(defaultDataSpace); +} + static bool isPossiblyYUV(PixelFormat format) { - switch ((int)format) { + switch (static_cast<int>(format)) { case HAL_PIXEL_FORMAT_RGBA_8888: case HAL_PIXEL_FORMAT_RGBX_8888: case HAL_PIXEL_FORMAT_RGB_888: case HAL_PIXEL_FORMAT_RGB_565: case HAL_PIXEL_FORMAT_BGRA_8888: - case HAL_PIXEL_FORMAT_sRGB_A_8888: - case HAL_PIXEL_FORMAT_sRGB_X_8888: case HAL_PIXEL_FORMAT_Y8: case HAL_PIXEL_FORMAT_Y16: - case HAL_PIXEL_FORMAT_RAW16: // same as HAL_PIXEL_FORMAT_RAW_SENSOR + case HAL_PIXEL_FORMAT_RAW16: case HAL_PIXEL_FORMAT_RAW10: case HAL_PIXEL_FORMAT_RAW_OPAQUE: case HAL_PIXEL_FORMAT_BLOB: @@ -100,12 +106,12 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { if (!nativeBuffer) return BAD_VALUE; if (mCurrentLockedBuffers == mMaxLockedBuffers) { - CC_LOGW("Max buffers have been locked (%d), cannot lock anymore.", + CC_LOGW("Max buffers have been locked (%zd), cannot lock anymore.", mMaxLockedBuffers); return NOT_ENOUGH_DATA; } - BufferQueue::BufferItem b; + BufferItem b; Mutex::Autolock _l(mMutex); @@ -173,7 +179,7 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { } size_t lockedIdx = 0; - for (; lockedIdx < mMaxLockedBuffers; lockedIdx++) { + for (; lockedIdx < static_cast<size_t>(mMaxLockedBuffers); lockedIdx++) { if (mAcquiredBuffers[lockedIdx].mSlot == BufferQueue::INVALID_BUFFER_SLOT) { break; @@ -193,19 +199,20 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { nativeBuffer->format = format; nativeBuffer->flexFormat = flexFormat; nativeBuffer->stride = (ycbcr.y != NULL) ? - ycbcr.ystride : + static_cast<uint32_t>(ycbcr.ystride) : mSlots[buf].mGraphicBuffer->getStride(); nativeBuffer->crop = b.mCrop; nativeBuffer->transform = b.mTransform; nativeBuffer->scalingMode = b.mScalingMode; nativeBuffer->timestamp = b.mTimestamp; + nativeBuffer->dataSpace = b.mDataSpace; nativeBuffer->frameNumber = b.mFrameNumber; nativeBuffer->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb); nativeBuffer->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr); - nativeBuffer->chromaStride = ycbcr.cstride; - nativeBuffer->chromaStep = ycbcr.chroma_step; + nativeBuffer->chromaStride = static_cast<uint32_t>(ycbcr.cstride); + nativeBuffer->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step); mCurrentLockedBuffers++; @@ -215,10 +222,9 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) { Mutex::Autolock _l(mMutex); size_t lockedIdx = 0; - status_t err; void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data); - for (; lockedIdx < mMaxLockedBuffers; lockedIdx++) { + for (; lockedIdx < static_cast<size_t>(mMaxLockedBuffers); lockedIdx++) { if (bufPtr == mAcquiredBuffers[lockedIdx].mBufferPointer) break; } if (lockedIdx == mMaxLockedBuffers) { @@ -229,13 +235,13 @@ status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) { return releaseAcquiredBufferLocked(lockedIdx); } -status_t CpuConsumer::releaseAcquiredBufferLocked(int lockedIdx) { +status_t CpuConsumer::releaseAcquiredBufferLocked(size_t lockedIdx) { status_t err; int fd = -1; err = mAcquiredBuffers[lockedIdx].mGraphicBuffer->unlockAsync(&fd); if (err != OK) { - CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, + CC_LOGE("%s: Unable to unlock graphic buffer %zd", __FUNCTION__, lockedIdx); return err; } diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp index 318c087..96c0841 100644 --- a/libs/gui/GLConsumer.cpp +++ b/libs/gui/GLConsumer.cpp @@ -29,6 +29,7 @@ #include <hardware/hardware.h> +#include <gui/BufferItem.h> #include <gui/GLConsumer.h> #include <gui/IGraphicBufferAlloc.h> #include <gui/ISurfaceComposer.h> @@ -47,18 +48,28 @@ EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint na namespace android { // Macros for including the GLConsumer name in log messages -#define ST_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__) -#define ST_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__) -#define ST_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__) -#define ST_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__) -#define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__) +#define GLC_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__) +#define GLC_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__) +//#define GLC_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__) +#define GLC_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__) +#define GLC_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__) static const struct { - size_t width, height; + uint32_t width, height; char const* bits; } kDebugData = { 15, 12, - "___________________________________XX_XX_______X_X_____X_X____X_XXXXXXX_X____XXXXXXXXXXX__" - "___XX_XXX_XX_______XXXXXXX_________X___X_________X_____X__________________________________" + "_______________" + "_______________" + "_____XX_XX_____" + "__X_X_____X_X__" + "__X_XXXXXXX_X__" + "__XXXXXXXXXXX__" + "___XX_XXX_XX___" + "____XXXXXXX____" + "_____X___X_____" + "____X_____X____" + "_______________" + "_______________" }; // Transform matrices @@ -135,7 +146,7 @@ GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex, mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT), mAttached(true) { - ST_LOGV("GLConsumer"); + GLC_LOGV("GLConsumer"); memcpy(mCurrentTransformMatrix, mtxIdentity, sizeof(mCurrentTransformMatrix)); @@ -154,7 +165,7 @@ GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget, mDefaultWidth(1), mDefaultHeight(1), mFilteringEnabled(true), - mTexName(-1), + mTexName(0), mUseFenceSync(useFenceSync), mTexTarget(texTarget), mEglDisplay(EGL_NO_DISPLAY), @@ -162,7 +173,7 @@ GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget, mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT), mAttached(false) { - ST_LOGV("GLConsumer"); + GLC_LOGV("GLConsumer"); memcpy(mCurrentTransformMatrix, mtxIdentity, sizeof(mCurrentTransformMatrix)); @@ -186,11 +197,11 @@ status_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h) status_t GLConsumer::updateTexImage() { ATRACE_CALL(); - ST_LOGV("updateTexImage"); + GLC_LOGV("updateTexImage"); Mutex::Autolock lock(mMutex); if (mAbandoned) { - ST_LOGE("updateTexImage: GLConsumer is abandoned!"); + GLC_LOGE("updateTexImage: GLConsumer is abandoned!"); return NO_INIT; } @@ -200,7 +211,7 @@ status_t GLConsumer::updateTexImage() { return err; } - BufferQueue::BufferItem item; + BufferItem item; // Acquire the next buffer. // In asynchronous mode the list is guaranteed to be one buffer @@ -209,11 +220,11 @@ status_t GLConsumer::updateTexImage() { if (err != NO_ERROR) { if (err == BufferQueue::NO_BUFFER_AVAILABLE) { // We always bind the texture even if we don't update its contents. - ST_LOGV("updateTexImage: no buffers were available"); + GLC_LOGV("updateTexImage: no buffers were available"); glBindTexture(mTexTarget, mTexName); err = NO_ERROR; } else { - ST_LOGE("updateTexImage: acquire failed: %s (%d)", + GLC_LOGE("updateTexImage: acquire failed: %s (%d)", strerror(-err), err); } return err; @@ -234,11 +245,11 @@ status_t GLConsumer::updateTexImage() { status_t GLConsumer::releaseTexImage() { ATRACE_CALL(); - ST_LOGV("releaseTexImage"); + GLC_LOGV("releaseTexImage"); Mutex::Autolock lock(mMutex); if (mAbandoned) { - ST_LOGE("releaseTexImage: GLConsumer is abandoned!"); + GLC_LOGE("releaseTexImage: GLConsumer is abandoned!"); return NO_INIT; } @@ -258,13 +269,13 @@ status_t GLConsumer::releaseTexImage() { int buf = mCurrentTexture; if (buf != BufferQueue::INVALID_BUFFER_SLOT) { - ST_LOGV("releaseTexImage: (slot=%d, mAttached=%d)", buf, mAttached); + GLC_LOGV("releaseTexImage: (slot=%d, mAttached=%d)", buf, mAttached); if (mAttached) { // Do whatever sync ops we need to do before releasing the slot. err = syncForReleaseLocked(mEglDisplay); if (err != NO_ERROR) { - ST_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err); + GLC_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err); return err; } } else { @@ -274,7 +285,7 @@ status_t GLConsumer::releaseTexImage() { err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR); if (err < NO_ERROR) { - ST_LOGE("releaseTexImage: failed to release buffer: %s (%d)", + GLC_LOGE("releaseTexImage: failed to release buffer: %s (%d)", strerror(-err), err); return err; } @@ -293,9 +304,9 @@ status_t GLConsumer::releaseTexImage() { if (mAttached) { // This binds a dummy buffer (mReleasedTexImage). - status_t err = bindTextureImageLocked(); - if (err != NO_ERROR) { - return err; + status_t result = bindTextureImageLocked(); + if (result != NO_ERROR) { + return result; } } else { // detached, don't touch the texture (and we may not even have an @@ -316,14 +327,15 @@ sp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() { GraphicBuffer::USAGE_SW_WRITE_RARELY); uint32_t* bits; buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits)); - size_t w = buffer->getStride(); - size_t h = buffer->getHeight(); - memset(bits, 0, w*h*4); - for (size_t y=0 ; y<kDebugData.height ; y++) { - for (size_t x=0 ; x<kDebugData.width ; x++) { - bits[x] = (kDebugData.bits[y*kDebugData.width+x] == 'X') ? 0xFF000000 : 0xFFFFFFFF; + uint32_t stride = buffer->getStride(); + uint32_t height = buffer->getHeight(); + memset(bits, 0, stride * height * 4); + for (uint32_t y = 0; y < kDebugData.height; y++) { + for (uint32_t x = 0; x < kDebugData.width; x++) { + bits[x] = (kDebugData.bits[y + kDebugData.width + x] == 'X') ? + 0xFF000000 : 0xFFFFFFFF; } - bits += w; + bits += stride; } buffer->unlock(); sReleasedTexImageBuffer = buffer; @@ -331,7 +343,7 @@ sp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() { return sReleasedTexImageBuffer; } -status_t GLConsumer::acquireBufferLocked(BufferQueue::BufferItem *item, +status_t GLConsumer::acquireBufferLocked(BufferItem *item, nsecs_t presentWhen) { status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen); if (err != NO_ERROR) { @@ -362,14 +374,14 @@ status_t GLConsumer::releaseBufferLocked(int buf, return err; } -status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item) +status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item) { status_t err = NO_ERROR; int buf = item.mBuf; if (!mAttached) { - ST_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL " + GLC_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL " "ES context"); releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR); @@ -391,7 +403,7 @@ status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item) // means the buffer was previously acquired). err = mEglSlots[buf].mEglImage->createIfNeeded(mEglDisplay, item.mCrop); if (err != NO_ERROR) { - ST_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d", + GLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d", mEglDisplay, buf); releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR); @@ -410,7 +422,7 @@ status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item) return err; } - ST_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", + GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture, mCurrentTextureImage != NULL ? mCurrentTextureImage->graphicBufferHandle() : 0, buf, mSlots[buf].mGraphicBuffer->handle); @@ -421,7 +433,7 @@ status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item) mCurrentTexture, mCurrentTextureImage->graphicBuffer(), mEglDisplay, mEglSlots[mCurrentTexture].mEglFence); if (status < NO_ERROR) { - ST_LOGE("updateAndRelease: failed to release buffer: %s (%d)", + GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status), status); err = status; // keep going, with error raised [?] @@ -449,22 +461,22 @@ status_t GLConsumer::bindTextureImageLocked() { return INVALID_OPERATION; } - GLint error; + GLenum error; while ((error = glGetError()) != GL_NO_ERROR) { - ST_LOGW("bindTextureImage: clearing GL error: %#04x", error); + GLC_LOGW("bindTextureImage: clearing GL error: %#04x", error); } glBindTexture(mTexTarget, mTexName); if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureImage == NULL) { - ST_LOGE("bindTextureImage: no currently-bound texture"); + GLC_LOGE("bindTextureImage: no currently-bound texture"); return NO_INIT; } status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay, mCurrentCrop); if (err != NO_ERROR) { - ST_LOGW("bindTextureImage: can't create image on display=%p slot=%d", + GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d", mEglDisplay, mCurrentTexture); return UNKNOWN_ERROR; } @@ -476,17 +488,17 @@ status_t GLConsumer::bindTextureImageLocked() { // forcing the creation of a new image. if ((error = glGetError()) != GL_NO_ERROR) { glBindTexture(mTexTarget, mTexName); - status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay, - mCurrentCrop, - true); - if (err != NO_ERROR) { - ST_LOGW("bindTextureImage: can't create image on display=%p slot=%d", + status_t result = mCurrentTextureImage->createIfNeeded(mEglDisplay, + mCurrentCrop, + true); + if (result != NO_ERROR) { + GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d", mEglDisplay, mCurrentTexture); return UNKNOWN_ERROR; } mCurrentTextureImage->bindToTextureTarget(mTexTarget); if ((error = glGetError()) != GL_NO_ERROR) { - ST_LOGE("bindTextureImage: error binding external image: %#04x", error); + GLC_LOGE("bindTextureImage: error binding external image: %#04x", error); return UNKNOWN_ERROR; } } @@ -511,12 +523,12 @@ status_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) { } if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) { - ST_LOGE("checkAndUpdateEglState: invalid current EGLDisplay"); + GLC_LOGE("checkAndUpdateEglState: invalid current EGLDisplay"); return INVALID_OPERATION; } if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) { - ST_LOGE("checkAndUpdateEglState: invalid current EGLContext"); + GLC_LOGE("checkAndUpdateEglState: invalid current EGLContext"); return INVALID_OPERATION; } @@ -531,7 +543,7 @@ void GLConsumer::setReleaseFence(const sp<Fence>& fence) { status_t err = addReleaseFence(mCurrentTexture, mCurrentTextureImage->graphicBuffer(), fence); if (err != OK) { - ST_LOGE("setReleaseFence: failed to add the fence: %s (%d)", + GLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)", strerror(-err), err); } } @@ -539,16 +551,16 @@ void GLConsumer::setReleaseFence(const sp<Fence>& fence) { status_t GLConsumer::detachFromContext() { ATRACE_CALL(); - ST_LOGV("detachFromContext"); + GLC_LOGV("detachFromContext"); Mutex::Autolock lock(mMutex); if (mAbandoned) { - ST_LOGE("detachFromContext: abandoned GLConsumer"); + GLC_LOGE("detachFromContext: abandoned GLConsumer"); return NO_INIT; } if (!mAttached) { - ST_LOGE("detachFromContext: GLConsumer is not attached to a " + GLC_LOGE("detachFromContext: GLConsumer is not attached to a " "context"); return INVALID_OPERATION; } @@ -557,12 +569,12 @@ status_t GLConsumer::detachFromContext() { EGLContext ctx = eglGetCurrentContext(); if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) { - ST_LOGE("detachFromContext: invalid current EGLDisplay"); + GLC_LOGE("detachFromContext: invalid current EGLDisplay"); return INVALID_OPERATION; } if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) { - ST_LOGE("detachFromContext: invalid current EGLContext"); + GLC_LOGE("detachFromContext: invalid current EGLContext"); return INVALID_OPERATION; } @@ -584,16 +596,16 @@ status_t GLConsumer::detachFromContext() { status_t GLConsumer::attachToContext(uint32_t tex) { ATRACE_CALL(); - ST_LOGV("attachToContext"); + GLC_LOGV("attachToContext"); Mutex::Autolock lock(mMutex); if (mAbandoned) { - ST_LOGE("attachToContext: abandoned GLConsumer"); + GLC_LOGE("attachToContext: abandoned GLConsumer"); return NO_INIT; } if (mAttached) { - ST_LOGE("attachToContext: GLConsumer is already attached to a " + GLC_LOGE("attachToContext: GLConsumer is already attached to a " "context"); return INVALID_OPERATION; } @@ -602,12 +614,12 @@ status_t GLConsumer::attachToContext(uint32_t tex) { EGLContext ctx = eglGetCurrentContext(); if (dpy == EGL_NO_DISPLAY) { - ST_LOGE("attachToContext: invalid current EGLDisplay"); + GLC_LOGE("attachToContext: invalid current EGLDisplay"); return INVALID_OPERATION; } if (ctx == EGL_NO_CONTEXT) { - ST_LOGE("attachToContext: invalid current EGLContext"); + GLC_LOGE("attachToContext: invalid current EGLContext"); return INVALID_OPERATION; } @@ -636,14 +648,14 @@ status_t GLConsumer::attachToContext(uint32_t tex) { status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) { - ST_LOGV("syncForReleaseLocked"); + GLC_LOGV("syncForReleaseLocked"); if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { if (SyncFeatures::getInstance().useNativeFenceSync()) { EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); if (sync == EGL_NO_SYNC_KHR) { - ST_LOGE("syncForReleaseLocked: error creating EGL fence: %#x", + GLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x", eglGetError()); return UNKNOWN_ERROR; } @@ -651,7 +663,7 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) { int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync); eglDestroySyncKHR(dpy, sync); if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { - ST_LOGE("syncForReleaseLocked: error dup'ing native fence " + GLC_LOGE("syncForReleaseLocked: error dup'ing native fence " "fd: %#x", eglGetError()); return UNKNOWN_ERROR; } @@ -659,7 +671,7 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) { status_t err = addReleaseFenceLocked(mCurrentTexture, mCurrentTextureImage->graphicBuffer(), fence); if (err != OK) { - ST_LOGE("syncForReleaseLocked: error adding release fence: " + GLC_LOGE("syncForReleaseLocked: error adding release fence: " "%s (%d)", strerror(-err), err); return err; } @@ -672,11 +684,11 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) { // before the producer accesses it. EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000); if (result == EGL_FALSE) { - ST_LOGE("syncForReleaseLocked: error waiting for previous " + GLC_LOGE("syncForReleaseLocked: error waiting for previous " "fence: %#x", eglGetError()); return UNKNOWN_ERROR; } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { - ST_LOGE("syncForReleaseLocked: timeout waiting for previous " + GLC_LOGE("syncForReleaseLocked: timeout waiting for previous " "fence"); return TIMED_OUT; } @@ -687,7 +699,7 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) { // OpenGL ES context. fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); if (fence == EGL_NO_SYNC_KHR) { - ST_LOGE("syncForReleaseLocked: error creating fence: %#x", + GLC_LOGE("syncForReleaseLocked: error creating fence: %#x", eglGetError()); return UNKNOWN_ERROR; } @@ -699,7 +711,7 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) { return OK; } -bool GLConsumer::isExternalFormat(uint32_t format) +bool GLConsumer::isExternalFormat(PixelFormat format) { switch (format) { // supported YUV formats @@ -730,14 +742,14 @@ void GLConsumer::getTransformMatrix(float mtx[16]) { void GLConsumer::setFilteringEnabled(bool enabled) { Mutex::Autolock lock(mMutex); if (mAbandoned) { - ST_LOGE("setFilteringEnabled: GLConsumer is abandoned!"); + GLC_LOGE("setFilteringEnabled: GLConsumer is abandoned!"); return; } bool needsRecompute = mFilteringEnabled != enabled; mFilteringEnabled = enabled; if (needsRecompute && mCurrentTextureImage==NULL) { - ST_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL"); + GLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL"); } if (needsRecompute && mCurrentTextureImage != NULL) { @@ -746,7 +758,7 @@ void GLConsumer::setFilteringEnabled(bool enabled) { } void GLConsumer::computeCurrentTransformMatrixLocked() { - ST_LOGV("computeCurrentTransformMatrixLocked"); + GLC_LOGV("computeCurrentTransformMatrixLocked"); float xform[16]; for (int i = 0; i < 16; i++) { @@ -778,7 +790,7 @@ void GLConsumer::computeCurrentTransformMatrixLocked() { NULL : mCurrentTextureImage->graphicBuffer(); if (buf == NULL) { - ST_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureImage is NULL"); + GLC_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureImage is NULL"); } float mtxBeforeFlipV[16]; @@ -850,13 +862,13 @@ void GLConsumer::computeCurrentTransformMatrixLocked() { } nsecs_t GLConsumer::getTimestamp() { - ST_LOGV("getTimestamp"); + GLC_LOGV("getTimestamp"); Mutex::Autolock lock(mMutex); return mCurrentTimestamp; } -nsecs_t GLConsumer::getFrameNumber() { - ST_LOGV("getFrameNumber"); +uint64_t GLConsumer::getFrameNumber() { + GLC_LOGV("getFrameNumber"); Mutex::Autolock lock(mMutex); return mCurrentFrameNumber; } @@ -872,30 +884,33 @@ Rect GLConsumer::getCurrentCrop() const { Rect outCrop = mCurrentCrop; if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) { - int32_t newWidth = mCurrentCrop.width(); - int32_t newHeight = mCurrentCrop.height(); + uint32_t newWidth = static_cast<uint32_t>(mCurrentCrop.width()); + uint32_t newHeight = static_cast<uint32_t>(mCurrentCrop.height()); if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) { newWidth = newHeight * mDefaultWidth / mDefaultHeight; - ST_LOGV("too wide: newWidth = %d", newWidth); + GLC_LOGV("too wide: newWidth = %d", newWidth); } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) { newHeight = newWidth * mDefaultHeight / mDefaultWidth; - ST_LOGV("too tall: newHeight = %d", newHeight); + GLC_LOGV("too tall: newHeight = %d", newHeight); } + uint32_t currentWidth = static_cast<uint32_t>(mCurrentCrop.width()); + uint32_t currentHeight = static_cast<uint32_t>(mCurrentCrop.height()); + // The crop is too wide - if (newWidth < mCurrentCrop.width()) { - int32_t dw = (newWidth - mCurrentCrop.width())/2; - outCrop.left -=dw; - outCrop.right += dw; + if (newWidth < currentWidth) { + uint32_t dw = (currentWidth - newWidth) / 2; + outCrop.left += dw; + outCrop.right -= dw; // The crop is too tall - } else if (newHeight < mCurrentCrop.height()) { - int32_t dh = (newHeight - mCurrentCrop.height())/2; - outCrop.top -= dh; - outCrop.bottom += dh; + } else if (newHeight < currentHeight) { + uint32_t dh = (currentHeight - newHeight) / 2; + outCrop.top += dh; + outCrop.bottom -= dh; } - ST_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]", + GLC_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]", outCrop.left, outCrop.top, outCrop.right,outCrop.bottom); } @@ -929,12 +944,12 @@ status_t GLConsumer::doGLFenceWaitLocked() const { EGLContext ctx = eglGetCurrentContext(); if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) { - ST_LOGE("doGLFenceWait: invalid current EGLDisplay"); + GLC_LOGE("doGLFenceWait: invalid current EGLDisplay"); return INVALID_OPERATION; } if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) { - ST_LOGE("doGLFenceWait: invalid current EGLContext"); + GLC_LOGE("doGLFenceWait: invalid current EGLContext"); return INVALID_OPERATION; } @@ -943,7 +958,7 @@ status_t GLConsumer::doGLFenceWaitLocked() const { // Create an EGLSyncKHR from the current fence. int fenceFd = mCurrentFence->dup(); if (fenceFd == -1) { - ST_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno); + GLC_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno); return -errno; } EGLint attribs[] = { @@ -954,7 +969,7 @@ status_t GLConsumer::doGLFenceWaitLocked() const { EGL_SYNC_NATIVE_FENCE_ANDROID, attribs); if (sync == EGL_NO_SYNC_KHR) { close(fenceFd); - ST_LOGE("doGLFenceWait: error creating EGL fence: %#x", + GLC_LOGE("doGLFenceWait: error creating EGL fence: %#x", eglGetError()); return UNKNOWN_ERROR; } @@ -966,7 +981,7 @@ status_t GLConsumer::doGLFenceWaitLocked() const { EGLint eglErr = eglGetError(); eglDestroySyncKHR(dpy, sync); if (eglErr != EGL_SUCCESS) { - ST_LOGE("doGLFenceWait: error waiting for EGL fence: %#x", + GLC_LOGE("doGLFenceWait: error waiting for EGL fence: %#x", eglErr); return UNKNOWN_ERROR; } @@ -974,7 +989,7 @@ status_t GLConsumer::doGLFenceWaitLocked() const { status_t err = mCurrentFence->waitForever( "GLConsumer::doGLFenceWaitLocked"); if (err != NO_ERROR) { - ST_LOGE("doGLFenceWait: error waiting for fence: %d", err); + GLC_LOGE("doGLFenceWait: error waiting for fence: %d", err); return err; } } @@ -984,7 +999,7 @@ status_t GLConsumer::doGLFenceWaitLocked() const { } void GLConsumer::freeBufferLocked(int slotIndex) { - ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex); + GLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex); if (slotIndex == mCurrentTexture) { mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT; } @@ -993,7 +1008,7 @@ void GLConsumer::freeBufferLocked(int slotIndex) { } void GLConsumer::abandonLocked() { - ST_LOGV("abandonLocked"); + GLC_LOGV("abandonLocked"); mCurrentTextureImage.clear(); ConsumerBase::abandonLocked(); } @@ -1004,11 +1019,17 @@ void GLConsumer::setName(const String8& name) { mConsumer->setConsumerName(name); } -status_t GLConsumer::setDefaultBufferFormat(uint32_t defaultFormat) { +status_t GLConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) { Mutex::Autolock lock(mMutex); return mConsumer->setDefaultBufferFormat(defaultFormat); } +status_t GLConsumer::setDefaultBufferDataSpace( + android_dataspace defaultDataSpace) { + Mutex::Autolock lock(mMutex); + return mConsumer->setDefaultBufferDataSpace(defaultDataSpace); +} + status_t GLConsumer::setConsumerUsageBits(uint32_t usage) { Mutex::Autolock lock(mMutex); usage |= DEFAULT_USAGE_FLAGS; @@ -1107,12 +1128,14 @@ status_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay, } void GLConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) { - glEGLImageTargetTexture2DOES(texTarget, (GLeglImageOES)mEglImage); + glEGLImageTargetTexture2DOES(texTarget, + static_cast<GLeglImageOES>(mEglImage)); } EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy, const sp<GraphicBuffer>& graphicBuffer, const Rect& crop) { - EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer(); + EGLClientBuffer cbuf = + static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer()); EGLint attrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_IMAGE_CROP_LEFT_ANDROID, crop.left, diff --git a/libs/gui/GraphicBufferAlloc.cpp b/libs/gui/GraphicBufferAlloc.cpp index b360e81..9643402 100644 --- a/libs/gui/GraphicBufferAlloc.cpp +++ b/libs/gui/GraphicBufferAlloc.cpp @@ -31,9 +31,10 @@ GraphicBufferAlloc::GraphicBufferAlloc() { GraphicBufferAlloc::~GraphicBufferAlloc() { } -sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage, status_t* error) { - sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage)); +sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t width, + uint32_t height, PixelFormat format, uint32_t usage, status_t* error) { + sp<GraphicBuffer> graphicBuffer( + new GraphicBuffer(width, height, format, usage)); status_t err = graphicBuffer->initCheck(); *error = err; if (err != 0 || graphicBuffer->handle == 0) { @@ -42,7 +43,7 @@ sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h } ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) " "failed (%s), handle=%p", - w, h, strerror(-err), graphicBuffer->handle); + width, height, strerror(-err), graphicBuffer->handle); return 0; } return graphicBuffer; diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp index 409dfe4..cab7dc3 100644 --- a/libs/gui/IConsumerListener.cpp +++ b/libs/gui/IConsumerListener.cpp @@ -40,6 +40,8 @@ public: : BpInterface<IConsumerListener>(impl) { } + virtual ~BpConsumerListener(); + virtual void onFrameAvailable(const BufferItem& item) { Parcel data, reply; data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor()); @@ -60,6 +62,10 @@ public: } }; +// Out-of-line virtual method definition to trigger vtable emission in this +// translation unit (see clang warning -Wweak-vtables) +BpConsumerListener::~BpConsumerListener() {} + IMPLEMENT_META_INTERFACE(ConsumerListener, "android.gui.IConsumerListener"); // ---------------------------------------------------------------------- diff --git a/libs/gui/IDisplayEventConnection.cpp b/libs/gui/IDisplayEventConnection.cpp index 887d176..9890f44 100644 --- a/libs/gui/IDisplayEventConnection.cpp +++ b/libs/gui/IDisplayEventConnection.cpp @@ -44,6 +44,8 @@ public: { } + virtual ~BpDisplayEventConnection(); + virtual sp<BitTube> getDataChannel() const { Parcel data, reply; @@ -55,7 +57,7 @@ public: virtual void setVsyncRate(uint32_t count) { Parcel data, reply; data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor()); - data.writeInt32(count); + data.writeUint32(count); remote()->transact(SET_VSYNC_RATE, data, &reply); } @@ -66,6 +68,10 @@ public: } }; +// Out-of-line virtual method definition to trigger vtable emission in this +// translation unit (see clang warning -Wweak-vtables) +BpDisplayEventConnection::~BpDisplayEventConnection() {} + IMPLEMENT_META_INTERFACE(DisplayEventConnection, "android.gui.DisplayEventConnection"); // ---------------------------------------------------------------------------- @@ -79,17 +85,17 @@ status_t BnDisplayEventConnection::onTransact( sp<BitTube> channel(getDataChannel()); channel->writeToParcel(reply); return NO_ERROR; - } break; + } case SET_VSYNC_RATE: { CHECK_INTERFACE(IDisplayEventConnection, data, reply); - setVsyncRate(data.readInt32()); + setVsyncRate(data.readUint32()); return NO_ERROR; - } break; + } case REQUEST_NEXT_VSYNC: { CHECK_INTERFACE(IDisplayEventConnection, data, reply); requestNextVsync(); return NO_ERROR; - } break; + } } return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp index 139f219..09b63a1 100644 --- a/libs/gui/IGraphicBufferAlloc.cpp +++ b/libs/gui/IGraphicBufferAlloc.cpp @@ -42,14 +42,17 @@ public: { } - virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage, status_t* error) { + virtual ~BpGraphicBufferAlloc(); + + virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t width, + uint32_t height, PixelFormat format, uint32_t usage, + status_t* error) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor()); - data.writeInt32(w); - data.writeInt32(h); - data.writeInt32(format); - data.writeInt32(usage); + data.writeUint32(width); + data.writeUint32(height); + data.writeInt32(static_cast<int32_t>(format)); + data.writeUint32(usage); remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply); sp<GraphicBuffer> graphicBuffer; status_t result = reply.readInt32(); @@ -65,6 +68,10 @@ public: } }; +// Out-of-line virtual method definition to trigger vtable emission in this +// translation unit (see clang warning -Wweak-vtables) +BpGraphicBufferAlloc::~BpGraphicBufferAlloc() {} + IMPLEMENT_META_INTERFACE(GraphicBufferAlloc, "android.ui.IGraphicBufferAlloc"); // ---------------------------------------------------------------------- @@ -74,27 +81,26 @@ status_t BnGraphicBufferAlloc::onTransact( { // codes that don't require permission check - /* BufferReference just keeps a strong reference to a - * GraphicBuffer until it is destroyed (that is, until - * no local or remote process have a reference to it). - */ + // BufferReference just keeps a strong reference to a GraphicBuffer until it + // is destroyed (that is, until no local or remote process have a reference + // to it). class BufferReference : public BBinder { - sp<GraphicBuffer> buffer; + sp<GraphicBuffer> mBuffer; public: - BufferReference(const sp<GraphicBuffer>& buffer) : buffer(buffer) { } + BufferReference(const sp<GraphicBuffer>& buffer) : mBuffer(buffer) {} }; - switch(code) { + switch (code) { case CREATE_GRAPHIC_BUFFER: { CHECK_INTERFACE(IGraphicBufferAlloc, data, reply); - uint32_t w = data.readInt32(); - uint32_t h = data.readInt32(); - PixelFormat format = data.readInt32(); - uint32_t usage = data.readInt32(); + uint32_t width = data.readUint32(); + uint32_t height = data.readUint32(); + PixelFormat format = static_cast<PixelFormat>(data.readInt32()); + uint32_t usage = data.readUint32(); status_t error; sp<GraphicBuffer> result = - createGraphicBuffer(w, h, format, usage, &error); + createGraphicBuffer(width, height, format, usage, &error); reply->writeInt32(error); if (result != 0) { reply->write(*result); @@ -107,7 +113,7 @@ status_t BnGraphicBufferAlloc::onTransact( reply->writeStrongBinder( new BufferReference(result) ); } return NO_ERROR; - } break; + } default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp index dc917a8..3c0907a 100644 --- a/libs/gui/IGraphicBufferConsumer.cpp +++ b/libs/gui/IGraphicBufferConsumer.cpp @@ -23,6 +23,7 @@ #include <binder/Parcel.h> #include <binder/IInterface.h> +#include <gui/BufferItem.h> #include <gui/IConsumerListener.h> #include <gui/IGraphicBufferConsumer.h> @@ -32,159 +33,6 @@ #include <system/window.h> namespace android { -// --------------------------------------------------------------------------- - -IGraphicBufferConsumer::BufferItem::BufferItem() : - mTransform(0), - mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), - mTimestamp(0), - mIsAutoTimestamp(false), - mFrameNumber(0), - mBuf(INVALID_BUFFER_SLOT), - mIsDroppable(false), - mAcquireCalled(false), - mTransformToDisplayInverse(false) { - mCrop.makeInvalid(); -} - -size_t IGraphicBufferConsumer::BufferItem::getPodSize() const { - size_t c = sizeof(mCrop) + - sizeof(mTransform) + - sizeof(mScalingMode) + - sizeof(mTimestamp) + - sizeof(mIsAutoTimestamp) + - sizeof(mFrameNumber) + - sizeof(mBuf) + - sizeof(mIsDroppable) + - sizeof(mAcquireCalled) + - sizeof(mTransformToDisplayInverse); - return c; -} - -size_t IGraphicBufferConsumer::BufferItem::getFlattenedSize() const { - size_t c = 0; - if (mGraphicBuffer != 0) { - c += mGraphicBuffer->getFlattenedSize(); - c = FlattenableUtils::align<4>(c); - } - if (mFence != 0) { - c += mFence->getFlattenedSize(); - c = FlattenableUtils::align<4>(c); - } - return sizeof(int32_t) + c + getPodSize(); -} - -size_t IGraphicBufferConsumer::BufferItem::getFdCount() const { - size_t c = 0; - if (mGraphicBuffer != 0) { - c += mGraphicBuffer->getFdCount(); - } - if (mFence != 0) { - c += mFence->getFdCount(); - } - return c; -} - -static void writeBoolAsInt(void*& buffer, size_t& size, bool b) { - FlattenableUtils::write(buffer, size, static_cast<int32_t>(b)); -} - -static bool readBoolFromInt(void const*& buffer, size_t& size) { - int32_t i; - FlattenableUtils::read(buffer, size, i); - return static_cast<bool>(i); -} - -status_t IGraphicBufferConsumer::BufferItem::flatten( - void*& buffer, size_t& size, int*& fds, size_t& count) const { - - // make sure we have enough space - if (size < BufferItem::getFlattenedSize()) { - return NO_MEMORY; - } - - // content flags are stored first - uint32_t& flags = *static_cast<uint32_t*>(buffer); - - // advance the pointer - FlattenableUtils::advance(buffer, size, sizeof(uint32_t)); - - flags = 0; - if (mGraphicBuffer != 0) { - status_t err = mGraphicBuffer->flatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - flags |= 1; - } - if (mFence != 0) { - status_t err = mFence->flatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - flags |= 2; - } - - // check we have enough space (in case flattening the fence/graphicbuffer lied to us) - if (size < getPodSize()) { - return NO_MEMORY; - } - - FlattenableUtils::write(buffer, size, mCrop); - FlattenableUtils::write(buffer, size, mTransform); - FlattenableUtils::write(buffer, size, mScalingMode); - FlattenableUtils::write(buffer, size, mTimestamp); - writeBoolAsInt(buffer, size, mIsAutoTimestamp); - FlattenableUtils::write(buffer, size, mFrameNumber); - FlattenableUtils::write(buffer, size, mBuf); - writeBoolAsInt(buffer, size, mIsDroppable); - writeBoolAsInt(buffer, size, mAcquireCalled); - writeBoolAsInt(buffer, size, mTransformToDisplayInverse); - - return NO_ERROR; -} - -status_t IGraphicBufferConsumer::BufferItem::unflatten( - void const*& buffer, size_t& size, int const*& fds, size_t& count) { - - if (size < sizeof(uint32_t)) - return NO_MEMORY; - - uint32_t flags = 0; - FlattenableUtils::read(buffer, size, flags); - - if (flags & 1) { - mGraphicBuffer = new GraphicBuffer(); - status_t err = mGraphicBuffer->unflatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - } - - if (flags & 2) { - mFence = new Fence(); - status_t err = mFence->unflatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - } - - // check we have enough space - if (size < getPodSize()) { - return NO_MEMORY; - } - - FlattenableUtils::read(buffer, size, mCrop); - FlattenableUtils::read(buffer, size, mTransform); - FlattenableUtils::read(buffer, size, mScalingMode); - FlattenableUtils::read(buffer, size, mTimestamp); - mIsAutoTimestamp = readBoolFromInt(buffer, size); - FlattenableUtils::read(buffer, size, mFrameNumber); - FlattenableUtils::read(buffer, size, mBuf); - mIsDroppable = readBoolFromInt(buffer, size); - mAcquireCalled = readBoolFromInt(buffer, size); - mTransformToDisplayInverse = readBoolFromInt(buffer, size); - - return NO_ERROR; -} - -// --------------------------------------------------------------------------- enum { ACQUIRE_BUFFER = IBinder::FIRST_CALL_TRANSACTION, @@ -200,6 +48,7 @@ enum { SET_MAX_ACQUIRED_BUFFER_COUNT, SET_CONSUMER_NAME, SET_DEFAULT_BUFFER_FORMAT, + SET_DEFAULT_BUFFER_DATA_SPACE, SET_CONSUMER_USAGE_BITS, SET_TRANSFORM_HINT, GET_SIDEBAND_STREAM, @@ -215,6 +64,8 @@ public: { } + virtual ~BpGraphicBufferConsumer(); + virtual status_t acquireBuffer(BufferItem *buffer, nsecs_t presentWhen) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor()); @@ -261,7 +112,7 @@ public: Parcel data, reply; data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor()); data.writeInt32(buf); - data.writeInt64(frameNumber); + data.writeInt64(static_cast<int64_t>(frameNumber)); data.write(*releaseFence); status_t result = remote()->transact(RELEASE_BUFFER, data, &reply); if (result != NO_ERROR) { @@ -273,7 +124,7 @@ public: virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeStrongBinder(consumer->asBinder()); + data.writeStrongBinder(IInterface::asBinder(consumer)); data.writeInt32(controlledByApp); status_t result = remote()->transact(CONSUMER_CONNECT, data, &reply); if (result != NO_ERROR) { @@ -303,15 +154,15 @@ public: if (result != NO_ERROR) { return result; } - *slotMask = reply.readInt64(); + *slotMask = static_cast<uint64_t>(reply.readInt64()); return reply.readInt32(); } - virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) { + virtual status_t setDefaultBufferSize(uint32_t width, uint32_t height) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(w); - data.writeInt32(h); + data.writeUint32(width); + data.writeUint32(height); status_t result = remote()->transact(SET_DEFAULT_BUFFER_SIZE, data, &reply); if (result != NO_ERROR) { return result; @@ -358,10 +209,10 @@ public: remote()->transact(SET_CONSUMER_NAME, data, &reply); } - virtual status_t setDefaultBufferFormat(uint32_t defaultFormat) { + virtual status_t setDefaultBufferFormat(PixelFormat defaultFormat) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(defaultFormat); + data.writeInt32(static_cast<int32_t>(defaultFormat)); status_t result = remote()->transact(SET_DEFAULT_BUFFER_FORMAT, data, &reply); if (result != NO_ERROR) { return result; @@ -369,10 +220,23 @@ public: return reply.readInt32(); } + virtual status_t setDefaultBufferDataSpace( + android_dataspace defaultDataSpace) { + Parcel data, reply; + data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor()); + data.writeInt32(static_cast<int32_t>(defaultDataSpace)); + status_t result = remote()->transact(SET_DEFAULT_BUFFER_DATA_SPACE, + data, &reply); + if (result != NO_ERROR) { + return result; + } + return reply.readInt32(); + } + virtual status_t setConsumerUsageBits(uint32_t usage) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(usage); + data.writeUint32(usage); status_t result = remote()->transact(SET_CONSUMER_USAGE_BITS, data, &reply); if (result != NO_ERROR) { return result; @@ -383,7 +247,7 @@ public: virtual status_t setTransformHint(uint32_t hint) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor()); - data.writeInt32(hint); + data.writeUint32(hint); status_t result = remote()->transact(SET_TRANSFORM_HINT, data, &reply); if (result != NO_ERROR) { return result; @@ -415,6 +279,10 @@ public: } }; +// Out-of-line virtual method definition to trigger vtable emission in this +// translation unit (see clang warning -Wweak-vtables) +BpGraphicBufferConsumer::~BpGraphicBufferConsumer() {} + IMPLEMENT_META_INTERFACE(GraphicBufferConsumer, "android.gui.IGraphicBufferConsumer"); // ---------------------------------------------------------------------- @@ -432,14 +300,14 @@ status_t BnGraphicBufferConsumer::onTransact( if (err) return err; reply->writeInt32(result); return NO_ERROR; - } break; + } case DETACH_BUFFER: { CHECK_INTERFACE(IGraphicBufferConsumer, data, reply); int slot = data.readInt32(); int result = detachBuffer(slot); reply->writeInt32(result); return NO_ERROR; - } break; + } case ATTACH_BUFFER: { CHECK_INTERFACE(IGraphicBufferConsumer, data, reply); sp<GraphicBuffer> buffer = new GraphicBuffer(); @@ -449,11 +317,11 @@ status_t BnGraphicBufferConsumer::onTransact( reply->writeInt32(slot); reply->writeInt32(result); return NO_ERROR; - } break; + } case RELEASE_BUFFER: { CHECK_INTERFACE(IGraphicBufferConsumer, data, reply); int buf = data.readInt32(); - uint64_t frameNumber = data.readInt64(); + uint64_t frameNumber = static_cast<uint64_t>(data.readInt64()); sp<Fence> releaseFence = new Fence(); status_t err = data.read(*releaseFence); if (err) return err; @@ -461,7 +329,7 @@ status_t BnGraphicBufferConsumer::onTransact( EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, releaseFence); reply->writeInt32(result); return NO_ERROR; - } break; + } case CONSUMER_CONNECT: { CHECK_INTERFACE(IGraphicBufferConsumer, data, reply); sp<IConsumerListener> consumer = IConsumerListener::asInterface( data.readStrongBinder() ); @@ -469,75 +337,83 @@ status_t BnGraphicBufferConsumer::onTransact( status_t result = consumerConnect(consumer, controlledByApp); reply->writeInt32(result); return NO_ERROR; - } break; + } case CONSUMER_DISCONNECT: { CHECK_INTERFACE(IGraphicBufferConsumer, data, reply); status_t result = consumerDisconnect(); reply->writeInt32(result); return NO_ERROR; - } break; + } case GET_RELEASED_BUFFERS: { CHECK_INTERFACE(IGraphicBufferConsumer, data, reply); uint64_t slotMask; status_t result = getReleasedBuffers(&slotMask); - reply->writeInt64(slotMask); + reply->writeInt64(static_cast<int64_t>(slotMask)); reply->writeInt32(result); return NO_ERROR; - } break; + } case SET_DEFAULT_BUFFER_SIZE: { CHECK_INTERFACE(IGraphicBufferConsumer, data, reply); - uint32_t w = data.readInt32(); - uint32_t h = data.readInt32(); - status_t result = setDefaultBufferSize(w, h); + uint32_t width = data.readUint32(); + uint32_t height = data.readUint32(); + status_t result = setDefaultBufferSize(width, height); reply->writeInt32(result); return NO_ERROR; - } break; + } case SET_DEFAULT_MAX_BUFFER_COUNT: { CHECK_INTERFACE(IGraphicBufferConsumer, data, reply); - uint32_t bufferCount = data.readInt32(); + int bufferCount = data.readInt32(); status_t result = setDefaultMaxBufferCount(bufferCount); reply->writeInt32(result); return NO_ERROR; - } break; + } case DISABLE_ASYNC_BUFFER: { CHECK_INTERFACE(IGraphicBufferConsumer, data, reply); status_t result = disableAsyncBuffer(); reply->writeInt32(result); return NO_ERROR; - } break; + } case SET_MAX_ACQUIRED_BUFFER_COUNT: { CHECK_INTERFACE(IGraphicBufferConsumer, data, reply); - uint32_t maxAcquiredBuffers = data.readInt32(); + int maxAcquiredBuffers = data.readInt32(); status_t result = setMaxAcquiredBufferCount(maxAcquiredBuffers); reply->writeInt32(result); return NO_ERROR; - } break; + } case SET_CONSUMER_NAME: { CHECK_INTERFACE(IGraphicBufferConsumer, data, reply); setConsumerName( data.readString8() ); return NO_ERROR; - } break; + } case SET_DEFAULT_BUFFER_FORMAT: { CHECK_INTERFACE(IGraphicBufferConsumer, data, reply); - uint32_t defaultFormat = data.readInt32(); + PixelFormat defaultFormat = static_cast<PixelFormat>(data.readInt32()); status_t result = setDefaultBufferFormat(defaultFormat); reply->writeInt32(result); return NO_ERROR; - } break; + } + case SET_DEFAULT_BUFFER_DATA_SPACE: { + CHECK_INTERFACE(IGraphicBufferConsumer, data, reply); + android_dataspace defaultDataSpace = + static_cast<android_dataspace>(data.readInt32()); + status_t result = setDefaultBufferDataSpace(defaultDataSpace); + reply->writeInt32(result); + return NO_ERROR; + } case SET_CONSUMER_USAGE_BITS: { CHECK_INTERFACE(IGraphicBufferConsumer, data, reply); - uint32_t usage = data.readInt32(); + uint32_t usage = data.readUint32(); status_t result = setConsumerUsageBits(usage); reply->writeInt32(result); return NO_ERROR; - } break; + } case SET_TRANSFORM_HINT: { CHECK_INTERFACE(IGraphicBufferConsumer, data, reply); - uint32_t hint = data.readInt32(); + uint32_t hint = data.readUint32(); status_t result = setTransformHint(hint); reply->writeInt32(result); return NO_ERROR; - } break; + } case DUMP: { CHECK_INTERFACE(IGraphicBufferConsumer, data, reply); String8 result = data.readString8(); diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index 67690b7..ec05f60 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -46,6 +46,7 @@ enum { DISCONNECT, SET_SIDEBAND_STREAM, ALLOCATE_BUFFERS, + ALLOW_ALLOCATION, }; class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer> @@ -56,6 +57,8 @@ public: { } + virtual ~BpGraphicBufferProducer(); + virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); @@ -91,14 +94,15 @@ public: } virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async, - uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { + uint32_t width, uint32_t height, PixelFormat format, + uint32_t usage) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); - data.writeInt32(async); - data.writeInt32(w); - data.writeInt32(h); - data.writeInt32(format); - data.writeInt32(usage); + data.writeInt32(static_cast<int32_t>(async)); + data.writeUint32(width); + data.writeUint32(height); + data.writeInt32(static_cast<int32_t>(format)); + data.writeUint32(usage); status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply); if (result != NO_ERROR) { return result; @@ -211,7 +215,7 @@ public: data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); if (listener != NULL) { data.writeInt32(1); - data.writeStrongBinder(listener->asBinder()); + data.writeStrongBinder(IInterface::asBinder(listener)); } else { data.writeInt32(0); } @@ -255,21 +259,37 @@ public: } virtual void allocateBuffers(bool async, uint32_t width, uint32_t height, - uint32_t format, uint32_t usage) { + PixelFormat format, uint32_t usage) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); data.writeInt32(static_cast<int32_t>(async)); - data.writeInt32(static_cast<int32_t>(width)); - data.writeInt32(static_cast<int32_t>(height)); + data.writeUint32(width); + data.writeUint32(height); data.writeInt32(static_cast<int32_t>(format)); - data.writeInt32(static_cast<int32_t>(usage)); + data.writeUint32(usage); status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply); if (result != NO_ERROR) { ALOGE("allocateBuffers failed to transact: %d", result); } } + + virtual status_t allowAllocation(bool allow) { + Parcel data, reply; + data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); + data.writeInt32(static_cast<int32_t>(allow)); + status_t result = remote()->transact(ALLOW_ALLOCATION, data, &reply); + if (result != NO_ERROR) { + return result; + } + result = reply.readInt32(); + return result; + } }; +// Out-of-line virtual method definition to trigger vtable emission in this +// translation unit (see clang warning -Wweak-vtables) +BpGraphicBufferProducer::~BpGraphicBufferProducer() {} + IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer"); // ---------------------------------------------------------------------- @@ -289,24 +309,25 @@ status_t BnGraphicBufferProducer::onTransact( } reply->writeInt32(result); return NO_ERROR; - } break; + } case SET_BUFFER_COUNT: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); int bufferCount = data.readInt32(); int result = setBufferCount(bufferCount); reply->writeInt32(result); return NO_ERROR; - } break; + } case DEQUEUE_BUFFER: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); - bool async = data.readInt32(); - uint32_t w = data.readInt32(); - uint32_t h = data.readInt32(); - uint32_t format = data.readInt32(); - uint32_t usage = data.readInt32(); + bool async = static_cast<bool>(data.readInt32()); + uint32_t width = data.readUint32(); + uint32_t height = data.readUint32(); + PixelFormat format = static_cast<PixelFormat>(data.readInt32()); + uint32_t usage = data.readUint32(); int buf = 0; sp<Fence> fence; - int result = dequeueBuffer(&buf, &fence, async, w, h, format, usage); + int result = dequeueBuffer(&buf, &fence, async, width, height, + format, usage); reply->writeInt32(buf); reply->writeInt32(fence != NULL); if (fence != NULL) { @@ -314,14 +335,14 @@ status_t BnGraphicBufferProducer::onTransact( } reply->writeInt32(result); return NO_ERROR; - } break; + } case DETACH_BUFFER: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); int slot = data.readInt32(); int result = detachBuffer(slot); reply->writeInt32(result); return NO_ERROR; - } break; + } case DETACH_NEXT_BUFFER: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); sp<GraphicBuffer> buffer; @@ -339,7 +360,7 @@ status_t BnGraphicBufferProducer::onTransact( } } return NO_ERROR; - } break; + } case ATTACH_BUFFER: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); sp<GraphicBuffer> buffer = new GraphicBuffer(); @@ -349,7 +370,7 @@ status_t BnGraphicBufferProducer::onTransact( reply->writeInt32(slot); reply->writeInt32(result); return NO_ERROR; - } break; + } case QUEUE_BUFFER: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); int buf = data.readInt32(); @@ -361,7 +382,7 @@ status_t BnGraphicBufferProducer::onTransact( status_t result = queueBuffer(buf, input, output); reply->writeInt32(result); return NO_ERROR; - } break; + } case CANCEL_BUFFER: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); int buf = data.readInt32(); @@ -369,7 +390,7 @@ status_t BnGraphicBufferProducer::onTransact( data.read(*fence.get()); cancelBuffer(buf, fence); return NO_ERROR; - } break; + } case QUERY: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); int value = 0; @@ -378,7 +399,7 @@ status_t BnGraphicBufferProducer::onTransact( reply->writeInt32(value); reply->writeInt32(res); return NO_ERROR; - } break; + } case CONNECT: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); sp<IProducerListener> listener; @@ -393,14 +414,14 @@ status_t BnGraphicBufferProducer::onTransact( status_t res = connect(listener, api, producerControlledByApp, output); reply->writeInt32(res); return NO_ERROR; - } break; + } case DISCONNECT: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); int api = data.readInt32(); status_t res = disconnect(api); reply->writeInt32(res); return NO_ERROR; - } break; + } case SET_SIDEBAND_STREAM: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); sp<NativeHandle> stream; @@ -410,16 +431,24 @@ status_t BnGraphicBufferProducer::onTransact( status_t result = setSidebandStream(stream); reply->writeInt32(result); return NO_ERROR; - } break; - case ALLOCATE_BUFFERS: + } + case ALLOCATE_BUFFERS: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); bool async = static_cast<bool>(data.readInt32()); - uint32_t width = static_cast<uint32_t>(data.readInt32()); - uint32_t height = static_cast<uint32_t>(data.readInt32()); - uint32_t format = static_cast<uint32_t>(data.readInt32()); - uint32_t usage = static_cast<uint32_t>(data.readInt32()); + uint32_t width = data.readUint32(); + uint32_t height = data.readUint32(); + PixelFormat format = static_cast<PixelFormat>(data.readInt32()); + uint32_t usage = data.readUint32(); allocateBuffers(async, width, height, format, usage); return NO_ERROR; + } + case ALLOW_ALLOCATION: { + CHECK_INTERFACE(IGraphicBufferProducer, data, reply); + bool allow = static_cast<bool>(data.readInt32()); + status_t result = allowAllocation(allow); + reply->writeInt32(result); + return NO_ERROR; + } } return BBinder::onTransact(code, data, reply, flags); } @@ -433,12 +462,14 @@ IGraphicBufferProducer::QueueBufferInput::QueueBufferInput(const Parcel& parcel) size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const { return sizeof(timestamp) + sizeof(isAutoTimestamp) + + sizeof(dataSpace) + sizeof(crop) + sizeof(scalingMode) + sizeof(transform) + sizeof(stickyTransform) + sizeof(async) - + fence->getFlattenedSize(); + + fence->getFlattenedSize() + + surfaceDamage.getFlattenedSize(); } size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const { @@ -453,12 +484,17 @@ status_t IGraphicBufferProducer::QueueBufferInput::flatten( } FlattenableUtils::write(buffer, size, timestamp); FlattenableUtils::write(buffer, size, isAutoTimestamp); + FlattenableUtils::write(buffer, size, dataSpace); FlattenableUtils::write(buffer, size, crop); FlattenableUtils::write(buffer, size, scalingMode); FlattenableUtils::write(buffer, size, transform); FlattenableUtils::write(buffer, size, stickyTransform); FlattenableUtils::write(buffer, size, async); - return fence->flatten(buffer, size, fds, count); + status_t result = fence->flatten(buffer, size, fds, count); + if (result != NO_ERROR) { + return result; + } + return surfaceDamage.flatten(buffer, size); } status_t IGraphicBufferProducer::QueueBufferInput::unflatten( @@ -467,6 +503,7 @@ status_t IGraphicBufferProducer::QueueBufferInput::unflatten( size_t minNeeded = sizeof(timestamp) + sizeof(isAutoTimestamp) + + sizeof(dataSpace) + sizeof(crop) + sizeof(scalingMode) + sizeof(transform) @@ -479,6 +516,7 @@ status_t IGraphicBufferProducer::QueueBufferInput::unflatten( FlattenableUtils::read(buffer, size, timestamp); FlattenableUtils::read(buffer, size, isAutoTimestamp); + FlattenableUtils::read(buffer, size, dataSpace); FlattenableUtils::read(buffer, size, crop); FlattenableUtils::read(buffer, size, scalingMode); FlattenableUtils::read(buffer, size, transform); @@ -486,7 +524,11 @@ status_t IGraphicBufferProducer::QueueBufferInput::unflatten( FlattenableUtils::read(buffer, size, async); fence = new Fence(); - return fence->unflatten(buffer, size, fds, count); + status_t result = fence->unflatten(buffer, size, fds, count); + if (result != NO_ERROR) { + return result; + } + return surfaceDamage.unflatten(buffer, size); } }; // namespace android diff --git a/libs/gui/IProducerListener.cpp b/libs/gui/IProducerListener.cpp index efe4069..81adc95 100644 --- a/libs/gui/IProducerListener.cpp +++ b/libs/gui/IProducerListener.cpp @@ -30,6 +30,8 @@ public: BpProducerListener(const sp<IBinder>& impl) : BpInterface<IProducerListener>(impl) {} + virtual ~BpProducerListener(); + virtual void onBufferReleased() { Parcel data, reply; data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor()); @@ -37,6 +39,10 @@ public: } }; +// Out-of-line virtual method definition to trigger vtable emission in this +// translation unit (see clang warning -Wweak-vtables) +BpProducerListener::~BpProducerListener() {} + IMPLEMENT_META_INTERFACE(ProducerListener, "android.gui.IProducerListener") status_t BnProducerListener::onTransact(uint32_t code, const Parcel& data, diff --git a/libs/gui/ISensorEventConnection.cpp b/libs/gui/ISensorEventConnection.cpp index 28fcb53..dc7a35c 100644 --- a/libs/gui/ISensorEventConnection.cpp +++ b/libs/gui/ISensorEventConnection.cpp @@ -45,6 +45,8 @@ public: { } + virtual ~BpSensorEventConnection(); + virtual sp<BitTube> getSensorChannel() const { Parcel data, reply; @@ -85,6 +87,10 @@ public: } }; +// Out-of-line virtual method definition to trigger vtable emission in this +// translation unit (see clang warning -Wweak-vtables) +BpSensorEventConnection::~BpSensorEventConnection() {} + IMPLEMENT_META_INTERFACE(SensorEventConnection, "android.gui.SensorEventConnection"); // ---------------------------------------------------------------------------- @@ -98,7 +104,7 @@ status_t BnSensorEventConnection::onTransact( sp<BitTube> channel(getSensorChannel()); channel->writeToParcel(reply); return NO_ERROR; - } break; + } case ENABLE_DISABLE: { CHECK_INTERFACE(ISensorEventConnection, data, reply); int handle = data.readInt32(); @@ -110,21 +116,21 @@ status_t BnSensorEventConnection::onTransact( maxBatchReportLatencyNs, reservedFlags); reply->writeInt32(result); return NO_ERROR; - } break; + } case SET_EVENT_RATE: { CHECK_INTERFACE(ISensorEventConnection, data, reply); int handle = data.readInt32(); - int ns = data.readInt64(); + nsecs_t ns = data.readInt64(); status_t result = setEventRate(handle, ns); reply->writeInt32(result); return NO_ERROR; - } break; + } case FLUSH_SENSOR: { CHECK_INTERFACE(ISensorEventConnection, data, reply); status_t result = flush(); reply->writeInt32(result); return NO_ERROR; - } break; + } } return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/ISensorServer.cpp b/libs/gui/ISensorServer.cpp index 0b76f37..8e09e7c 100644 --- a/libs/gui/ISensorServer.cpp +++ b/libs/gui/ISensorServer.cpp @@ -45,6 +45,8 @@ public: { } + virtual ~BpSensorServer(); + virtual Vector<Sensor> getSensorList() { Parcel data, reply; @@ -52,7 +54,7 @@ public: remote()->transact(GET_SENSOR_LIST, data, &reply); Sensor s; Vector<Sensor> v; - int32_t n = reply.readInt32(); + uint32_t n = reply.readUint32(); v.setCapacity(n); while (n--) { reply.read(s); @@ -70,6 +72,10 @@ public: } }; +// Out-of-line virtual method definition to trigger vtable emission in this +// translation unit (see clang warning -Wweak-vtables) +BpSensorServer::~BpSensorServer() {} + IMPLEMENT_META_INTERFACE(SensorServer, "android.gui.SensorServer"); // ---------------------------------------------------------------------- @@ -82,18 +88,18 @@ status_t BnSensorServer::onTransact( CHECK_INTERFACE(ISensorServer, data, reply); Vector<Sensor> v(getSensorList()); size_t n = v.size(); - reply->writeInt32(n); - for (size_t i=0 ; i<n ; i++) { + reply->writeUint32(static_cast<uint32_t>(n)); + for (size_t i = 0; i < n; i++) { reply->write(v[i]); } return NO_ERROR; - } break; + } case CREATE_SENSOR_EVENT_CONNECTION: { CHECK_INTERFACE(ISensorServer, data, reply); sp<ISensorEventConnection> connection(createSensorEventConnection()); - reply->writeStrongBinder(connection->asBinder()); + reply->writeStrongBinder(IInterface::asBinder(connection)); return NO_ERROR; - } break; + } } return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index ebb687a..78886d5 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -51,9 +51,10 @@ public: { } + virtual ~BpSurfaceComposer(); + virtual sp<ISurfaceComposerClient> createConnection() { - uint32_t n; Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply); @@ -62,7 +63,6 @@ public: virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc() { - uint32_t n; Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); remote()->transact(BnSurfaceComposer::CREATE_GRAPHIC_BUFFER_ALLOC, data, &reply); @@ -76,23 +76,18 @@ public: { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - { - Vector<ComposerState>::const_iterator b(state.begin()); - Vector<ComposerState>::const_iterator e(state.end()); - data.writeInt32(state.size()); - for ( ; b != e ; ++b ) { - b->write(data); - } + + data.writeUint32(static_cast<uint32_t>(state.size())); + for (const auto& s : state) { + s.write(data); } - { - Vector<DisplayState>::const_iterator b(displays.begin()); - Vector<DisplayState>::const_iterator e(displays.end()); - data.writeInt32(displays.size()); - for ( ; b != e ; ++b ) { - b->write(data); - } + + data.writeUint32(static_cast<uint32_t>(displays.size())); + for (const auto& d : displays) { + d.write(data); } - data.writeInt32(flags); + + data.writeUint32(flags); remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply); } @@ -113,12 +108,12 @@ public: Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); - data.writeStrongBinder(producer->asBinder()); + data.writeStrongBinder(IInterface::asBinder(producer)); data.write(sourceCrop); - data.writeInt32(reqWidth); - data.writeInt32(reqHeight); - data.writeInt32(minLayerZ); - data.writeInt32(maxLayerZ); + data.writeUint32(reqWidth); + data.writeUint32(reqHeight); + data.writeUint32(minLayerZ); + data.writeUint32(maxLayerZ); data.writeInt32(static_cast<int32_t>(useIdentityTransform)); data.writeInt32(static_cast<int32_t>(rotation)); remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); @@ -137,7 +132,7 @@ public: "interface descriptor: %s (%d)", strerror(-err), -err); return false; } - err = data.writeStrongBinder(bufferProducer->asBinder()); + err = data.writeStrongBinder(IInterface::asBinder(bufferProducer)); if (err != NO_ERROR) { ALOGE("ISurfaceComposer::authenticateSurfaceTexture: error writing " "strong binder to parcel: %s (%d)", strerror(-err), -err); @@ -226,7 +221,7 @@ public: remote()->transact(BnSurfaceComposer::GET_DISPLAY_CONFIGS, data, &reply); status_t result = reply.readInt32(); if (result == NO_ERROR) { - size_t numConfigs = static_cast<size_t>(reply.readInt32()); + size_t numConfigs = reply.readUint32(); configs->clear(); configs->resize(numConfigs); for (size_t c = 0; c < numConfigs; ++c) { @@ -289,6 +284,10 @@ public: } }; +// Out-of-line virtual method definition to trigger vtable emission in this +// translation unit (see clang warning -Wweak-vtables) +BpSurfaceComposer::~BpSurfaceComposer() {} + IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer"); // ---------------------------------------------------------------------- @@ -299,46 +298,49 @@ status_t BnSurfaceComposer::onTransact( switch(code) { case CREATE_CONNECTION: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<IBinder> b = createConnection()->asBinder(); + sp<IBinder> b = IInterface::asBinder(createConnection()); reply->writeStrongBinder(b); return NO_ERROR; } case CREATE_GRAPHIC_BUFFER_ALLOC: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<IBinder> b = createGraphicBufferAlloc()->asBinder(); + sp<IBinder> b = IInterface::asBinder(createGraphicBufferAlloc()); reply->writeStrongBinder(b); return NO_ERROR; } case SET_TRANSACTION_STATE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - size_t count = data.readInt32(); + + size_t count = data.readUint32(); if (count > data.dataSize()) { return BAD_VALUE; } ComposerState s; Vector<ComposerState> state; state.setCapacity(count); - for (size_t i=0 ; i<count ; i++) { + for (size_t i = 0; i < count; i++) { if (s.read(data) == BAD_VALUE) { return BAD_VALUE; } state.add(s); } - count = data.readInt32(); + + count = data.readUint32(); if (count > data.dataSize()) { return BAD_VALUE; } DisplayState d; Vector<DisplayState> displays; displays.setCapacity(count); - for (size_t i=0 ; i<count ; i++) { + for (size_t i = 0; i < count; i++) { if (d.read(data) == BAD_VALUE) { return BAD_VALUE; } displays.add(d); } - uint32_t flags = data.readInt32(); - setTransactionState(state, displays, flags); + + uint32_t stateFlags = data.readUint32(); + setTransactionState(state, displays, stateFlags); return NO_ERROR; } case BOOT_FINISHED: { @@ -353,12 +355,12 @@ status_t BnSurfaceComposer::onTransact( interface_cast<IGraphicBufferProducer>(data.readStrongBinder()); Rect sourceCrop; data.read(sourceCrop); - uint32_t reqWidth = data.readInt32(); - uint32_t reqHeight = data.readInt32(); - uint32_t minLayerZ = data.readInt32(); - uint32_t maxLayerZ = data.readInt32(); + uint32_t reqWidth = data.readUint32(); + uint32_t reqHeight = data.readUint32(); + uint32_t minLayerZ = data.readUint32(); + uint32_t maxLayerZ = data.readUint32(); bool useIdentityTransform = static_cast<bool>(data.readInt32()); - uint32_t rotation = data.readInt32(); + int32_t rotation = data.readInt32(); status_t res = captureScreen(display, producer, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, @@ -378,7 +380,7 @@ status_t BnSurfaceComposer::onTransact( case CREATE_DISPLAY_EVENT_CONNECTION: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp<IDisplayEventConnection> connection(createDisplayEventConnection()); - reply->writeStrongBinder(connection->asBinder()); + reply->writeStrongBinder(IInterface::asBinder(connection)); return NO_ERROR; } case CREATE_DISPLAY: { @@ -409,7 +411,7 @@ status_t BnSurfaceComposer::onTransact( status_t result = getDisplayConfigs(display, &configs); reply->writeInt32(result); if (result == NO_ERROR) { - reply->writeInt32(static_cast<int32_t>(configs.size())); + reply->writeUint32(static_cast<uint32_t>(configs.size())); for (size_t c = 0; c < configs.size(); ++c) { memcpy(reply->writeInplace(sizeof(DisplayInfo)), &configs[c], sizeof(DisplayInfo)); @@ -469,8 +471,6 @@ status_t BnSurfaceComposer::onTransact( return BBinder::onTransact(code, data, reply, flags); } } - // should be unreachable - return NO_ERROR; } // ---------------------------------------------------------------------------- diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index 3da6423..2ecb908 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -51,17 +51,19 @@ public: : BpInterface<ISurfaceComposerClient>(impl) { } - virtual status_t createSurface(const String8& name, uint32_t w, - uint32_t h, PixelFormat format, uint32_t flags, + virtual ~BpSurfaceComposerClient(); + + virtual status_t createSurface(const String8& name, uint32_t width, + uint32_t height, PixelFormat format, uint32_t flags, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor()); data.writeString8(name); - data.writeInt32(w); - data.writeInt32(h); - data.writeInt32(format); - data.writeInt32(flags); + data.writeUint32(width); + data.writeUint32(height); + data.writeInt32(static_cast<int32_t>(format)); + data.writeUint32(flags); remote()->transact(CREATE_SURFACE, data, &reply); *handle = reply.readStrongBinder(); *gbp = interface_cast<IGraphicBufferProducer>(reply.readStrongBinder()); @@ -94,6 +96,10 @@ public: } }; +// Out-of-line virtual method definition to trigger vtable emission in this +// translation unit (see clang warning -Wweak-vtables) +BpSurfaceComposerClient::~BpSurfaceComposerClient() {} + IMPLEMENT_META_INTERFACE(SurfaceComposerClient, "android.ui.ISurfaceComposerClient"); // ---------------------------------------------------------------------- @@ -105,31 +111,31 @@ status_t BnSurfaceComposerClient::onTransact( case CREATE_SURFACE: { CHECK_INTERFACE(ISurfaceComposerClient, data, reply); String8 name = data.readString8(); - uint32_t w = data.readInt32(); - uint32_t h = data.readInt32(); - PixelFormat format = data.readInt32(); - uint32_t flags = data.readInt32(); + uint32_t width = data.readUint32(); + uint32_t height = data.readUint32(); + PixelFormat format = static_cast<PixelFormat>(data.readInt32()); + uint32_t createFlags = data.readUint32(); sp<IBinder> handle; sp<IGraphicBufferProducer> gbp; - status_t result = createSurface(name, w, h, format, flags, - &handle, &gbp); + status_t result = createSurface(name, width, height, format, + createFlags, &handle, &gbp); reply->writeStrongBinder(handle); - reply->writeStrongBinder(gbp->asBinder()); + reply->writeStrongBinder(IInterface::asBinder(gbp)); reply->writeInt32(result); return NO_ERROR; - } break; + } case DESTROY_SURFACE: { CHECK_INTERFACE(ISurfaceComposerClient, data, reply); reply->writeInt32(destroySurface( data.readStrongBinder() ) ); return NO_ERROR; - } break; + } case CLEAR_LAYER_FRAME_STATS: { CHECK_INTERFACE(ISurfaceComposerClient, data, reply); sp<IBinder> handle = data.readStrongBinder(); status_t result = clearLayerFrameStats(handle); reply->writeInt32(result); return NO_ERROR; - } break; + } case GET_LAYER_FRAME_STATS: { CHECK_INTERFACE(ISurfaceComposerClient, data, reply); sp<IBinder> handle = data.readStrongBinder(); @@ -138,7 +144,7 @@ status_t BnSurfaceComposerClient::onTransact( reply->write(stats); reply->writeInt32(result); return NO_ERROR; - } break; + } default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 1183d59..00323dc 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -25,16 +25,16 @@ namespace android { status_t layer_state_t::write(Parcel& output) const { output.writeStrongBinder(surface); - output.writeInt32(what); + output.writeUint32(what); output.writeFloat(x); output.writeFloat(y); - output.writeInt32(z); - output.writeInt32(w); - output.writeInt32(h); - output.writeInt32(layerStack); + output.writeUint32(z); + output.writeUint32(w); + output.writeUint32(h); + output.writeUint32(layerStack); output.writeFloat(alpha); - output.writeInt32(flags); - output.writeInt32(mask); + output.writeUint32(flags); + output.writeUint32(mask); *reinterpret_cast<layer_state_t::matrix22_t *>( output.writeInplace(sizeof(layer_state_t::matrix22_t))) = matrix; output.write(crop); @@ -45,16 +45,16 @@ status_t layer_state_t::write(Parcel& output) const status_t layer_state_t::read(const Parcel& input) { surface = input.readStrongBinder(); - what = input.readInt32(); + what = input.readUint32(); x = input.readFloat(); y = input.readFloat(); - z = input.readInt32(); - w = input.readInt32(); - h = input.readInt32(); - layerStack = input.readInt32(); + z = input.readUint32(); + w = input.readUint32(); + h = input.readUint32(); + layerStack = input.readUint32(); alpha = input.readFloat(); - flags = input.readInt32(); - mask = input.readInt32(); + flags = static_cast<uint8_t>(input.readUint32()); + mask = static_cast<uint8_t>(input.readUint32()); const void* matrix_data = input.readInplace(sizeof(layer_state_t::matrix22_t)); if (matrix_data) { matrix = *reinterpret_cast<layer_state_t::matrix22_t const *>(matrix_data); @@ -67,7 +67,7 @@ status_t layer_state_t::read(const Parcel& input) } status_t ComposerState::write(Parcel& output) const { - output.writeStrongBinder(client->asBinder()); + output.writeStrongBinder(IInterface::asBinder(client)); return state.write(output); } @@ -79,27 +79,27 @@ status_t ComposerState::read(const Parcel& input) { status_t DisplayState::write(Parcel& output) const { output.writeStrongBinder(token); - output.writeStrongBinder(surface->asBinder()); - output.writeInt32(what); - output.writeInt32(layerStack); - output.writeInt32(orientation); + output.writeStrongBinder(IInterface::asBinder(surface)); + output.writeUint32(what); + output.writeUint32(layerStack); + output.writeUint32(orientation); output.write(viewport); output.write(frame); - output.writeInt32(width); - output.writeInt32(height); + output.writeUint32(width); + output.writeUint32(height); return NO_ERROR; } status_t DisplayState::read(const Parcel& input) { token = input.readStrongBinder(); surface = interface_cast<IGraphicBufferProducer>(input.readStrongBinder()); - what = input.readInt32(); - layerStack = input.readInt32(); - orientation = input.readInt32(); + what = input.readUint32(); + layerStack = input.readUint32(); + orientation = input.readUint32(); input.read(viewport); input.read(frame); - width = input.readInt32(); - height = input.readInt32(); + width = input.readUint32(); + height = input.readUint32(); return NO_ERROR; } diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp index b4291bb..35661f2 100644 --- a/libs/gui/Sensor.cpp +++ b/libs/gui/Sensor.cpp @@ -72,7 +72,7 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) static_cast<int64_t>(hwSensor->maxDelay)); mMaxDelay = INT_MAX; } else { - mMaxDelay = (int32_t) hwSensor->maxDelay; + mMaxDelay = static_cast<int32_t>(hwSensor->maxDelay); } } else { // For older hals set maxDelay to 0. @@ -204,6 +204,13 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) mFlags |= SENSOR_FLAG_WAKE_UP; } break; + case SENSOR_TYPE_WRIST_TILT_GESTURE: + mStringType = SENSOR_STRING_TYPE_WRIST_TILT_GESTURE; + mFlags |= SENSOR_FLAG_SPECIAL_REPORTING_MODE; + if (halVersion < SENSORS_DEVICE_API_VERSION_1_3) { + mFlags |= SENSOR_FLAG_WAKE_UP; + } + break; default: // Only pipe the stringType, requiredPermission and flags for custom sensors. if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor->stringType) { @@ -214,7 +221,7 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) } if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) { - mFlags = (int32_t) hwSensor->flags; + mFlags = static_cast<uint32_t>(hwSensor->flags); } else { // This is an OEM defined sensor on an older HAL. Use minDelay to determine the // reporting mode of the sensor. @@ -295,11 +302,11 @@ int32_t Sensor::getVersion() const { return mVersion; } -int32_t Sensor::getFifoReservedEventCount() const { +uint32_t Sensor::getFifoReservedEventCount() const { return mFifoReservedEventCount; } -int32_t Sensor::getFifoMaxEventCount() const { +uint32_t Sensor::getFifoMaxEventCount() const { return mFifoMaxEventCount; } @@ -315,7 +322,7 @@ int32_t Sensor::getMaxDelay() const { return mMaxDelay; } -int32_t Sensor::getFlags() const { +uint32_t Sensor::getFlags() const { return mFlags; } @@ -407,7 +414,7 @@ status_t Sensor::unflatten(void const* buffer, size_t size) { void Sensor::flattenString8(void*& buffer, size_t& size, const String8& string8) { - uint32_t len = string8.length(); + uint32_t len = static_cast<uint32_t>(string8.length()); FlattenableUtils::write(buffer, size, len); memcpy(static_cast<char*>(buffer), string8.string(), len); FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len)); diff --git a/libs/gui/SensorEventQueue.cpp b/libs/gui/SensorEventQueue.cpp index 1305e9f..76ae470 100644 --- a/libs/gui/SensorEventQueue.cpp +++ b/libs/gui/SensorEventQueue.cpp @@ -16,6 +16,7 @@ #define LOG_TAG "Sensors" +#include <algorithm> #include <stdint.h> #include <sys/types.h> #include <sys/socket.h> @@ -31,6 +32,8 @@ #include <android/sensor.h> +using std::min; + // ---------------------------------------------------------------------------- namespace android { // ---------------------------------------------------------------------------- @@ -68,14 +71,14 @@ ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents) { if (err < 0) { return err; } - mAvailable = err; + mAvailable = static_cast<size_t>(err); mConsumed = 0; } - size_t count = numEvents < mAvailable ? numEvents : mAvailable; - memcpy(events, mRecBuffer + mConsumed, count*sizeof(ASensorEvent)); + size_t count = min(numEvents, mAvailable); + memcpy(events, mRecBuffer + mConsumed, count * sizeof(ASensorEvent)); mAvailable -= count; mConsumed += count; - return count; + return static_cast<ssize_t>(count); } sp<Looper> SensorEventQueue::getLooper() const @@ -157,7 +160,7 @@ void SensorEventQueue::sendAck(const ASensorEvent* events, int count) { ssize_t size = ::send(mSensorChannel->getFd(), &mNumAcksToSend, sizeof(mNumAcksToSend), MSG_DONTWAIT | MSG_NOSIGNAL); if (size < 0) { - ALOGE("sendAck failure %d %d", size, mNumAcksToSend); + ALOGE("sendAck failure %zd %d", size, mNumAcksToSend); } else { mNumAcksToSend = 0; } diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp index 7b4fa2f..d6df404 100644 --- a/libs/gui/SensorManager.cpp +++ b/libs/gui/SensorManager.cpp @@ -86,11 +86,12 @@ status_t SensorManager::assertStateLocked() const { }; mDeathObserver = new DeathObserver(*const_cast<SensorManager *>(this)); - mSensorServer->asBinder()->linkToDeath(mDeathObserver); + IInterface::asBinder(mSensorServer)->linkToDeath(mDeathObserver); mSensors = mSensorServer->getSensorList(); size_t count = mSensors.size(); - mSensorList = (Sensor const**)malloc(count * sizeof(Sensor*)); + mSensorList = + static_cast<Sensor const**>(malloc(count * sizeof(Sensor*))); for (size_t i=0 ; i<count ; i++) { mSensorList[i] = mSensors.array() + i; } @@ -106,10 +107,10 @@ ssize_t SensorManager::getSensorList(Sensor const* const** list) const Mutex::Autolock _l(mLock); status_t err = assertStateLocked(); if (err < 0) { - return ssize_t(err); + return static_cast<ssize_t>(err); } *list = mSensorList; - return mSensors.size(); + return static_cast<ssize_t>(mSensors.size()); } Sensor const* SensorManager::getDefaultSensor(int type) diff --git a/libs/gui/StreamSplitter.cpp b/libs/gui/StreamSplitter.cpp index 5f39905..43f9214 100644 --- a/libs/gui/StreamSplitter.cpp +++ b/libs/gui/StreamSplitter.cpp @@ -20,6 +20,7 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS //#define LOG_NDEBUG 0 +#include <gui/BufferItem.h> #include <gui/IGraphicBufferConsumer.h> #include <gui/IGraphicBufferProducer.h> #include <gui/StreamSplitter.h> @@ -80,7 +81,7 @@ status_t StreamSplitter::addOutput( IGraphicBufferProducer::QueueBufferOutput queueBufferOutput; sp<OutputListener> listener(new OutputListener(this, outputQueue)); - outputQueue->asBinder()->linkToDeath(listener); + IInterface::asBinder(outputQueue)->linkToDeath(listener); status_t status = outputQueue->connect(listener, NATIVE_WINDOW_API_CPU, /* producerControlledByApp */ false, &queueBufferOutput); if (status != NO_ERROR) { @@ -123,7 +124,7 @@ void StreamSplitter::onFrameAvailable(const BufferItem& /* item */) { ++mOutstandingBuffers; // Acquire and detach the buffer from the input - IGraphicBufferConsumer::BufferItem bufferItem; + BufferItem bufferItem; status_t status = mInput->acquireBuffer(&bufferItem, /* presentWhen */ 0); LOG_ALWAYS_FATAL_IF(status != NO_ERROR, "acquiring buffer from input failed (%d)", status); @@ -141,7 +142,8 @@ void StreamSplitter::onFrameAvailable(const BufferItem& /* item */) { IGraphicBufferProducer::QueueBufferInput queueInput( bufferItem.mTimestamp, bufferItem.mIsAutoTimestamp, - bufferItem.mCrop, bufferItem.mScalingMode, + bufferItem.mDataSpace, bufferItem.mCrop, + static_cast<int32_t>(bufferItem.mScalingMode), bufferItem.mTransform, bufferItem.mIsDroppable, bufferItem.mFence); diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 0e2baa2..b8acad2 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -27,6 +27,7 @@ #include <utils/NativeHandle.h> #include <ui/Fence.h> +#include <ui/Region.h> #include <gui/IProducerListener.h> #include <gui/ISurfaceComposer.h> @@ -64,6 +65,7 @@ Surface::Surface( mReqFormat = 0; mReqUsage = 0; mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO; + mDataSpace = HAL_DATASPACE_UNKNOWN; mCrop.clear(); mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE; mTransform = 0; @@ -96,8 +98,8 @@ void Surface::setSidebandStream(const sp<NativeHandle>& stream) { void Surface::allocateBuffers() { uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth; uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight; - mGraphicBufferProducer->allocateBuffers(mSwapIntervalZero, mReqWidth, - mReqHeight, mReqFormat, mReqUsage); + mGraphicBufferProducer->allocateBuffers(mSwapIntervalZero, reqWidth, + reqHeight, mReqFormat, mReqUsage); } int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) { @@ -193,17 +195,17 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { ATRACE_CALL(); ALOGV("Surface::dequeueBuffer"); - int reqW; - int reqH; + uint32_t reqWidth; + uint32_t reqHeight; bool swapIntervalZero; - uint32_t reqFormat; + PixelFormat reqFormat; uint32_t reqUsage; { Mutex::Autolock lock(mMutex); - reqW = mReqWidth ? mReqWidth : mUserWidth; - reqH = mReqHeight ? mReqHeight : mUserHeight; + reqWidth = mReqWidth ? mReqWidth : mUserWidth; + reqHeight = mReqHeight ? mReqHeight : mUserHeight; swapIntervalZero = mSwapIntervalZero; reqFormat = mReqFormat; @@ -213,12 +215,12 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { int buf = -1; sp<Fence> fence; status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, swapIntervalZero, - reqW, reqH, reqFormat, reqUsage); + reqWidth, reqHeight, reqFormat, reqUsage); if (result < 0) { ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d, %d)" - "failed: %d", swapIntervalZero, reqW, reqH, reqFormat, reqUsage, - result); + "failed: %d", swapIntervalZero, reqWidth, reqHeight, reqFormat, + reqUsage, result); return result; } @@ -274,7 +276,6 @@ int Surface::cancelBuffer(android_native_buffer_t* buffer, int Surface::getSlotFromBufferLocked( android_native_buffer_t* buffer) const { - bool dumpedState = false; for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { if (mSlots[i].buffer != NULL && mSlots[i].buffer->handle == buffer->handle) { @@ -318,8 +319,27 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) { sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE); IGraphicBufferProducer::QueueBufferOutput output; IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp, - crop, mScalingMode, mTransform ^ mStickyTransform, mSwapIntervalZero, - fence, mStickyTransform); + mDataSpace, crop, mScalingMode, mTransform ^ mStickyTransform, + mSwapIntervalZero, fence, mStickyTransform); + + if (mConnectedToCpu || mDirtyRegion.bounds() == Rect::INVALID_RECT) { + input.setSurfaceDamage(Region::INVALID_REGION); + } else { + // The surface damage was specified using the OpenGL ES convention of + // the origin being in the bottom-left corner. Here we flip to the + // convention that the rest of the system uses (top-left corner) by + // subtracting all top/bottom coordinates from the buffer height. + Region flippedRegion; + for (auto rect : mDirtyRegion) { + auto top = buffer->height - rect.bottom; + auto bottom = buffer->height - rect.top; + Rect flippedRect{rect.left, top, rect.right, bottom}; + flippedRegion.orSelf(flippedRect); + } + + input.setSurfaceDamage(flippedRegion); + } + status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output); if (err != OK) { ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err); @@ -336,6 +356,11 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) { mConsumerRunningBehind = (numPendingBuffers >= 2); + if (!mConnectedToCpu) { + // Clear surface damage back to full-buffer + mDirtyRegion = Region::INVALID_REGION; + } + return err; } @@ -347,7 +372,7 @@ int Surface::query(int what, int* value) const { switch (what) { case NATIVE_WINDOW_FORMAT: if (mReqFormat) { - *value = mReqFormat; + *value = static_cast<int>(mReqFormat); return NO_ERROR; } break; @@ -365,13 +390,15 @@ int Surface::query(int what, int* value) const { *value = NATIVE_WINDOW_SURFACE; return NO_ERROR; case NATIVE_WINDOW_DEFAULT_WIDTH: - *value = mUserWidth ? mUserWidth : mDefaultWidth; + *value = static_cast<int>( + mUserWidth ? mUserWidth : mDefaultWidth); return NO_ERROR; case NATIVE_WINDOW_DEFAULT_HEIGHT: - *value = mUserHeight ? mUserHeight : mDefaultHeight; + *value = static_cast<int>( + mUserHeight ? mUserHeight : mDefaultHeight); return NO_ERROR; case NATIVE_WINDOW_TRANSFORM_HINT: - *value = mTransformHint; + *value = static_cast<int>(mTransformHint); return NO_ERROR; case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: { status_t err = NO_ERROR; @@ -448,6 +475,12 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_SET_SIDEBAND_STREAM: res = dispatchSetSidebandStream(args); break; + case NATIVE_WINDOW_SET_BUFFERS_DATASPACE: + res = dispatchSetBuffersDataSpace(args); + break; + case NATIVE_WINDOW_SET_SURFACE_DAMAGE: + res = dispatchSetSurfaceDamage(args); + break; default: res = NAME_NOT_FOUND; break; @@ -467,7 +500,7 @@ int Surface::dispatchDisconnect(va_list args) { int Surface::dispatchSetUsage(va_list args) { int usage = va_arg(args, int); - return setUsage(usage); + return setUsage(static_cast<uint32_t>(usage)); } int Surface::dispatchSetCrop(va_list args) { @@ -477,49 +510,49 @@ int Surface::dispatchSetCrop(va_list args) { int Surface::dispatchSetBufferCount(va_list args) { size_t bufferCount = va_arg(args, size_t); - return setBufferCount(bufferCount); + return setBufferCount(static_cast<int32_t>(bufferCount)); } int Surface::dispatchSetBuffersGeometry(va_list args) { - int w = va_arg(args, int); - int h = va_arg(args, int); - int f = va_arg(args, int); - int err = setBuffersDimensions(w, h); + uint32_t width = va_arg(args, uint32_t); + uint32_t height = va_arg(args, uint32_t); + PixelFormat format = va_arg(args, PixelFormat); + int err = setBuffersDimensions(width, height); if (err != 0) { return err; } - return setBuffersFormat(f); + return setBuffersFormat(format); } int Surface::dispatchSetBuffersDimensions(va_list args) { - int w = va_arg(args, int); - int h = va_arg(args, int); - return setBuffersDimensions(w, h); + uint32_t width = va_arg(args, uint32_t); + uint32_t height = va_arg(args, uint32_t); + return setBuffersDimensions(width, height); } int Surface::dispatchSetBuffersUserDimensions(va_list args) { - int w = va_arg(args, int); - int h = va_arg(args, int); - return setBuffersUserDimensions(w, h); + uint32_t width = va_arg(args, uint32_t); + uint32_t height = va_arg(args, uint32_t); + return setBuffersUserDimensions(width, height); } int Surface::dispatchSetBuffersFormat(va_list args) { - int f = va_arg(args, int); - return setBuffersFormat(f); + PixelFormat format = va_arg(args, PixelFormat); + return setBuffersFormat(format); } int Surface::dispatchSetScalingMode(va_list args) { - int m = va_arg(args, int); - return setScalingMode(m); + int mode = va_arg(args, int); + return setScalingMode(mode); } int Surface::dispatchSetBuffersTransform(va_list args) { - int transform = va_arg(args, int); + uint32_t transform = va_arg(args, uint32_t); return setBuffersTransform(transform); } int Surface::dispatchSetBuffersStickyTransform(va_list args) { - int transform = va_arg(args, int); + uint32_t transform = va_arg(args, uint32_t); return setBuffersStickyTransform(transform); } @@ -545,10 +578,27 @@ int Surface::dispatchSetSidebandStream(va_list args) { return OK; } +int Surface::dispatchSetBuffersDataSpace(va_list args) { + android_dataspace dataspace = + static_cast<android_dataspace>(va_arg(args, int)); + return setBuffersDataSpace(dataspace); +} + +int Surface::dispatchSetSurfaceDamage(va_list args) { + android_native_rect_t* rects = va_arg(args, android_native_rect_t*); + size_t numRects = va_arg(args, size_t); + setSurfaceDamage(rects, numRects); + return NO_ERROR; +} + int Surface::connect(int api) { + static sp<IProducerListener> listener = new DummyProducerListener(); + return connect(api, listener); +} + +int Surface::connect(int api, const sp<IProducerListener>& listener) { ATRACE_CALL(); ALOGV("Surface::connect"); - static sp<IProducerListener> listener = new DummyProducerListener(); Mutex::Autolock lock(mMutex); IGraphicBufferProducer::QueueBufferOutput output; int err = mGraphicBufferProducer->connect(listener, api, mProducerControlledByApp, &output); @@ -567,7 +617,13 @@ int Surface::connect(int api) { } if (!err && api == NATIVE_WINDOW_API_CPU) { mConnectedToCpu = true; + // Clear the dirty region in case we're switching from a non-CPU API + mDirtyRegion.clear(); + } else if (!err) { + // Initialize the dirty region for tracking surface damage + mDirtyRegion = Region::INVALID_REGION; } + return err; } @@ -595,6 +651,55 @@ int Surface::disconnect(int api) { return err; } +int Surface::detachNextBuffer(ANativeWindowBuffer** outBuffer, + sp<Fence>* outFence) { + ATRACE_CALL(); + ALOGV("Surface::detachNextBuffer"); + + if (outBuffer == NULL || outFence == NULL) { + return BAD_VALUE; + } + + Mutex::Autolock lock(mMutex); + + sp<GraphicBuffer> buffer(NULL); + sp<Fence> fence(NULL); + status_t result = mGraphicBufferProducer->detachNextBuffer( + &buffer, &fence); + if (result != NO_ERROR) { + return result; + } + + *outBuffer = buffer.get(); + if (fence != NULL && fence->isValid()) { + *outFence = fence; + } else { + *outFence = Fence::NO_FENCE; + } + + return NO_ERROR; +} + +int Surface::attachBuffer(ANativeWindowBuffer* buffer) +{ + ATRACE_CALL(); + ALOGV("Surface::attachBuffer"); + + Mutex::Autolock lock(mMutex); + + sp<GraphicBuffer> graphicBuffer(static_cast<GraphicBuffer*>(buffer)); + int32_t attachedSlot = -1; + status_t result = mGraphicBufferProducer->attachBuffer( + &attachedSlot, graphicBuffer); + if (result != NO_ERROR) { + ALOGE("attachBuffer: IGraphicBufferProducer call failed (%d)", result); + return result; + } + mSlots[attachedSlot].buffer = graphicBuffer; + + return NO_ERROR; +} + int Surface::setUsage(uint32_t reqUsage) { ALOGV("Surface::setUsage"); @@ -639,47 +744,38 @@ int Surface::setBufferCount(int bufferCount) return err; } -int Surface::setBuffersDimensions(int w, int h) +int Surface::setBuffersDimensions(uint32_t width, uint32_t height) { ATRACE_CALL(); ALOGV("Surface::setBuffersDimensions"); - if (w<0 || h<0) - return BAD_VALUE; - - if ((w && !h) || (!w && h)) + if ((width && !height) || (!width && height)) return BAD_VALUE; Mutex::Autolock lock(mMutex); - mReqWidth = w; - mReqHeight = h; + mReqWidth = width; + mReqHeight = height; return NO_ERROR; } -int Surface::setBuffersUserDimensions(int w, int h) +int Surface::setBuffersUserDimensions(uint32_t width, uint32_t height) { ATRACE_CALL(); ALOGV("Surface::setBuffersUserDimensions"); - if (w<0 || h<0) - return BAD_VALUE; - - if ((w && !h) || (!w && h)) + if ((width && !height) || (!width && height)) return BAD_VALUE; Mutex::Autolock lock(mMutex); - mUserWidth = w; - mUserHeight = h; + mUserWidth = width; + mUserHeight = height; return NO_ERROR; } -int Surface::setBuffersFormat(int format) +int Surface::setBuffersFormat(PixelFormat format) { ALOGV("Surface::setBuffersFormat"); - if (format<0) - return BAD_VALUE; - Mutex::Autolock lock(mMutex); mReqFormat = format; return NO_ERROR; @@ -705,7 +801,7 @@ int Surface::setScalingMode(int mode) return NO_ERROR; } -int Surface::setBuffersTransform(int transform) +int Surface::setBuffersTransform(uint32_t transform) { ATRACE_CALL(); ALOGV("Surface::setBuffersTransform"); @@ -714,7 +810,7 @@ int Surface::setBuffersTransform(int transform) return NO_ERROR; } -int Surface::setBuffersStickyTransform(int transform) +int Surface::setBuffersStickyTransform(uint32_t transform) { ATRACE_CALL(); ALOGV("Surface::setBuffersStickyTransform"); @@ -731,12 +827,41 @@ int Surface::setBuffersTimestamp(int64_t timestamp) return NO_ERROR; } +int Surface::setBuffersDataSpace(android_dataspace dataSpace) +{ + ALOGV("Surface::setBuffersDataSpace"); + Mutex::Autolock lock(mMutex); + mDataSpace = dataSpace; + return NO_ERROR; +} + void Surface::freeAllBuffers() { for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { mSlots[i].buffer = 0; } } +void Surface::setSurfaceDamage(android_native_rect_t* rects, size_t numRects) { + ATRACE_CALL(); + ALOGV("Surface::setSurfaceDamage"); + Mutex::Autolock lock(mMutex); + + if (mConnectedToCpu || numRects == 0) { + mDirtyRegion = Region::INVALID_REGION; + return; + } + + mDirtyRegion.clear(); + for (size_t r = 0; r < numRects; ++r) { + // We intentionally flip top and bottom here, since because they're + // specified with a bottom-left origin, top > bottom, which fails + // validation in the Region class. We will fix this up when we flip to a + // top-left origin in queueBuffer. + Rect rect(rects[r].left, rects[r].bottom, rects[r].right, rects[r].top); + mDirtyRegion.orSelf(rect); + } +} + // ---------------------------------------------------------------------- // the lock/unlock APIs must be used from the same thread @@ -748,30 +873,34 @@ static status_t copyBlt( // src and dst with, height and format must be identical. no verification // is done here. status_t err; - uint8_t const * src_bits = NULL; - err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits); + uint8_t* src_bits = NULL; + err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), + reinterpret_cast<void**>(&src_bits)); ALOGE_IF(err, "error locking src buffer %s", strerror(-err)); uint8_t* dst_bits = NULL; - err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), (void**)&dst_bits); + err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), + reinterpret_cast<void**>(&dst_bits)); ALOGE_IF(err, "error locking dst buffer %s", strerror(-err)); Region::const_iterator head(reg.begin()); Region::const_iterator tail(reg.end()); if (head != tail && src_bits && dst_bits) { const size_t bpp = bytesPerPixel(src->format); - const size_t dbpr = dst->stride * bpp; - const size_t sbpr = src->stride * bpp; + const size_t dbpr = static_cast<uint32_t>(dst->stride) * bpp; + const size_t sbpr = static_cast<uint32_t>(src->stride) * bpp; while (head != tail) { const Rect& r(*head++); - ssize_t h = r.height(); + int32_t h = r.height(); if (h <= 0) continue; - size_t size = r.width() * bpp; - uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; - uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; + size_t size = static_cast<uint32_t>(r.width()) * bpp; + uint8_t const * s = src_bits + + static_cast<uint32_t>(r.left + src->stride * r.top) * bpp; + uint8_t * d = dst_bits + + static_cast<uint32_t>(r.left + dst->stride * r.top) * bpp; if (dbpr==sbpr && size==sbpr) { - size *= h; + size *= static_cast<size_t>(h); h = 1; } do { diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 6446926..707a321 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -71,7 +71,7 @@ void ComposerService::connectLocked() { }; mDeathObserver = new DeathObserver(*const_cast<ComposerService*>(this)); - mComposerService->asBinder()->linkToDeath(mDeathObserver); + IInterface::asBinder(mComposerService)->linkToDeath(mDeathObserver); } /*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() { @@ -143,7 +143,7 @@ public: status_t setSize(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, uint32_t w, uint32_t h); status_t setLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, - int32_t z); + uint32_t z); status_t setFlags(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, uint32_t flags, uint32_t mask); status_t setTransparentRegionHint( @@ -293,7 +293,7 @@ status_t Composer::setSize(const sp<SurfaceComposerClient>& client, } status_t Composer::setLayer(const sp<SurfaceComposerClient>& client, - const sp<IBinder>& id, int32_t z) { + const sp<IBinder>& id, uint32_t z) { Mutex::Autolock _l(mLock); layer_state_t* s = getLayerStateLocked(client, id); if (!s) @@ -395,7 +395,7 @@ DisplayState& Composer::getDisplayStateLocked(const sp<IBinder>& token) { s.what = 0; index = mDisplayStates.add(s); } - return mDisplayStates.editItemAt(index); + return mDisplayStates.editItemAt(static_cast<size_t>(index)); } void Composer::setDisplaySurface(const sp<IBinder>& token, @@ -462,14 +462,14 @@ status_t SurfaceComposerClient::initCheck() const { } sp<IBinder> SurfaceComposerClient::connection() const { - return (mClient != 0) ? mClient->asBinder() : 0; + return IInterface::asBinder(mClient); } status_t SurfaceComposerClient::linkToComposerDeath( const sp<IBinder::DeathRecipient>& recipient, void* cookie, uint32_t flags) { sp<ISurfaceComposer> sm(ComposerService::getComposerService()); - return sm->asBinder()->linkToDeath(recipient, cookie, flags); + return IInterface::asBinder(sm)->linkToDeath(recipient, cookie, flags); } void SurfaceComposerClient::dispose() { @@ -571,7 +571,7 @@ status_t SurfaceComposerClient::setSize(const sp<IBinder>& id, uint32_t w, uint3 return getComposer().setSize(this, id, w, h); } -status_t SurfaceComposerClient::setLayer(const sp<IBinder>& id, int32_t z) { +status_t SurfaceComposerClient::setLayer(const sp<IBinder>& id, uint32_t z) { return getComposer().setLayer(this, id, z); } @@ -657,7 +657,7 @@ status_t SurfaceComposerClient::getDisplayInfo(const sp<IBinder>& display, return NAME_NOT_FOUND; } - *info = configs[activeId]; + *info = configs[static_cast<size_t>(activeId)]; return NO_ERROR; } @@ -752,14 +752,14 @@ status_t ScreenshotClient::update(const sp<IBinder>& display, status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop, bool useIdentityTransform) { - return ScreenshotClient::update(display, sourceCrop, 0, 0, 0, -1UL, + return ScreenshotClient::update(display, sourceCrop, 0, 0, 0, -1U, useIdentityTransform, ISurfaceComposer::eRotateNone); } status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform) { return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight, - 0, -1UL, useIdentityTransform, ISurfaceComposer::eRotateNone); + 0, -1U, useIdentityTransform, ISurfaceComposer::eRotateNone); } void ScreenshotClient::release() { diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index 7597c99..1983027 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -89,12 +89,12 @@ bool SurfaceControl::isSameSurface( return lhs->mHandle == rhs->mHandle; } -status_t SurfaceControl::setLayerStack(int32_t layerStack) { +status_t SurfaceControl::setLayerStack(uint32_t layerStack) { status_t err = validate(); if (err < 0) return err; return mClient->setLayerStack(mHandle, layerStack); } -status_t SurfaceControl::setLayer(int32_t layer) { +status_t SurfaceControl::setLayer(uint32_t layer) { status_t err = validate(); if (err < 0) return err; return mClient->setLayer(mHandle, layer); @@ -176,7 +176,7 @@ status_t SurfaceControl::writeSurfaceToParcel( if (control != NULL) { bp = control->mGraphicBufferProducer; } - return parcel->writeStrongBinder(bp->asBinder()); + return parcel->writeStrongBinder(IInterface::asBinder(bp)); } sp<Surface> SurfaceControl::getSurface() const diff --git a/libs/gui/SyncFeatures.cpp b/libs/gui/SyncFeatures.cpp index e5804a7..187b211 100644 --- a/libs/gui/SyncFeatures.cpp +++ b/libs/gui/SyncFeatures.cpp @@ -16,7 +16,6 @@ #define LOG_TAG "GLConsumer" -#define GL_GLEXT_PROTOTYPES #define EGL_EGLEXT_PROTOTYPES #include <EGL/egl.h> @@ -78,10 +77,11 @@ bool SyncFeatures::useFenceSync() const { // on some devices it's better to not use EGL_KHR_fence_sync // even if they have it return false; -#endif +#else // currently we shall only attempt to use EGL_KHR_fence_sync if // USE_FENCE_SYNC is set in our makefile return !mHasNativeFenceSync && mHasFenceSync; +#endif } bool SyncFeatures::useWaitSync() const { return (useNativeFenceSync() || useFenceSync()) && mHasWaitSync; diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk index e460290..6ad9986 100644 --- a/libs/gui/tests/Android.mk +++ b/libs/gui/tests/Android.mk @@ -1,6 +1,9 @@ # Build the unit tests, LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk + +LOCAL_CLANG := true LOCAL_MODULE := libgui_test @@ -31,17 +34,10 @@ LOCAL_SHARED_LIBRARIES := \ libbinder \ libcutils \ libgui \ - libstlport \ libsync \ libui \ libutils \ -LOCAL_C_INCLUDES := \ - bionic \ - bionic/libstdc++/include \ - external/gtest/include \ - external/stlport/stlport \ - # Build the binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE) # to integrate with auto-test framework. include $(BUILD_NATIVE_TEST) diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp index 96de11f..1584fef 100644 --- a/libs/gui/tests/BufferQueue_test.cpp +++ b/libs/gui/tests/BufferQueue_test.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "BufferQueue_test" //#define LOG_NDEBUG 0 +#include <gui/BufferItem.h> #include <gui/BufferQueue.h> #include <gui/IProducerListener.h> @@ -72,6 +73,8 @@ struct DummyConsumer : public BnConsumerListener { virtual void onSidebandStreamChanged() {} }; +static const uint32_t TEST_DATA = 0x12345678u; + // XXX: Tests that fork a process to hold the BufferQueue must run before tests // that use a local BufferQueue, or else Binder will get unhappy TEST_F(BufferQueueTest, BufferQueueInAnotherProcess) { @@ -87,8 +90,8 @@ TEST_F(BufferQueueTest, BufferQueueInAnotherProcess) { sp<IGraphicBufferConsumer> consumer; BufferQueue::createBufferQueue(&producer, &consumer); sp<IServiceManager> serviceManager = defaultServiceManager(); - serviceManager->addService(PRODUCER_NAME, producer->asBinder()); - serviceManager->addService(CONSUMER_NAME, consumer->asBinder()); + serviceManager->addService(PRODUCER_NAME, IInterface::asBinder(producer)); + serviceManager->addService(CONSUMER_NAME, IInterface::asBinder(consumer)); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); LOG_ALWAYS_FATAL("Shouldn't be here"); @@ -121,20 +124,21 @@ TEST_F(BufferQueueTest, BufferQueueInAnotherProcess) { uint32_t* dataIn; ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, reinterpret_cast<void**>(&dataIn))); - *dataIn = 0x12345678; + *dataIn = TEST_DATA; ASSERT_EQ(OK, buffer->unlock()); - IGraphicBufferProducer::QueueBufferInput input(0, false, Rect(0, 0, 1, 1), + IGraphicBufferProducer::QueueBufferInput input(0, false, + HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE); ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); - IGraphicBufferConsumer::BufferItem item; + BufferItem item; ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); uint32_t* dataOut; ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&dataOut))); - ASSERT_EQ(*dataOut, 0x12345678); + ASSERT_EQ(*dataOut, TEST_DATA); ASSERT_EQ(OK, item.mGraphicBuffer->unlock()); } @@ -150,9 +154,10 @@ TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) { int slot; sp<Fence> fence; sp<GraphicBuffer> buf; - IGraphicBufferProducer::QueueBufferInput qbi(0, false, Rect(0, 0, 1, 1), + IGraphicBufferProducer::QueueBufferInput qbi(0, false, + HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE); - BufferQueue::BufferItem item; + BufferItem item; for (int i = 0; i < 2; i++) { ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, @@ -236,7 +241,7 @@ TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) { uint32_t* dataIn; ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, reinterpret_cast<void**>(&dataIn))); - *dataIn = 0x12345678; + *dataIn = TEST_DATA; ASSERT_EQ(OK, buffer->unlock()); int newSlot; @@ -244,17 +249,18 @@ TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) { ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, NULL)); ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer)); - IGraphicBufferProducer::QueueBufferInput input(0, false, Rect(0, 0, 1, 1), + IGraphicBufferProducer::QueueBufferInput input(0, false, + HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE); ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output)); - IGraphicBufferConsumer::BufferItem item; + BufferItem item; ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0))); uint32_t* dataOut; ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&dataOut))); - ASSERT_EQ(*dataOut, 0x12345678); + ASSERT_EQ(*dataOut, TEST_DATA); ASSERT_EQ(OK, item.mGraphicBuffer->unlock()); } @@ -273,7 +279,8 @@ TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) { mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN)); ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); - IGraphicBufferProducer::QueueBufferInput input(0, false, Rect(0, 0, 1, 1), + IGraphicBufferProducer::QueueBufferInput input(0, false, + HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE); ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); @@ -282,7 +289,7 @@ TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) { BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(0)); // Not acquired - IGraphicBufferConsumer::BufferItem item; + BufferItem item; ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0))); ASSERT_EQ(OK, mConsumer->detachBuffer(item.mBuf)); @@ -292,7 +299,7 @@ TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) { ASSERT_EQ(OK, item.mGraphicBuffer->lock( GraphicBuffer::USAGE_SW_WRITE_OFTEN, reinterpret_cast<void**>(&dataIn))); - *dataIn = 0x12345678; + *dataIn = TEST_DATA; ASSERT_EQ(OK, item.mGraphicBuffer->unlock()); int newSlot; @@ -312,7 +319,7 @@ TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) { uint32_t* dataOut; ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&dataOut))); - ASSERT_EQ(*dataOut, 0x12345678); + ASSERT_EQ(*dataOut, TEST_DATA); ASSERT_EQ(OK, buffer->unlock()); } @@ -335,14 +342,15 @@ TEST_F(BufferQueueTest, MoveFromConsumerToProducer) { uint32_t* dataIn; ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, reinterpret_cast<void**>(&dataIn))); - *dataIn = 0x12345678; + *dataIn = TEST_DATA; ASSERT_EQ(OK, buffer->unlock()); - IGraphicBufferProducer::QueueBufferInput input(0, false, Rect(0, 0, 1, 1), + IGraphicBufferProducer::QueueBufferInput input(0, false, + HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE); ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); - IGraphicBufferConsumer::BufferItem item; + BufferItem item; ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0))); ASSERT_EQ(OK, mConsumer->detachBuffer(item.mBuf)); @@ -354,8 +362,44 @@ TEST_F(BufferQueueTest, MoveFromConsumerToProducer) { uint32_t* dataOut; ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&dataOut))); - ASSERT_EQ(*dataOut, 0x12345678); + ASSERT_EQ(*dataOut, TEST_DATA); ASSERT_EQ(OK, item.mGraphicBuffer->unlock()); } +TEST_F(BufferQueueTest, TestDisallowingAllocation) { + createBufferQueue(); + sp<DummyConsumer> dc(new DummyConsumer); + ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true)); + IGraphicBufferProducer::QueueBufferOutput output; + ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, + NATIVE_WINDOW_API_CPU, true, &output)); + + static const uint32_t WIDTH = 320; + static const uint32_t HEIGHT = 240; + + ASSERT_EQ(OK, mConsumer->setDefaultBufferSize(WIDTH, HEIGHT)); + + int slot; + sp<Fence> fence; + sp<GraphicBuffer> buffer; + // This should return an error since it would require an allocation + ASSERT_EQ(OK, mProducer->allowAllocation(false)); + ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, + 0, GRALLOC_USAGE_SW_WRITE_OFTEN)); + + // This should succeed, now that we've lifted the prohibition + ASSERT_EQ(OK, mProducer->allowAllocation(true)); + ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, + mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, + GRALLOC_USAGE_SW_WRITE_OFTEN)); + + // Release the previous buffer back to the BufferQueue + mProducer->cancelBuffer(slot, fence); + + // This should fail since we're requesting a different size + ASSERT_EQ(OK, mProducer->allowAllocation(false)); + ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, false, + WIDTH * 2, HEIGHT * 2, 0, GRALLOC_USAGE_SW_WRITE_OFTEN)); +} + } // namespace android diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp index abd3724..2dc9ccc 100644 --- a/libs/gui/tests/CpuConsumer_test.cpp +++ b/libs/gui/tests/CpuConsumer_test.cpp @@ -94,7 +94,7 @@ protected: mPendingFrames--; } - virtual void onFrameAvailable() { + virtual void onFrameAvailable(const BufferItem&) { Mutex::Autolock lock(mMutex); mPendingFrames++; mCondition.signal(); @@ -125,7 +125,7 @@ protected: mPendingFrames--; } - virtual void onFrameAvailable() { + virtual void onFrameAvailable(const BufferItem&) { Mutex::Autolock lock(mMutex); mPendingFrames++; mFrameCondition.signal(); @@ -166,7 +166,7 @@ void checkPixel(const CpuConsumer::LockedBuffer &buf, uint32_t x, uint32_t y, uint32_t r, uint32_t g=0, uint32_t b=0) { // Ignores components that don't exist for given pixel switch(buf.format) { - case HAL_PIXEL_FORMAT_RAW_SENSOR: { + case HAL_PIXEL_FORMAT_RAW16: { String8 msg; uint16_t *bPtr = (uint16_t*)buf.data; bPtr += y * buf.stride + x; @@ -429,7 +429,7 @@ void checkBayerRawBuffer(const CpuConsumer::LockedBuffer &buf) { void checkAnyBuffer(const CpuConsumer::LockedBuffer &buf, int format) { switch (format) { - case HAL_PIXEL_FORMAT_RAW_SENSOR: + case HAL_PIXEL_FORMAT_RAW16: checkBayerRawBuffer(buf); break; case HAL_PIXEL_FORMAT_Y8: @@ -457,9 +457,12 @@ void configureANW(const sp<ANativeWindow>& anw, const CpuConsumerTestParams& params, int maxBufferSlack) { status_t err; - err = native_window_set_buffers_geometry(anw.get(), - params.width, params.height, params.format); - ASSERT_NO_ERROR(err, "set_buffers_geometry error: "); + err = native_window_set_buffers_dimensions(anw.get(), + params.width, params.height); + ASSERT_NO_ERROR(err, "set_buffers_dimensions error: "); + + err = native_window_set_buffers_format(anw.get(), params.format); + ASSERT_NO_ERROR(err, "set_buffers_format error: "); err = native_window_set_usage(anw.get(), GRALLOC_USAGE_SW_WRITE_OFTEN); @@ -505,7 +508,7 @@ void produceOneFrame(const sp<ANativeWindow>& anw, case HAL_PIXEL_FORMAT_YV12: fillYV12Buffer(img, params.width, params.height, *stride); break; - case HAL_PIXEL_FORMAT_RAW_SENSOR: + case HAL_PIXEL_FORMAT_RAW16: fillBayerRawBuffer(img, params.width, params.height, buf->getStride()); break; case HAL_PIXEL_FORMAT_Y8: @@ -537,7 +540,7 @@ void produceOneFrame(const sp<ANativeWindow>& anw, ASSERT_NO_ERROR(err, "queueBuffer error:"); }; -// This test is disabled because the HAL_PIXEL_FORMAT_RAW_SENSOR format is not +// This test is disabled because the HAL_PIXEL_FORMAT_RAW16 format is not // supported on all devices. TEST_P(CpuConsumerTest, FromCpuSingle) { status_t err; @@ -571,7 +574,7 @@ TEST_P(CpuConsumerTest, FromCpuSingle) { mCC->unlockBuffer(b); } -// This test is disabled because the HAL_PIXEL_FORMAT_RAW_SENSOR format is not +// This test is disabled because the HAL_PIXEL_FORMAT_RAW16 format is not // supported on all devices. TEST_P(CpuConsumerTest, FromCpuManyInQueue) { status_t err; @@ -614,7 +617,7 @@ TEST_P(CpuConsumerTest, FromCpuManyInQueue) { } } -// This test is disabled because the HAL_PIXEL_FORMAT_RAW_SENSOR format is not +// This test is disabled because the HAL_PIXEL_FORMAT_RAW16 format is not // supported on all devices. TEST_P(CpuConsumerTest, FromCpuLockMax) { status_t err; @@ -710,12 +713,12 @@ CpuConsumerTestParams y16TestSets[] = { }; CpuConsumerTestParams rawTestSets[] = { - { 512, 512, 1, HAL_PIXEL_FORMAT_RAW_SENSOR}, - { 512, 512, 3, HAL_PIXEL_FORMAT_RAW_SENSOR}, - { 2608, 1960, 1, HAL_PIXEL_FORMAT_RAW_SENSOR}, - { 2608, 1960, 3, HAL_PIXEL_FORMAT_RAW_SENSOR}, - { 100, 100, 1, HAL_PIXEL_FORMAT_RAW_SENSOR}, - { 100, 100, 3, HAL_PIXEL_FORMAT_RAW_SENSOR}, + { 512, 512, 1, HAL_PIXEL_FORMAT_RAW16}, + { 512, 512, 3, HAL_PIXEL_FORMAT_RAW16}, + { 2608, 1960, 1, HAL_PIXEL_FORMAT_RAW16}, + { 2608, 1960, 3, HAL_PIXEL_FORMAT_RAW16}, + { 100, 100, 1, HAL_PIXEL_FORMAT_RAW16}, + { 100, 100, 3, HAL_PIXEL_FORMAT_RAW16}, }; CpuConsumerTestParams rgba8888TestSets[] = { diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp index 8d5fd8f..ff58420 100644 --- a/libs/gui/tests/IGraphicBufferProducer_test.cpp +++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp @@ -38,30 +38,31 @@ #define TEST_CONTROLLED_BY_APP false #define TEST_PRODUCER_USAGE_BITS (0) -// TODO: Make these public constants in a header -enum { +namespace android { + +namespace { // Default dimensions before setDefaultBufferSize is called - DEFAULT_WIDTH = 1, - DEFAULT_HEIGHT = 1, + const uint32_t DEFAULT_WIDTH = 1; + const uint32_t DEFAULT_HEIGHT = 1; // Default format before setDefaultBufferFormat is called - DEFAULT_FORMAT = HAL_PIXEL_FORMAT_RGBA_8888, + const PixelFormat DEFAULT_FORMAT = HAL_PIXEL_FORMAT_RGBA_8888; // Default transform hint before setTransformHint is called - DEFAULT_TRANSFORM_HINT = 0, -}; + const uint32_t DEFAULT_TRANSFORM_HINT = 0; -namespace android { + // TODO: Make these constants in header + const int DEFAULT_CONSUMER_USAGE_BITS = 0; -namespace { -// Parameters for a generic "valid" input for queueBuffer. -const int64_t QUEUE_BUFFER_INPUT_TIMESTAMP = 1384888611; -const bool QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP = false; -const Rect QUEUE_BUFFER_INPUT_RECT = Rect(DEFAULT_WIDTH, DEFAULT_HEIGHT); -const int QUEUE_BUFFER_INPUT_SCALING_MODE = 0; -const int QUEUE_BUFFER_INPUT_TRANSFORM = 0; -const bool QUEUE_BUFFER_INPUT_ASYNC = false; -const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE; + // Parameters for a generic "valid" input for queueBuffer. + const int64_t QUEUE_BUFFER_INPUT_TIMESTAMP = 1384888611; + const bool QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP = false; + const android_dataspace QUEUE_BUFFER_INPUT_DATASPACE = HAL_DATASPACE_UNKNOWN; + const Rect QUEUE_BUFFER_INPUT_RECT = Rect(DEFAULT_WIDTH, DEFAULT_HEIGHT); + const int QUEUE_BUFFER_INPUT_SCALING_MODE = 0; + const int QUEUE_BUFFER_INPUT_TRANSFORM = 0; + const bool QUEUE_BUFFER_INPUT_ASYNC = false; + const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE; }; // namespace anonymous struct DummyConsumer : public BnConsumerListener { @@ -126,6 +127,7 @@ protected: QueueBufferInputBuilder() { timestamp = QUEUE_BUFFER_INPUT_TIMESTAMP; isAutoTimestamp = QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP; + dataSpace = QUEUE_BUFFER_INPUT_DATASPACE; crop = QUEUE_BUFFER_INPUT_RECT; scalingMode = QUEUE_BUFFER_INPUT_SCALING_MODE; transform = QUEUE_BUFFER_INPUT_TRANSFORM; @@ -137,6 +139,7 @@ protected: return IGraphicBufferProducer::QueueBufferInput( timestamp, isAutoTimestamp, + dataSpace, crop, scalingMode, transform, @@ -154,6 +157,11 @@ protected: return *this; } + QueueBufferInputBuilder& setDataSpace(android_dataspace dataSpace) { + this->dataSpace = dataSpace; + return *this; + } + QueueBufferInputBuilder& setCrop(Rect crop) { this->crop = crop; return *this; @@ -182,6 +190,7 @@ protected: private: int64_t timestamp; bool isAutoTimestamp; + android_dataspace dataSpace; Rect crop; int scalingMode; uint32_t transform; @@ -264,15 +273,12 @@ TEST_F(IGraphicBufferProducerTest, Disconnect_ReturnsError) { TEST_F(IGraphicBufferProducerTest, Query_Succeeds) { ASSERT_NO_FATAL_FAILURE(ConnectProducer()); - // TODO: Make these constants in header - const int DEFAULT_CONSUMER_USAGE_BITS = 0; - - int value = -1; + int32_t value = -1; EXPECT_OK(mProducer->query(NATIVE_WINDOW_WIDTH, &value)); - EXPECT_EQ(DEFAULT_WIDTH, value); + EXPECT_EQ(DEFAULT_WIDTH, static_cast<uint32_t>(value)); EXPECT_OK(mProducer->query(NATIVE_WINDOW_HEIGHT, &value)); - EXPECT_EQ(DEFAULT_HEIGHT, value); + EXPECT_EQ(DEFAULT_HEIGHT, static_cast<uint32_t>(value)); EXPECT_OK(mProducer->query(NATIVE_WINDOW_FORMAT, &value)); EXPECT_EQ(DEFAULT_FORMAT, value); @@ -293,7 +299,7 @@ TEST_F(IGraphicBufferProducerTest, Query_ReturnsError) { ASSERT_NO_FATAL_FAILURE(ConnectProducer()); // One past the end of the last 'query' enum value. Update this if we add more enums. - const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_CONSUMER_USAGE_BITS + 1; + const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_DEFAULT_DATASPACE + 1; int value; // What was out of range @@ -360,7 +366,7 @@ TEST_F(IGraphicBufferProducerTest, Queue_Succeeds) { EXPECT_EQ(DEFAULT_WIDTH, width); EXPECT_EQ(DEFAULT_HEIGHT, height); EXPECT_EQ(DEFAULT_TRANSFORM_HINT, transformHint); - EXPECT_EQ(1, numPendingBuffers); // since queueBuffer was called exactly once + EXPECT_EQ(1u, numPendingBuffers); // since queueBuffer was called exactly once } // Buffer was not in the dequeued state diff --git a/libs/gui/tests/SRGB_test.cpp b/libs/gui/tests/SRGB_test.cpp index 2d5b8aa..3b11b97 100644 --- a/libs/gui/tests/SRGB_test.cpp +++ b/libs/gui/tests/SRGB_test.cpp @@ -17,8 +17,14 @@ #define LOG_TAG "SRGB_test" //#define LOG_NDEBUG 0 +// Ignore for this file because it flags every instance of +// ASSERT_EQ(GL_NO_ERROR, glGetError()); +#pragma clang diagnostic ignored "-Wsign-compare" + #include "GLTest.h" +#include <math.h> + #include <gui/CpuConsumer.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> @@ -212,10 +218,11 @@ protected: ASSERT_EQ(GL_NO_ERROR, glGetError()); } - void checkLockedBuffer(PixelFormat format) { + void checkLockedBuffer(PixelFormat format, android_dataspace dataSpace) { ASSERT_EQ(mLockedBuffer.format, format); ASSERT_EQ(mLockedBuffer.width, DISPLAY_WIDTH); ASSERT_EQ(mLockedBuffer.height, DISPLAY_HEIGHT); + ASSERT_EQ(mLockedBuffer.dataSpace, dataSpace); } static bool withinTolerance(int a, int b) { @@ -326,14 +333,15 @@ private: ANativeWindow_Buffer outBuffer; ARect outBufferBounds; mOutputSurface->lock(&outBuffer, &outBufferBounds); - ASSERT_EQ(mLockedBuffer.width, outBuffer.width); - ASSERT_EQ(mLockedBuffer.height, outBuffer.height); - ASSERT_EQ(mLockedBuffer.stride, outBuffer.stride); + ASSERT_EQ(mLockedBuffer.width, static_cast<uint32_t>(outBuffer.width)); + ASSERT_EQ(mLockedBuffer.height, static_cast<uint32_t>(outBuffer.height)); + ASSERT_EQ(mLockedBuffer.stride, static_cast<uint32_t>(outBuffer.stride)); if (mLockedBuffer.format == outBuffer.format) { memcpy(outBuffer.bits, mLockedBuffer.data, bufferSize); } else { - ASSERT_EQ(mLockedBuffer.format, PIXEL_FORMAT_sRGB_A_8888); + ASSERT_EQ(mLockedBuffer.format, PIXEL_FORMAT_RGBA_8888); + ASSERT_EQ(mLockedBuffer.dataSpace, HAL_DATASPACE_SRGB); ASSERT_EQ(outBuffer.format, PIXEL_FORMAT_RGBA_8888); uint8_t* outPointer = reinterpret_cast<uint8_t*>(outBuffer.bits); for (int y = 0; y < outBuffer.height; ++y) { @@ -378,7 +386,8 @@ TEST_F(SRGBTest, GLRenderFromSRGBTexture) { // Lock ASSERT_EQ(NO_ERROR, mCpuConsumer->lockNextBuffer(&mLockedBuffer)); - ASSERT_NO_FATAL_FAILURE(checkLockedBuffer(PIXEL_FORMAT_RGBA_8888)); + ASSERT_NO_FATAL_FAILURE( + checkLockedBuffer(PIXEL_FORMAT_RGBA_8888, HAL_DATASPACE_UNKNOWN)); // Compare a pixel in the middle of each texture int midSRGBOffset = (DISPLAY_HEIGHT / 4) * mLockedBuffer.stride * @@ -396,7 +405,8 @@ TEST_F(SRGBTest, GLRenderFromSRGBTexture) { // the debug surface if necessary } -TEST_F(SRGBTest, RenderToSRGBSurface) { +// XXX: Disabled since we don't currently expect this to work +TEST_F(SRGBTest, DISABLED_RenderToSRGBSurface) { ASSERT_NO_FATAL_FAILURE(initShaders()); // By default, the first buffer we write into will be RGB @@ -409,7 +419,8 @@ TEST_F(SRGBTest, RenderToSRGBSurface) { // Lock ASSERT_EQ(NO_ERROR, mCpuConsumer->lockNextBuffer(&mLockedBuffer)); - ASSERT_NO_FATAL_FAILURE(checkLockedBuffer(PIXEL_FORMAT_RGBA_8888)); + ASSERT_NO_FATAL_FAILURE( + checkLockedBuffer(PIXEL_FORMAT_RGBA_8888, HAL_DATASPACE_UNKNOWN)); // Save the values of the middle pixel for later comparison against SRGB uint8_t values[PIXEL_SIZE] = {}; @@ -458,7 +469,8 @@ TEST_F(SRGBTest, RenderToSRGBSurface) { ASSERT_EQ(NO_ERROR, mCpuConsumer->lockNextBuffer(&mLockedBuffer)); // Make sure we actually got the SRGB buffer on the consumer side - ASSERT_NO_FATAL_FAILURE(checkLockedBuffer(PIXEL_FORMAT_sRGB_A_8888)); + ASSERT_NO_FATAL_FAILURE( + checkLockedBuffer(PIXEL_FORMAT_RGBA_8888, HAL_DATASPACE_SRGB)); // Verify that the stored value is the same, accounting for RGB/SRGB for (int c = 0; c < PIXEL_SIZE; ++c) { diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp index 4e63a6f..00cc39d 100644 --- a/libs/gui/tests/StreamSplitter_test.cpp +++ b/libs/gui/tests/StreamSplitter_test.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "StreamSplitter_test" //#define LOG_NDEBUG 0 +#include <gui/BufferItem.h> #include <gui/BufferQueue.h> #include <gui/IConsumerListener.h> #include <gui/ISurfaceComposer.h> @@ -75,6 +76,8 @@ private: int mAllocCount; }; +static const uint32_t TEST_DATA = 0x12345678u; + TEST_F(StreamSplitterTest, OneInputOneOutput) { sp<CountedAllocator> allocator(new CountedAllocator); @@ -107,21 +110,22 @@ TEST_F(StreamSplitterTest, OneInputOneOutput) { uint32_t* dataIn; ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, reinterpret_cast<void**>(&dataIn))); - *dataIn = 0x12345678; + *dataIn = TEST_DATA; ASSERT_EQ(OK, buffer->unlock()); IGraphicBufferProducer::QueueBufferInput qbInput(0, false, + HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE); ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput)); - IGraphicBufferConsumer::BufferItem item; + BufferItem item; ASSERT_EQ(OK, outputConsumer->acquireBuffer(&item, 0)); uint32_t* dataOut; ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&dataOut))); - ASSERT_EQ(*dataOut, 0x12345678); + ASSERT_EQ(*dataOut, TEST_DATA); ASSERT_EQ(OK, item.mGraphicBuffer->unlock()); ASSERT_EQ(OK, outputConsumer->releaseBuffer(item.mBuf, item.mFrameNumber, @@ -173,22 +177,23 @@ TEST_F(StreamSplitterTest, OneInputMultipleOutputs) { uint32_t* dataIn; ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, reinterpret_cast<void**>(&dataIn))); - *dataIn = 0x12345678; + *dataIn = TEST_DATA; ASSERT_EQ(OK, buffer->unlock()); IGraphicBufferProducer::QueueBufferInput qbInput(0, false, + HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE); ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput)); for (int output = 0; output < NUM_OUTPUTS; ++output) { - IGraphicBufferConsumer::BufferItem item; + BufferItem item; ASSERT_EQ(OK, outputConsumers[output]->acquireBuffer(&item, 0)); uint32_t* dataOut; ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&dataOut))); - ASSERT_EQ(*dataOut, 0x12345678); + ASSERT_EQ(*dataOut, TEST_DATA); ASSERT_EQ(OK, item.mGraphicBuffer->unlock()); ASSERT_EQ(OK, outputConsumers[output]->releaseBuffer(item.mBuf, @@ -234,6 +239,7 @@ TEST_F(StreamSplitterTest, OutputAbandonment) { outputConsumer->consumerDisconnect(); IGraphicBufferProducer::QueueBufferInput qbInput(0, false, + HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE); ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput)); diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp index 8cdf3bc..d750cd0 100644 --- a/libs/gui/tests/SurfaceTextureClient_test.cpp +++ b/libs/gui/tests/SurfaceTextureClient_test.cpp @@ -207,12 +207,8 @@ TEST_F(SurfaceTextureClientTest, EglSwapBuffersAbandonErrorIsEglBadSurface) { } TEST_F(SurfaceTextureClientTest, BufferGeometryInvalidSizesFail) { - EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), -1, 0, 0)); - EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 0, -1, 0)); - EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, -1)); - EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), -1, -1, 0)); - EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 0, 8, 0)); - EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 8, 0, 0)); + EXPECT_GT(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 8)); + EXPECT_GT(OK, native_window_set_buffers_dimensions(mANW.get(), 8, 0)); } TEST_F(SurfaceTextureClientTest, DefaultGeometryValues) { @@ -226,7 +222,8 @@ TEST_F(SurfaceTextureClientTest, DefaultGeometryValues) { TEST_F(SurfaceTextureClientTest, BufferGeometryCanBeSet) { ANativeWindowBuffer* buf; - EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, PIXEL_FORMAT_RGB_565)); + EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8)); + EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565)); ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf)); EXPECT_EQ(16, buf->width); EXPECT_EQ(8, buf->height); @@ -236,7 +233,8 @@ TEST_F(SurfaceTextureClientTest, BufferGeometryCanBeSet) { TEST_F(SurfaceTextureClientTest, BufferGeometryDefaultSizeSetFormat) { ANativeWindowBuffer* buf; - EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, PIXEL_FORMAT_RGB_565)); + EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 0)); + EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565)); ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf)); EXPECT_EQ(1, buf->width); EXPECT_EQ(1, buf->height); @@ -246,7 +244,8 @@ TEST_F(SurfaceTextureClientTest, BufferGeometryDefaultSizeSetFormat) { TEST_F(SurfaceTextureClientTest, BufferGeometrySetSizeDefaultFormat) { ANativeWindowBuffer* buf; - EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, 0)); + EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8)); + EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0)); ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf)); EXPECT_EQ(16, buf->width); EXPECT_EQ(8, buf->height); @@ -256,13 +255,15 @@ TEST_F(SurfaceTextureClientTest, BufferGeometrySetSizeDefaultFormat) { TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeUnset) { ANativeWindowBuffer* buf; - EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, 0)); + EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8)); + EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0)); ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf)); EXPECT_EQ(16, buf->width); EXPECT_EQ(8, buf->height); EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format); ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1)); - EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, 0)); + EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 0)); + EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0)); ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf)); EXPECT_EQ(1, buf->width); EXPECT_EQ(1, buf->height); @@ -272,7 +273,8 @@ TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeUnset) { TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeChangedWithoutFormat) { ANativeWindowBuffer* buf; - EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, PIXEL_FORMAT_RGB_565)); + EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 0)); + EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565)); ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf)); EXPECT_EQ(1, buf->width); EXPECT_EQ(1, buf->height); @@ -330,7 +332,8 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeVsGeometry) { EXPECT_EQ(8, buf[1]->height); ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1)); ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1], -1)); - EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 12, 24, 0)); + EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 12, 24)); + EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0)); ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1])); EXPECT_NE(buf[0], buf[1]); @@ -468,7 +471,8 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeMinUndequeued) { // Once we've queued a buffer, however we should not be able to dequeue more // than (buffer-count - MIN_UNDEQUEUED_BUFFERS), which is 2 in this case. - EXPECT_EQ(-EBUSY, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1])); + EXPECT_EQ(INVALID_OPERATION, + native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1])); ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1)); ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2], -1)); @@ -620,7 +624,8 @@ TEST_F(SurfaceTextureClientTest, GetTransformMatrixSucceedsAfterFreeingBuffersWi crop.bottom = 5; ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4)); - ASSERT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 8, 8, 0)); + ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 8, 8)); + ASSERT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0)); ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &crop)); ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1)); @@ -668,7 +673,8 @@ TEST_F(SurfaceTextureClientTest, QueryFormatAfterSettingWorks) { const int numFmts = (sizeof(fmts) / sizeof(fmts[0])); for (int i = 0; i < numFmts; i++) { int fmt = -1; - ASSERT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, fmts[i])); + ASSERT_EQ(OK, native_window_set_buffers_dimensions(anw.get(), 0, 0)); + ASSERT_EQ(OK, native_window_set_buffers_format(anw.get(), fmts[i])); ASSERT_EQ(OK, anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt)); EXPECT_EQ(fmts[i], fmt); } diff --git a/libs/gui/tests/SurfaceTextureFBO_test.cpp b/libs/gui/tests/SurfaceTextureFBO_test.cpp index b165ae6..c243fc0 100644 --- a/libs/gui/tests/SurfaceTextureFBO_test.cpp +++ b/libs/gui/tests/SurfaceTextureFBO_test.cpp @@ -27,8 +27,10 @@ TEST_F(SurfaceTextureFBOTest, BlitFromCpuFilledBufferToFbo) { const int texWidth = 64; const int texHeight = 64; - ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), - texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888)); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(), + texWidth, texHeight)); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(), + HAL_PIXEL_FORMAT_RGBA_8888)); ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); diff --git a/libs/gui/tests/SurfaceTextureGL_test.cpp b/libs/gui/tests/SurfaceTextureGL_test.cpp index fa1e1b7..fad133f 100644 --- a/libs/gui/tests/SurfaceTextureGL_test.cpp +++ b/libs/gui/tests/SurfaceTextureGL_test.cpp @@ -28,8 +28,10 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) { const int texWidth = 64; const int texHeight = 66; - ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), - texWidth, texHeight, HAL_PIXEL_FORMAT_YV12)); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(), + texWidth, texHeight)); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(), + HAL_PIXEL_FORMAT_YV12)); ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); @@ -74,8 +76,10 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferPow2) { const int texWidth = 64; const int texHeight = 64; - ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), - texWidth, texHeight, HAL_PIXEL_FORMAT_YV12)); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(), + texWidth, texHeight)); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(), + HAL_PIXEL_FORMAT_YV12)); ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); @@ -120,8 +124,10 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) { const int texWidth = 64; const int texHeight = 66; - ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), - texWidth, texHeight, HAL_PIXEL_FORMAT_YV12)); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(), + texWidth, texHeight)); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(), + HAL_PIXEL_FORMAT_YV12)); ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); @@ -185,8 +191,10 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) { enum { numFrames = 1024 }; ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2)); - ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), - texWidth, texHeight, HAL_PIXEL_FORMAT_YV12)); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(), + texWidth, texHeight)); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(), + HAL_PIXEL_FORMAT_YV12)); ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), GRALLOC_USAGE_SW_WRITE_OFTEN)); @@ -326,8 +334,10 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledRGBABufferNpot) { const int texWidth = 64; const int texHeight = 66; - ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), - texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888)); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(), + texWidth, texHeight)); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(), + HAL_PIXEL_FORMAT_RGBA_8888)); ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); @@ -368,8 +378,10 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledRGBABufferPow2) { const int texWidth = 64; const int texHeight = 64; - ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), - texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888)); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(), + texWidth, texHeight)); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(), + HAL_PIXEL_FORMAT_RGBA_8888)); ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 5e6aeef..4f87824 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -155,4 +155,26 @@ TEST_F(SurfaceTest, QueryConsumerUsage) { ASSERT_EQ(TEST_USAGE_FLAGS, flags); } +TEST_F(SurfaceTest, QueryDefaultBuffersDataSpace) { + const android_dataspace TEST_DATASPACE = HAL_DATASPACE_SRGB; + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1); + + cpuConsumer->setDefaultBufferDataSpace(TEST_DATASPACE); + + sp<Surface> s = new Surface(producer); + + sp<ANativeWindow> anw(s); + + android_dataspace dataSpace; + + int err = anw->query(anw.get(), NATIVE_WINDOW_DEFAULT_DATASPACE, + reinterpret_cast<int*>(&dataSpace)); + + ASSERT_EQ(NO_ERROR, err); + ASSERT_EQ(TEST_DATASPACE, dataSpace); +} + } diff --git a/libs/input/tests/Android.mk b/libs/input/tests/Android.mk index 9612a65..5bfa3d4 100644 --- a/libs/input/tests/Android.mk +++ b/libs/input/tests/Android.mk @@ -1,6 +1,5 @@ # Build the unit tests. LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) # Build the unit tests. test_src_files := \ @@ -14,14 +13,10 @@ shared_libraries := \ libutils \ libbinder \ libui \ - libstlport - -static_libraries := \ - libgtest \ - libgtest_main $(foreach file,$(test_src_files), \ $(eval include $(CLEAR_VARS)) \ + $(eval LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk) \ $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \ $(eval LOCAL_STATIC_LIBRARIES := $(static_libraries)) \ $(eval LOCAL_SRC_FILES := $(file)) \ @@ -33,6 +28,7 @@ $(foreach file,$(test_src_files), \ # run. All assertions are static_asserts and will fail during # buildtime if something's wrong. include $(CLEAR_VARS) +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk LOCAL_SRC_FILES := StructLayout_test.cpp LOCAL_MODULE := StructLayout_test LOCAL_CFLAGS := -std=c++11 -O0 diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk index eec97be..1ce8626 100644 --- a/libs/ui/Android.mk +++ b/libs/ui/Android.mk @@ -12,10 +12,28 @@ # See the License for the specific language governing permissions and # limitations under the License. -LOCAL_PATH:= $(call my-dir) +LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES:= \ +LOCAL_CLANG := true +LOCAL_CPPFLAGS := -std=c++1y -Weverything -Werror + +# The static constructors and destructors in this library have not been noted to +# introduce significant overheads +LOCAL_CPPFLAGS += -Wno-exit-time-destructors +LOCAL_CPPFLAGS += -Wno-global-constructors + +# We only care about compiling as C++14 +LOCAL_CPPFLAGS += -Wno-c++98-compat-pedantic + +# We use four-character constants for the GraphicBuffer header, and don't care +# that they're non-portable as long as they're consistent within one execution +LOCAL_CPPFLAGS += -Wno-four-char-constants + +# Don't warn about struct padding +LOCAL_CPPFLAGS += -Wno-padded + +LOCAL_SRC_FILES := \ Fence.cpp \ FramebufferNativeWindow.cpp \ FrameStats.cpp \ @@ -38,7 +56,7 @@ ifneq ($(BOARD_FRAMEBUFFER_FORCE_FORMAT),) LOCAL_CFLAGS += -DFRAMEBUFFER_FORCE_FORMAT=$(BOARD_FRAMEBUFFER_FORCE_FORMAT) endif -LOCAL_MODULE:= libui +LOCAL_MODULE := libui include $(BUILD_SHARED_LIBRARY) diff --git a/libs/ui/Fence.cpp b/libs/ui/Fence.cpp index 3c0306c..bf24ffb 100644 --- a/libs/ui/Fence.cpp +++ b/libs/ui/Fence.cpp @@ -18,10 +18,13 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS //#define LOG_NDEBUG 0 - // This is needed for stdint.h to define INT64_MAX in C++ - #define __STDC_LIMIT_MACROS - +// We would eliminate the non-conforming zero-length array, but we can't since +// this is effectively included from the Linux kernel +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wzero-length-array" #include <sync/sync.h> +#pragma clang diagnostic pop + #include <ui/Fence.h> #include <unistd.h> #include <utils/Log.h> @@ -45,7 +48,7 @@ Fence::~Fence() { } } -status_t Fence::wait(unsigned int timeout) { +status_t Fence::wait(int timeout) { ATRACE_CALL(); if (mFenceFd == -1) { return NO_ERROR; @@ -59,7 +62,7 @@ status_t Fence::waitForever(const char* logname) { if (mFenceFd == -1) { return NO_ERROR; } - unsigned int warningTimeout = 3000; + int warningTimeout = 3000; int err = sync_wait(mFenceFd, warningTimeout); if (err < 0 && errno == ETIME) { ALOGE("%s: fence %d didn't signal in %u ms", logname, mFenceFd, @@ -127,7 +130,7 @@ nsecs_t Fence::getSignalTime() const { } size_t Fence::getFlattenedSize() const { - return 1; + return 4; } size_t Fence::getFdCount() const { @@ -138,7 +141,9 @@ status_t Fence::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) c if (size < getFlattenedSize() || count < getFdCount()) { return NO_MEMORY; } - FlattenableUtils::write(buffer, size, (uint32_t)getFdCount()); + // Cast to uint32_t since the size of a size_t can vary between 32- and + // 64-bit processes + FlattenableUtils::write(buffer, size, static_cast<uint32_t>(getFdCount())); if (isValid()) { *fds++ = mFenceFd; count--; diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp index 918f2e7..3ead25c 100644 --- a/libs/ui/FramebufferNativeWindow.cpp +++ b/libs/ui/FramebufferNativeWindow.cpp @@ -1,17 +1,17 @@ -/* +/* ** ** Copyright 2007 The Android Open Source Project ** -** Licensed under the Apache License Version 2.0(the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at +** Licensed under the Apache License Version 2.0(the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at ** -** http://www.apache.org/licenses/LICENSE-2.0 +** http://www.apache.org/licenses/LICENSE-2.0 ** -** Unless required by applicable law or agreed to in writing software -** distributed under the License is distributed on an "AS IS" BASIS -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. -** See the License for the specific language governing permissions and +** Unless required by applicable law or agreed to in writing software +** distributed under the License is distributed on an "AS IS" BASIS +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. +** See the License for the specific language governing permissions and ** limitations under the License. */ @@ -29,7 +29,9 @@ #include <ui/ANativeObjectBase.h> #include <ui/Fence.h> +#define INCLUDED_FROM_FRAMEBUFFER_NATIVE_WINDOW_CPP #include <ui/FramebufferNativeWindow.h> +#undef INCLUDED_FROM_FRAMEBUFFER_NATIVE_WINDOW_CPP #include <ui/Rect.h> #include <EGL/egl.h> @@ -41,11 +43,11 @@ namespace android { // ---------------------------------------------------------------------------- -class NativeBuffer +class NativeBuffer final : public ANativeObjectBase< - ANativeWindowBuffer, - NativeBuffer, - LightRefBase<NativeBuffer> > + ANativeWindowBuffer, + NativeBuffer, + LightRefBase<NativeBuffer>> { public: NativeBuffer(int w, int h, int f, int u) : BASE() { @@ -55,43 +57,41 @@ public: ANativeWindowBuffer::usage = u; } private: - friend class LightRefBase<NativeBuffer>; - ~NativeBuffer() { }; // this class cannot be overloaded + friend class LightRefBase<NativeBuffer>; }; /* * This implements the (main) framebuffer management. This class is used * mostly by SurfaceFlinger, but also by command line GL application. - * + * * In fact this is an implementation of ANativeWindow on top of * the framebuffer. - * - * Currently it is pretty simple, it manages only two buffers (the front and + * + * Currently it is pretty simple, it manages only two buffers (the front and * back buffer). - * + * */ -FramebufferNativeWindow::FramebufferNativeWindow() +FramebufferNativeWindow::FramebufferNativeWindow() : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false) { hw_module_t const* module; if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { - int stride; int err; int i; err = framebuffer_open(module, &fbDev); ALOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err)); - + err = gralloc_open(module, &grDev); ALOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err)); // bail out if we can't initialize the modules if (!fbDev || !grDev) return; - + mUpdateOnDemand = (fbDev->setUpdateRect != 0); - + // initialize the buffer FIFO if(fbDev->numFramebuffers >= MIN_NUM_FRAME_BUFFERS && fbDev->numFramebuffers <= MAX_NUM_FRAME_BUFFERS){ @@ -114,36 +114,37 @@ FramebufferNativeWindow::FramebufferNativeWindow() *((uint32_t *)&fbDev->format) = FRAMEBUFFER_FORCE_FORMAT; #endif - for (i = 0; i < mNumBuffers; i++) - { - buffers[i] = new NativeBuffer( - fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); + for (i = 0; i < mNumBuffers; i++) { + buffers[i] = new NativeBuffer( + static_cast<int>(fbDev->width), + static_cast<int>(fbDev->height), + fbDev->format, GRALLOC_USAGE_HW_FB); } - for (i = 0; i < mNumBuffers; i++) - { - err = grDev->alloc(grDev, - fbDev->width, fbDev->height, fbDev->format, - GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride); - - ALOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s", - i, fbDev->width, fbDev->height, strerror(-err)); - - if (err) - { - mNumBuffers = i; - mNumFreeBuffers = i; - mBufferHead = mNumBuffers-1; - break; - } + for (i = 0; i < mNumBuffers; i++) { + err = grDev->alloc(grDev, + static_cast<int>(fbDev->width), + static_cast<int>(fbDev->height), + fbDev->format, GRALLOC_USAGE_HW_FB, + &buffers[i]->handle, &buffers[i]->stride); + + ALOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s", + i, fbDev->width, fbDev->height, strerror(-err)); + + if (err) { + mNumBuffers = i; + mNumFreeBuffers = i; + mBufferHead = mNumBuffers-1; + break; + } } - const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags; + const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags; const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi; const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi; - const_cast<int&>(ANativeWindow::minSwapInterval) = + const_cast<int&>(ANativeWindow::minSwapInterval) = fbDev->minSwapInterval; - const_cast<int&>(ANativeWindow::maxSwapInterval) = + const_cast<int&>(ANativeWindow::maxSwapInterval) = fbDev->maxSwapInterval; } else { ALOGE("Couldn't get gralloc module"); @@ -160,7 +161,7 @@ FramebufferNativeWindow::FramebufferNativeWindow() ANativeWindow::queueBuffer_DEPRECATED = queueBuffer_DEPRECATED; } -FramebufferNativeWindow::~FramebufferNativeWindow() +FramebufferNativeWindow::~FramebufferNativeWindow() { if (grDev) { for(int i = 0; i < mNumBuffers; i++) { @@ -176,7 +177,7 @@ FramebufferNativeWindow::~FramebufferNativeWindow() } } -status_t FramebufferNativeWindow::setUpdateRectangle(const Rect& r) +status_t FramebufferNativeWindow::setUpdateRectangle(const Rect& r) { if (!mUpdateOnDemand) { return INVALID_OPERATION; @@ -193,7 +194,7 @@ status_t FramebufferNativeWindow::compositionComplete() } int FramebufferNativeWindow::setSwapInterval( - ANativeWindow* window, int interval) + ANativeWindow* window, int interval) { framebuffer_device_t* fb = getSelf(window)->fbDev; return fb->setSwapInterval(fb, interval); @@ -217,7 +218,7 @@ int FramebufferNativeWindow::getCurrentBufferIndex() const return index; } -int FramebufferNativeWindow::dequeueBuffer_DEPRECATED(ANativeWindow* window, +int FramebufferNativeWindow::dequeueBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer** buffer) { int fenceFd = -1; @@ -232,12 +233,11 @@ int FramebufferNativeWindow::dequeueBuffer_DEPRECATED(ANativeWindow* window, return result; } -int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window, +int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd) { FramebufferNativeWindow* self = getSelf(window); Mutex::Autolock _l(self->mutex); - framebuffer_device_t* fb = self->fbDev; int index = self->mBufferHead++; if (self->mBufferHead >= self->mNumBuffers) @@ -247,7 +247,7 @@ int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window, while (self->mNumFreeBuffers < 2) { self->mCondition.wait(self->mutex); } - ALOG_ASSERT(self->buffers[index] != self->front); + ALOG_ASSERT(self->buffers[index] != self->front, ""); // get this buffer self->mNumFreeBuffers--; @@ -259,19 +259,19 @@ int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window, return 0; } -int FramebufferNativeWindow::lockBuffer_DEPRECATED(ANativeWindow* /*window*/, +int FramebufferNativeWindow::lockBuffer_DEPRECATED(ANativeWindow* /*window*/, ANativeWindowBuffer* /*buffer*/) { return NO_ERROR; } -int FramebufferNativeWindow::queueBuffer_DEPRECATED(ANativeWindow* window, +int FramebufferNativeWindow::queueBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer) { return queueBuffer(window, buffer, -1); } -int FramebufferNativeWindow::queueBuffer(ANativeWindow* window, +int FramebufferNativeWindow::queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) { FramebufferNativeWindow* self = getSelf(window); @@ -282,7 +282,6 @@ int FramebufferNativeWindow::queueBuffer(ANativeWindow* window, sp<Fence> fence(new Fence(fenceFd)); fence->wait(Fence::TIMEOUT_NEVER); - const int index = self->mCurrentBufferIndex; int res = fb->post(fb, handle); self->front = static_cast<NativeBuffer*>(buffer); self->mNumFreeBuffers++; @@ -291,17 +290,17 @@ int FramebufferNativeWindow::queueBuffer(ANativeWindow* window, } int FramebufferNativeWindow::query(const ANativeWindow* window, - int what, int* value) + int what, int* value) { const FramebufferNativeWindow* self = getSelf(window); Mutex::Autolock _l(self->mutex); framebuffer_device_t* fb = self->fbDev; switch (what) { case NATIVE_WINDOW_WIDTH: - *value = fb->width; + *value = static_cast<int>(fb->width); return NO_ERROR; case NATIVE_WINDOW_HEIGHT: - *value = fb->height; + *value = static_cast<int>(fb->height); return NO_ERROR; case NATIVE_WINDOW_FORMAT: *value = fb->format; @@ -313,10 +312,10 @@ int FramebufferNativeWindow::query(const ANativeWindow* window, *value = 0; return NO_ERROR; case NATIVE_WINDOW_DEFAULT_WIDTH: - *value = fb->width; + *value = static_cast<int>(fb->width); return NO_ERROR; case NATIVE_WINDOW_DEFAULT_HEIGHT: - *value = fb->height; + *value = static_cast<int>(fb->height); return NO_ERROR; case NATIVE_WINDOW_TRANSFORM_HINT: *value = 0; @@ -357,7 +356,8 @@ int FramebufferNativeWindow::perform(ANativeWindow* /*window*/, }; // namespace android // ---------------------------------------------------------------------------- -using namespace android; +using android::sp; +using android::FramebufferNativeWindow; EGLNativeWindowType android_createDisplaySurface(void) { @@ -368,5 +368,5 @@ EGLNativeWindowType android_createDisplaySurface(void) sp<FramebufferNativeWindow> ref(w); return NULL; } - return (EGLNativeWindowType)w; + return static_cast<EGLNativeWindowType>(w); } diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 3ae8840..6a42a22 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -45,40 +45,40 @@ GraphicBuffer::GraphicBuffer() : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()), mInitCheck(NO_ERROR), mId(getUniqueId()) { - width = - height = - stride = - format = + width = + height = + stride = + format = usage = 0; handle = NULL; } -GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, - PixelFormat reqFormat, uint32_t reqUsage) +GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, + PixelFormat inFormat, uint32_t inUsage) : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()), mInitCheck(NO_ERROR), mId(getUniqueId()) { - width = - height = - stride = - format = + width = + height = + stride = + format = usage = 0; handle = NULL; - mInitCheck = initSize(w, h, reqFormat, reqUsage); + mInitCheck = initSize(inWidth, inHeight, inFormat, inUsage); } -GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, - PixelFormat inFormat, uint32_t inUsage, - uint32_t inStride, native_handle_t* inHandle, bool keepOwnership) +GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, + PixelFormat inFormat, uint32_t inUsage, uint32_t inStride, + native_handle_t* inHandle, bool keepOwnership) : BASE(), mOwner(keepOwnership ? ownHandle : ownNone), mBufferMapper(GraphicBufferMapper::get()), mInitCheck(NO_ERROR), mId(getUniqueId()) { - width = w; - height = h; - stride = inStride; + width = static_cast<int>(inWidth); + height = static_cast<int>(inHeight); + stride = static_cast<int>(inStride); format = inFormat; - usage = inUsage; + usage = static_cast<int>(inUsage); handle = inHandle; } @@ -116,7 +116,7 @@ void GraphicBuffer::free_handle() } status_t GraphicBuffer::initCheck() const { - return mInitCheck; + return static_cast<status_t>(mInitCheck); } void GraphicBuffer::dumpAllocationsToSystemLog() @@ -131,13 +131,17 @@ ANativeWindowBuffer* GraphicBuffer::getNativeBuffer() const const_cast<GraphicBuffer*>(this)); } -status_t GraphicBuffer::reallocate(uint32_t w, uint32_t h, PixelFormat f, - uint32_t reqUsage) +status_t GraphicBuffer::reallocate(uint32_t inWidth, uint32_t inHeight, + PixelFormat inFormat, uint32_t inUsage) { if (mOwner != ownData) return INVALID_OPERATION; - if (handle && w==width && h==height && f==format && reqUsage==usage) + if (handle && + static_cast<int>(inWidth) == width && + static_cast<int>(inHeight) == height && + inFormat == format && + static_cast<int>(inUsage) == usage) return NO_ERROR; if (handle) { @@ -145,61 +149,74 @@ status_t GraphicBuffer::reallocate(uint32_t w, uint32_t h, PixelFormat f, allocator.free(handle); handle = 0; } - return initSize(w, h, f, reqUsage); + return initSize(inWidth, inHeight, inFormat, inUsage); } -status_t GraphicBuffer::initSize(uint32_t w, uint32_t h, PixelFormat format, - uint32_t reqUsage) +bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight, + PixelFormat inFormat, uint32_t inUsage) +{ + if (static_cast<int>(inWidth) != width) return true; + if (static_cast<int>(inHeight) != height) return true; + if (inFormat != format) return true; + if ((static_cast<uint32_t>(usage) & inUsage) != inUsage) return true; + return false; +} + +status_t GraphicBuffer::initSize(uint32_t inWidth, uint32_t inHeight, + PixelFormat inFormat, uint32_t inUsage) { GraphicBufferAllocator& allocator = GraphicBufferAllocator::get(); - status_t err = allocator.alloc(w, h, format, reqUsage, &handle, &stride); + uint32_t outStride = 0; + status_t err = allocator.alloc(inWidth, inHeight, inFormat, inUsage, + &handle, &outStride); if (err == NO_ERROR) { - this->width = w; - this->height = h; - this->format = format; - this->usage = reqUsage; + width = static_cast<int>(inWidth); + height = static_cast<int>(inHeight); + format = inFormat; + usage = static_cast<int>(inUsage); + stride = static_cast<int>(outStride); } return err; } -status_t GraphicBuffer::lock(uint32_t usage, void** vaddr) +status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr) { const Rect lockBounds(width, height); - status_t res = lock(usage, lockBounds, vaddr); + status_t res = lock(inUsage, lockBounds, vaddr); return res; } -status_t GraphicBuffer::lock(uint32_t usage, const Rect& rect, void** vaddr) +status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr) { - if (rect.left < 0 || rect.right > this->width || - rect.top < 0 || rect.bottom > this->height) { + if (rect.left < 0 || rect.right > width || + rect.top < 0 || rect.bottom > height) { ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", - rect.left, rect.top, rect.right, rect.bottom, - this->width, this->height); + rect.left, rect.top, rect.right, rect.bottom, + width, height); return BAD_VALUE; } - status_t res = getBufferMapper().lock(handle, usage, rect, vaddr); + status_t res = getBufferMapper().lock(handle, inUsage, rect, vaddr); return res; } -status_t GraphicBuffer::lockYCbCr(uint32_t usage, android_ycbcr *ycbcr) +status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, android_ycbcr* ycbcr) { const Rect lockBounds(width, height); - status_t res = lockYCbCr(usage, lockBounds, ycbcr); + status_t res = lockYCbCr(inUsage, lockBounds, ycbcr); return res; } -status_t GraphicBuffer::lockYCbCr(uint32_t usage, const Rect& rect, - android_ycbcr *ycbcr) +status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, const Rect& rect, + android_ycbcr* ycbcr) { - if (rect.left < 0 || rect.right > this->width || - rect.top < 0 || rect.bottom > this->height) { + if (rect.left < 0 || rect.right > width || + rect.top < 0 || rect.bottom > height) { ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", rect.left, rect.top, rect.right, rect.bottom, - this->width, this->height); + width, height); return BAD_VALUE; } - status_t res = getBufferMapper().lockYCbCr(handle, usage, rect, ycbcr); + status_t res = getBufferMapper().lockYCbCr(handle, inUsage, rect, ycbcr); return res; } @@ -209,43 +226,48 @@ status_t GraphicBuffer::unlock() return res; } -status_t GraphicBuffer::lockAsync(uint32_t usage, void** vaddr, int fenceFd) +status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd) { const Rect lockBounds(width, height); - status_t res = lockAsync(usage, lockBounds, vaddr, fenceFd); + status_t res = lockAsync(inUsage, lockBounds, vaddr, fenceFd); return res; } -status_t GraphicBuffer::lockAsync(uint32_t usage, const Rect& rect, void** vaddr, int fenceFd) +status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect, + void** vaddr, int fenceFd) { - if (rect.left < 0 || rect.right > this->width || - rect.top < 0 || rect.bottom > this->height) { + if (rect.left < 0 || rect.right > width || + rect.top < 0 || rect.bottom > height) { ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", rect.left, rect.top, rect.right, rect.bottom, - this->width, this->height); + width, height); return BAD_VALUE; } - status_t res = getBufferMapper().lockAsync(handle, usage, rect, vaddr, fenceFd); + status_t res = getBufferMapper().lockAsync(handle, inUsage, rect, vaddr, + fenceFd); return res; } -status_t GraphicBuffer::lockAsyncYCbCr(uint32_t usage, android_ycbcr *ycbcr, int fenceFd) +status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, android_ycbcr* ycbcr, + int fenceFd) { const Rect lockBounds(width, height); - status_t res = lockAsyncYCbCr(usage, lockBounds, ycbcr, fenceFd); + status_t res = lockAsyncYCbCr(inUsage, lockBounds, ycbcr, fenceFd); return res; } -status_t GraphicBuffer::lockAsyncYCbCr(uint32_t usage, const Rect& rect, android_ycbcr *ycbcr, int fenceFd) +status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, const Rect& rect, + android_ycbcr* ycbcr, int fenceFd) { - if (rect.left < 0 || rect.right > this->width || - rect.top < 0 || rect.bottom > this->height) { + if (rect.left < 0 || rect.right > width || + rect.top < 0 || rect.bottom > height) { ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", rect.left, rect.top, rect.right, rect.bottom, - this->width, this->height); + width, height); return BAD_VALUE; } - status_t res = getBufferMapper().lockAsyncYCbCr(handle, usage, rect, ycbcr, fenceFd); + status_t res = getBufferMapper().lockAsyncYCbCr(handle, inUsage, rect, + ycbcr, fenceFd); return res; } @@ -256,11 +278,11 @@ status_t GraphicBuffer::unlockAsync(int *fenceFd) } size_t GraphicBuffer::getFlattenedSize() const { - return (10 + (handle ? handle->numInts : 0))*sizeof(int); + return static_cast<size_t>(10 + (handle ? handle->numInts : 0)) * sizeof(int); } size_t GraphicBuffer::getFdCount() const { - return handle ? handle->numFds : 0; + return static_cast<size_t>(handle ? handle->numFds : 0); } status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const { @@ -285,16 +307,17 @@ status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& if (handle) { buf[8] = handle->numFds; buf[9] = handle->numInts; - native_handle_t const* const h = handle; - memcpy(fds, h->data, h->numFds*sizeof(int)); - memcpy(&buf[10], h->data + h->numFds, h->numInts*sizeof(int)); + memcpy(fds, handle->data, + static_cast<size_t>(handle->numFds) * sizeof(int)); + memcpy(&buf[10], handle->data + handle->numFds, + static_cast<size_t>(handle->numInts) * sizeof(int)); } - buffer = reinterpret_cast<void*>(static_cast<int*>(buffer) + sizeNeeded); + buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded); size -= sizeNeeded; if (handle) { fds += handle->numFds; - count -= handle->numFds; + count -= static_cast<size_t>(handle->numFds); } return NO_ERROR; @@ -307,8 +330,8 @@ status_t GraphicBuffer::unflatten( int const* buf = static_cast<int const*>(buffer); if (buf[0] != 'GBFR') return BAD_TYPE; - const size_t numFds = buf[8]; - const size_t numInts = buf[9]; + const size_t numFds = static_cast<size_t>(buf[8]); + const size_t numInts = static_cast<size_t>(buf[9]); // Limit the maxNumber to be relatively small. The number of fds or ints // should not come close to this number, and the number itself was simply @@ -318,7 +341,7 @@ status_t GraphicBuffer::unflatten( if (numFds >= maxNumber || numInts >= (maxNumber - 10)) { width = height = stride = format = usage = 0; handle = NULL; - ALOGE("unflatten: numFds or numInts is too large: %d, %d", + ALOGE("unflatten: numFds or numInts is too large: %zd, %zd", numFds, numInts); return BAD_VALUE; } @@ -340,15 +363,16 @@ status_t GraphicBuffer::unflatten( stride = buf[3]; format = buf[4]; usage = buf[5]; - native_handle* h = native_handle_create(numFds, numInts); + native_handle* h = native_handle_create( + static_cast<int>(numFds), static_cast<int>(numInts)); if (!h) { width = height = stride = format = usage = 0; handle = NULL; ALOGE("unflatten: native_handle_create failed"); return NO_MEMORY; } - memcpy(h->data, fds, numFds*sizeof(int)); - memcpy(h->data + numFds, &buf[10], numInts*sizeof(int)); + memcpy(h->data, fds, numFds * sizeof(int)); + memcpy(h->data + numFds, &buf[10], numInts * sizeof(int)); handle = h; } else { width = height = stride = format = usage = 0; @@ -371,7 +395,7 @@ status_t GraphicBuffer::unflatten( } } - buffer = reinterpret_cast<void const*>(static_cast<int const*>(buffer) + sizeNeeded); + buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded); size -= sizeNeeded; fds += numFds; count -= numFds; diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp index ff550d9..85e9675 100644 --- a/libs/ui/GraphicBufferAllocator.cpp +++ b/libs/ui/GraphicBufferAllocator.cpp @@ -1,17 +1,17 @@ -/* +/* ** ** Copyright 2009, The Android Open Source Project ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at ** -** http://www.apache.org/licenses/LICENSE-2.0 +** http://www.apache.org/licenses/LICENSE-2.0 ** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and ** limitations under the License. */ @@ -66,11 +66,11 @@ void GraphicBufferAllocator::dump(String8& result) const if (rec.size) { snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %8X | 0x%08x\n", list.keyAt(i), rec.size/1024.0f, - rec.w, rec.s, rec.h, rec.format, rec.usage); + rec.width, rec.stride, rec.height, rec.format, rec.usage); } else { snprintf(buffer, SIZE, "%10p: unknown | %4u (%4u) x %4u | %8X | 0x%08x\n", list.keyAt(i), - rec.w, rec.s, rec.h, rec.format, rec.usage); + rec.width, rec.stride, rec.height, rec.format, rec.usage); } result.append(buffer); total += rec.size; @@ -90,39 +90,40 @@ void GraphicBufferAllocator::dumpToSystemLog() ALOGD("%s", s.string()); } -status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, - int usage, buffer_handle_t* handle, int32_t* stride) +status_t GraphicBufferAllocator::alloc(uint32_t width, uint32_t height, + PixelFormat format, uint32_t usage, buffer_handle_t* handle, + uint32_t* stride) { ATRACE_CALL(); + // make sure to not allocate a N x 0 or 0 x N buffer, since this is // allowed from an API stand-point allocate a 1x1 buffer instead. - if (!w || !h) - w = h = 1; + if (!width || !height) + width = height = 1; // we have a h/w allocator and h/w buffer is requested - status_t err; - - err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride); + status_t err; + + int outStride = 0; + err = mAllocDev->alloc(mAllocDev, static_cast<int>(width), + static_cast<int>(height), format, static_cast<int>(usage), handle, + &outStride); + *stride = static_cast<uint32_t>(outStride); ALOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)", - w, h, format, usage, err, strerror(-err)); - + width, height, format, usage, err, strerror(-err)); + if (err == NO_ERROR) { Mutex::Autolock _l(sLock); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); - int bpp = bytesPerPixel(format); - if (bpp < 0) { - // probably a HAL custom format. in any case, we don't know - // what its pixel size is. - bpp = 0; - } + uint32_t bpp = bytesPerPixel(format); alloc_rec_t rec; - rec.w = w; - rec.h = h; - rec.s = *stride; + rec.width = width; + rec.height = height; + rec.stride = *stride; rec.format = format; rec.usage = usage; - rec.size = h * stride[0] * bpp; + rec.size = static_cast<size_t>(height * (*stride) * bpp); list.add(*handle, rec); } diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp index e949b0c..31bfb2d 100644 --- a/libs/ui/GraphicBufferMapper.cpp +++ b/libs/ui/GraphicBufferMapper.cpp @@ -20,7 +20,12 @@ #include <stdint.h> #include <errno.h> +// We would eliminate the non-conforming zero-length array, but we can't since +// this is effectively included from the Linux kernel +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wzero-length-array" #include <sync/sync.h> +#pragma clang diagnostic pop #include <utils/Errors.h> #include <utils/Log.h> @@ -44,7 +49,7 @@ GraphicBufferMapper::GraphicBufferMapper() int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); ALOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID); if (err == 0) { - mAllocMod = (gralloc_module_t const *)module; + mAllocMod = reinterpret_cast<gralloc_module_t const *>(module); } } @@ -72,13 +77,13 @@ status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle) return err; } -status_t GraphicBufferMapper::lock(buffer_handle_t handle, - int usage, const Rect& bounds, void** vaddr) +status_t GraphicBufferMapper::lock(buffer_handle_t handle, + uint32_t usage, const Rect& bounds, void** vaddr) { ATRACE_CALL(); status_t err; - err = mAllocMod->lock(mAllocMod, handle, usage, + err = mAllocMod->lock(mAllocMod, handle, static_cast<int>(usage), bounds.left, bounds.top, bounds.width(), bounds.height(), vaddr); @@ -87,7 +92,7 @@ status_t GraphicBufferMapper::lock(buffer_handle_t handle, } status_t GraphicBufferMapper::lockYCbCr(buffer_handle_t handle, - int usage, const Rect& bounds, android_ycbcr *ycbcr) + uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr) { ATRACE_CALL(); status_t err; @@ -96,7 +101,7 @@ status_t GraphicBufferMapper::lockYCbCr(buffer_handle_t handle, return -EINVAL; // do not log failure } - err = mAllocMod->lock_ycbcr(mAllocMod, handle, usage, + err = mAllocMod->lock_ycbcr(mAllocMod, handle, static_cast<int>(usage), bounds.left, bounds.top, bounds.width(), bounds.height(), ycbcr); @@ -116,19 +121,19 @@ status_t GraphicBufferMapper::unlock(buffer_handle_t handle) } status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle, - int usage, const Rect& bounds, void** vaddr, int fenceFd) + uint32_t usage, const Rect& bounds, void** vaddr, int fenceFd) { ATRACE_CALL(); status_t err; if (mAllocMod->common.module_api_version >= GRALLOC_MODULE_API_VERSION_0_3) { - err = mAllocMod->lockAsync(mAllocMod, handle, usage, + err = mAllocMod->lockAsync(mAllocMod, handle, static_cast<int>(usage), bounds.left, bounds.top, bounds.width(), bounds.height(), vaddr, fenceFd); } else { sync_wait(fenceFd, -1); close(fenceFd); - err = mAllocMod->lock(mAllocMod, handle, usage, + err = mAllocMod->lock(mAllocMod, handle, static_cast<int>(usage), bounds.left, bounds.top, bounds.width(), bounds.height(), vaddr); } @@ -138,20 +143,20 @@ status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle, } status_t GraphicBufferMapper::lockAsyncYCbCr(buffer_handle_t handle, - int usage, const Rect& bounds, android_ycbcr *ycbcr, int fenceFd) + uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr, int fenceFd) { ATRACE_CALL(); status_t err; if (mAllocMod->common.module_api_version >= GRALLOC_MODULE_API_VERSION_0_3 && mAllocMod->lockAsync_ycbcr != NULL) { - err = mAllocMod->lockAsync_ycbcr(mAllocMod, handle, usage, - bounds.left, bounds.top, bounds.width(), bounds.height(), - ycbcr, fenceFd); + err = mAllocMod->lockAsync_ycbcr(mAllocMod, handle, + static_cast<int>(usage), bounds.left, bounds.top, + bounds.width(), bounds.height(), ycbcr, fenceFd); } else if (mAllocMod->lock_ycbcr != NULL) { sync_wait(fenceFd, -1); close(fenceFd); - err = mAllocMod->lock_ycbcr(mAllocMod, handle, usage, + err = mAllocMod->lock_ycbcr(mAllocMod, handle, static_cast<int>(usage), bounds.left, bounds.top, bounds.width(), bounds.height(), ycbcr); } else { diff --git a/libs/ui/PixelFormat.cpp b/libs/ui/PixelFormat.cpp index 5ce7fba..cab1dde 100644 --- a/libs/ui/PixelFormat.cpp +++ b/libs/ui/PixelFormat.cpp @@ -15,19 +15,16 @@ */ #include <ui/PixelFormat.h> -#include <hardware/hardware.h> // ---------------------------------------------------------------------------- namespace android { // ---------------------------------------------------------------------------- -ssize_t bytesPerPixel(PixelFormat format) { +uint32_t bytesPerPixel(PixelFormat format) { switch (format) { case PIXEL_FORMAT_RGBA_8888: case PIXEL_FORMAT_RGBX_8888: case PIXEL_FORMAT_BGRA_8888: - case PIXEL_FORMAT_sRGB_A_8888: - case PIXEL_FORMAT_sRGB_X_8888: return 4; case PIXEL_FORMAT_RGB_888: return 3; @@ -36,10 +33,10 @@ ssize_t bytesPerPixel(PixelFormat format) { case PIXEL_FORMAT_RGBA_4444: return 2; } - return BAD_VALUE; + return 0; } -ssize_t bitsPerPixel(PixelFormat format) { +uint32_t bitsPerPixel(PixelFormat format) { switch (format) { case PIXEL_FORMAT_RGBA_8888: case PIXEL_FORMAT_RGBX_8888: @@ -52,10 +49,9 @@ ssize_t bitsPerPixel(PixelFormat format) { case PIXEL_FORMAT_RGBA_4444: return 16; } - return BAD_VALUE; + return 0; } // ---------------------------------------------------------------------------- }; // namespace android // ---------------------------------------------------------------------------- - diff --git a/libs/ui/Rect.cpp b/libs/ui/Rect.cpp index b480f3a..dcce21f 100644 --- a/libs/ui/Rect.cpp +++ b/libs/ui/Rect.cpp @@ -19,6 +19,8 @@ namespace android { +const Rect Rect::INVALID_RECT{0, 0, -1, -1}; + static inline int32_t min(int32_t a, int32_t b) { return (a < b) ? a : b; } diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp index fa812f4..3810da4 100644 --- a/libs/ui/Region.cpp +++ b/libs/ui/Region.cpp @@ -53,6 +53,8 @@ enum { direction_RTL }; +const Region Region::INVALID_REGION(Rect::INVALID_RECT); + // ---------------------------------------------------------------------------- Region::Region() { @@ -102,8 +104,8 @@ static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, current--; } while (current->top == lastTop && current >= begin); - unsigned int beginLastSpan = -1; - unsigned int endLastSpan = -1; + int beginLastSpan = -1; + int endLastSpan = -1; int top = -1; int bottom = -1; @@ -118,7 +120,7 @@ static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, } else { beginLastSpan = endLastSpan + 1; } - endLastSpan = dst.size() - 1; + endLastSpan = static_cast<int>(dst.size()) - 1; top = current->top; bottom = current->bottom; @@ -126,43 +128,46 @@ static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, int left = current->left; int right = current->right; - for (unsigned int prevIndex = beginLastSpan; prevIndex <= endLastSpan; prevIndex++) { - const Rect* prev = &dst[prevIndex]; + for (int prevIndex = beginLastSpan; prevIndex <= endLastSpan; prevIndex++) { + // prevIndex can't be -1 here because if endLastSpan is set to a + // value greater than -1 (allowing the loop to execute), + // beginLastSpan (and therefore prevIndex) will also be increased + const Rect prev = dst[static_cast<size_t>(prevIndex)]; if (spanDirection == direction_RTL) { // iterating over previous span RTL, quit if it's too far left - if (prev->right <= left) break; + if (prev.right <= left) break; - if (prev->right > left && prev->right < right) { - dst.add(Rect(prev->right, top, right, bottom)); - right = prev->right; + if (prev.right > left && prev.right < right) { + dst.add(Rect(prev.right, top, right, bottom)); + right = prev.right; } - if (prev->left > left && prev->left < right) { - dst.add(Rect(prev->left, top, right, bottom)); - right = prev->left; + if (prev.left > left && prev.left < right) { + dst.add(Rect(prev.left, top, right, bottom)); + right = prev.left; } // if an entry in the previous span is too far right, nothing further left in the // current span will need it - if (prev->left >= right) { + if (prev.left >= right) { beginLastSpan = prevIndex; } } else { // iterating over previous span LTR, quit if it's too far right - if (prev->left >= right) break; + if (prev.left >= right) break; - if (prev->left > left && prev->left < right) { - dst.add(Rect(left, top, prev->left, bottom)); - left = prev->left; + if (prev.left > left && prev.left < right) { + dst.add(Rect(left, top, prev.left, bottom)); + left = prev.left; } - if (prev->right > left && prev->right < right) { - dst.add(Rect(left, top, prev->right, bottom)); - left = prev->right; + if (prev.right > left && prev.right < right) { + dst.add(Rect(left, top, prev.right, bottom)); + left = prev.right; } // if an entry in the previous span is too far left, nothing further right in the // current span will need it - if (prev->right <= left) { + if (prev.right <= left) { beginLastSpan = prevIndex; } } @@ -250,10 +255,16 @@ void Region::set(const Rect& r) mStorage.add(r); } +void Region::set(int32_t w, int32_t h) +{ + mStorage.clear(); + mStorage.add(Rect(w, h)); +} + void Region::set(uint32_t w, uint32_t h) { mStorage.clear(); - mStorage.add(Rect(w,h)); + mStorage.add(Rect(w, h)); } bool Region::isTriviallyEqual(const Region& region) const { @@ -404,7 +415,7 @@ const Region Region::operation(const Region& rhs, int dx, int dy, int op) const // This is our region rasterizer, which merges rects and spans together // to obtain an optimal region. -class Region::rasterizer : public region_operator<Rect>::region_rasterizer +class Region::rasterizer : public region_operator<Rect>::region_rasterizer { Rect bounds; Vector<Rect>& storage; @@ -413,80 +424,91 @@ class Region::rasterizer : public region_operator<Rect>::region_rasterizer Vector<Rect> span; Rect* cur; public: - rasterizer(Region& reg) + rasterizer(Region& reg) : bounds(INT_MAX, 0, INT_MIN, 0), storage(reg.mStorage), head(), tail(), cur() { storage.clear(); } - ~rasterizer() { - if (span.size()) { - flushSpan(); - } - if (storage.size()) { - bounds.top = storage.itemAt(0).top; - bounds.bottom = storage.top().bottom; - if (storage.size() == 1) { - storage.clear(); - } - } else { - bounds.left = 0; - bounds.right = 0; + virtual ~rasterizer(); + + virtual void operator()(const Rect& rect); + +private: + template<typename T> + static inline T min(T rhs, T lhs) { return rhs < lhs ? rhs : lhs; } + template<typename T> + static inline T max(T rhs, T lhs) { return rhs > lhs ? rhs : lhs; } + + void flushSpan(); +}; + +Region::rasterizer::~rasterizer() +{ + if (span.size()) { + flushSpan(); + } + if (storage.size()) { + bounds.top = storage.itemAt(0).top; + bounds.bottom = storage.top().bottom; + if (storage.size() == 1) { + storage.clear(); } - storage.add(bounds); + } else { + bounds.left = 0; + bounds.right = 0; } - - virtual void operator()(const Rect& rect) { - //ALOGD(">>> %3d, %3d, %3d, %3d", - // rect.left, rect.top, rect.right, rect.bottom); - if (span.size()) { - if (cur->top != rect.top) { - flushSpan(); - } else if (cur->right == rect.left) { - cur->right = rect.right; - return; - } + storage.add(bounds); +} + +void Region::rasterizer::operator()(const Rect& rect) +{ + //ALOGD(">>> %3d, %3d, %3d, %3d", + // rect.left, rect.top, rect.right, rect.bottom); + if (span.size()) { + if (cur->top != rect.top) { + flushSpan(); + } else if (cur->right == rect.left) { + cur->right = rect.right; + return; } - span.add(rect); - cur = span.editArray() + (span.size() - 1); } -private: - template<typename T> - static inline T min(T rhs, T lhs) { return rhs < lhs ? rhs : lhs; } - template<typename T> - static inline T max(T rhs, T lhs) { return rhs > lhs ? rhs : lhs; } - void flushSpan() { - bool merge = false; - if (tail-head == ssize_t(span.size())) { - Rect const* p = span.editArray(); - Rect const* q = head; - if (p->top == q->bottom) { - merge = true; - while (q != tail) { - if ((p->left != q->left) || (p->right != q->right)) { - merge = false; - break; - } - p++, q++; + span.add(rect); + cur = span.editArray() + (span.size() - 1); +} + +void Region::rasterizer::flushSpan() +{ + bool merge = false; + if (tail-head == ssize_t(span.size())) { + Rect const* p = span.editArray(); + Rect const* q = head; + if (p->top == q->bottom) { + merge = true; + while (q != tail) { + if ((p->left != q->left) || (p->right != q->right)) { + merge = false; + break; } + p++, q++; } } - if (merge) { - const int bottom = span[0].bottom; - Rect* r = head; - while (r != tail) { - r->bottom = bottom; - r++; - } - } else { - bounds.left = min(span.itemAt(0).left, bounds.left); - bounds.right = max(span.top().right, bounds.right); - storage.appendVector(span); - tail = storage.editArray() + storage.size(); - head = tail - span.size(); + } + if (merge) { + const int bottom = span[0].bottom; + Rect* r = head; + while (r != tail) { + r->bottom = bottom; + r++; } - span.clear(); + } else { + bounds.left = min(span.itemAt(0).left, bounds.left); + bounds.right = max(span.top().right, bounds.right); + storage.appendVector(span); + tail = storage.editArray() + storage.size(); + head = tail - span.size(); } -}; + span.clear(); +} bool Region::validate(const Region& reg, const char* name, bool silent) { @@ -497,8 +519,12 @@ bool Region::validate(const Region& reg, const char* name, bool silent) Rect b(*prev); while (cur != tail) { if (cur->isValid() == false) { - ALOGE_IF(!silent, "%s: region contains an invalid Rect", name); - result = false; + // We allow this particular flavor of invalid Rect, since it is used + // as a signal value in various parts of the system + if (*cur != Rect::INVALID_RECT) { + ALOGE_IF(!silent, "%s: region contains an invalid Rect", name); + result = false; + } } if (cur->right > region_operator<Rect>::max_value) { ALOGE_IF(!silent, "%s: rect->right > max_value", name); @@ -670,7 +696,9 @@ void Region::boolean_operation(int op, Region& dst, const Region& lhs, const Rect& rhs, int dx, int dy) { - if (!rhs.isValid()) { + // We allow this particular flavor of invalid Rect, since it is used as a + // signal value in various parts of the system + if (!rhs.isValid() && rhs != Rect::INVALID_RECT) { ALOGE("Region::boolean_operation(op=%d) invalid Rect={%d,%d,%d,%d}", op, rhs.left, rhs.top, rhs.right, rhs.bottom); return; @@ -733,35 +761,52 @@ void Region::translate(Region& dst, const Region& reg, int dx, int dy) // ---------------------------------------------------------------------------- size_t Region::getFlattenedSize() const { - return mStorage.size() * sizeof(Rect); + return sizeof(uint32_t) + mStorage.size() * sizeof(Rect); } status_t Region::flatten(void* buffer, size_t size) const { #if VALIDATE_REGIONS validate(*this, "Region::flatten"); #endif - if (size < mStorage.size() * sizeof(Rect)) { + if (size < getFlattenedSize()) { return NO_MEMORY; } - Rect* rects = reinterpret_cast<Rect*>(buffer); - memcpy(rects, mStorage.array(), mStorage.size() * sizeof(Rect)); + // Cast to uint32_t since the size of a size_t can vary between 32- and + // 64-bit processes + FlattenableUtils::write(buffer, size, static_cast<uint32_t>(mStorage.size())); + for (auto rect : mStorage) { + status_t result = rect.flatten(buffer, size); + if (result != NO_ERROR) { + return result; + } + FlattenableUtils::advance(buffer, size, sizeof(rect)); + } return NO_ERROR; } status_t Region::unflatten(void const* buffer, size_t size) { + if (size < sizeof(uint32_t)) { + return NO_MEMORY; + } + + uint32_t numRects = 0; + FlattenableUtils::read(buffer, size, numRects); + if (size < numRects * sizeof(Rect)) { + return NO_MEMORY; + } + Region result; - if (size >= sizeof(Rect)) { - Rect const* rects = reinterpret_cast<Rect const*>(buffer); - size_t count = size / sizeof(Rect); - if (count > 0) { - result.mStorage.clear(); - ssize_t err = result.mStorage.insertAt(0, count); - if (err < 0) { - return status_t(err); - } - memcpy(result.mStorage.editArray(), rects, count*sizeof(Rect)); + result.mStorage.clear(); + for (size_t r = 0; r < numRects; ++r) { + Rect rect; + status_t status = rect.unflatten(buffer, size); + if (status != NO_ERROR) { + return status; } + FlattenableUtils::advance(buffer, size, sizeof(rect)); + result.mStorage.push_back(rect); } + #if VALIDATE_REGIONS validate(result, "Region::unflatten"); #endif @@ -786,10 +831,8 @@ Region::const_iterator Region::end() const { } Rect const* Region::getArray(size_t* count) const { - const_iterator const b(begin()); - const_iterator const e(end()); - if (count) *count = e-b; - return b; + if (count) *count = static_cast<size_t>(end() - begin()); + return begin(); } SharedBuffer const* Region::getSharedBuffer(size_t* count) const { @@ -806,29 +849,22 @@ SharedBuffer const* Region::getSharedBuffer(size_t* count) const { // ---------------------------------------------------------------------------- -void Region::dump(String8& out, const char* what, uint32_t flags) const +void Region::dump(String8& out, const char* what, uint32_t /* flags */) const { - (void)flags; const_iterator head = begin(); const_iterator const tail = end(); - size_t SIZE = 256; - char buffer[SIZE]; - - snprintf(buffer, SIZE, " Region %s (this=%p, count=%" PRIdPTR ")\n", - what, this, tail-head); - out.append(buffer); + out.appendFormat(" Region %s (this=%p, count=%" PRIdPTR ")\n", + what, this, tail - head); while (head != tail) { - snprintf(buffer, SIZE, " [%3d, %3d, %3d, %3d]\n", - head->left, head->top, head->right, head->bottom); - out.append(buffer); - head++; + out.appendFormat(" [%3d, %3d, %3d, %3d]\n", head->left, head->top, + head->right, head->bottom); + ++head; } } -void Region::dump(const char* what, uint32_t flags) const +void Region::dump(const char* what, uint32_t /* flags */) const { - (void)flags; const_iterator head = begin(); const_iterator const tail = end(); ALOGD(" Region %s (this=%p, count=%" PRIdPTR ")\n", what, this, tail-head); diff --git a/libs/ui/UiConfig.cpp b/libs/ui/UiConfig.cpp index 8b2130e..9e7ba8e 100644 --- a/libs/ui/UiConfig.cpp +++ b/libs/ui/UiConfig.cpp @@ -18,8 +18,11 @@ namespace android { +#ifdef FRAMEBUFFER_FORCE_FORMAT +// We need the two-level macro to stringify the contents of a macro argument #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) +#endif void appendUiConfigString(String8& configStr) { diff --git a/libs/ui/tests/Android.mk b/libs/ui/tests/Android.mk index b0c57db..6438b1f 100644 --- a/libs/ui/tests/Android.mk +++ b/libs/ui/tests/Android.mk @@ -1,31 +1,36 @@ -# Build the unit tests. -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -# Build the unit tests. -test_src_files := \ - Region_test.cpp \ - vec_test.cpp \ - mat_test.cpp - -shared_libraries := \ - libutils \ - libui +# +# Copyright (C) 2014 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# -static_libraries := \ - libgtest \ - libgtest_main +LOCAL_PATH := $(call my-dir) -$(foreach file,$(test_src_files), \ - $(eval include $(CLEAR_VARS)) \ - $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \ - $(eval LOCAL_STATIC_LIBRARIES := $(static_libraries)) \ - $(eval LOCAL_SRC_FILES := $(file)) \ - $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \ - $(eval include $(BUILD_NATIVE_TEST)) \ -) +include $(CLEAR_VARS) +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk +LOCAL_SHARED_LIBRARIES := libui +LOCAL_SRC_FILES := Region_test.cpp +LOCAL_MODULE := Region_test +include $(BUILD_NATIVE_TEST) -# Build the unit tests. +include $(CLEAR_VARS) +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk +LOCAL_SRC_FILES := vec_test.cpp +LOCAL_MODULE := vec_test +include $(BUILD_NATIVE_TEST) -# Build the manual test programs. -include $(call all-makefiles-under, $(LOCAL_PATH)) +include $(CLEAR_VARS) +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk +LOCAL_SRC_FILES := mat_test.cpp +LOCAL_MODULE := mat_test +include $(BUILD_NATIVE_TEST) diff --git a/libs/ui/tests/vec_test.cpp b/libs/ui/tests/vec_test.cpp index 00f737e..454c999 100644 --- a/libs/ui/tests/vec_test.cpp +++ b/libs/ui/tests/vec_test.cpp @@ -16,17 +16,18 @@ #define LOG_TAG "RegionTest" +#include <math.h> #include <stdlib.h> + #include <ui/Region.h> #include <ui/Rect.h> -#include <gtest/gtest.h> - #include <ui/vec4.h> +#include <gtest/gtest.h> + namespace android { class VecTest : public testing::Test { -protected: }; TEST_F(VecTest, Basics) { |