Merge "Newly create idmap only when it is stale" into oc-dev
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 6cfbed9..d3e0cd4 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -31,6 +31,7 @@
#include <unistd.h>
#include <zlib.h>
+#include <fstream>
#include <memory>
#include <binder/IBinder.h>
@@ -436,56 +437,31 @@
return writeStr(k_traceBufferSizePath, str);
}
-// Read the trace_clock sysfs file and return true if it matches the requested
-// value. The trace_clock file format is:
-// local [global] counter uptime perf
-static bool isTraceClock(const char *mode)
-{
- int fd = open((g_traceFolder + k_traceClockPath).c_str(), O_RDONLY);
- if (fd == -1) {
- fprintf(stderr, "error opening %s: %s (%d)\n", k_traceClockPath,
- strerror(errno), errno);
- return false;
- }
-
- char buf[4097];
- ssize_t n = read(fd, buf, 4096);
- close(fd);
- if (n == -1) {
- fprintf(stderr, "error reading %s: %s (%d)\n", k_traceClockPath,
- strerror(errno), errno);
- return false;
- }
- buf[n] = '\0';
-
- char *start = strchr(buf, '[');
- if (start == NULL) {
- return false;
- }
- start++;
-
- char *end = strchr(start, ']');
- if (end == NULL) {
- return false;
- }
- *end = '\0';
-
- return strcmp(mode, start) == 0;
-}
-
-// Enable or disable the kernel's use of the global clock. Disabling the global
-// clock will result in the kernel using a per-CPU local clock.
+// Set the clock to the best available option while tracing. Use 'boot' if it's
+// available; otherwise, use 'mono'. If neither are available use 'global'.
// Any write to the trace_clock sysfs file will reset the buffer, so only
// update it if the requested value is not the current value.
-static bool setGlobalClockEnable(bool enable)
+static bool setClock()
{
- const char *clock = enable ? "global" : "local";
+ std::ifstream clockFile((g_traceFolder + k_traceClockPath).c_str(), O_RDONLY);
+ std::string clockStr((std::istreambuf_iterator<char>(clockFile)),
+ std::istreambuf_iterator<char>());
- if (isTraceClock(clock)) {
- return true;
+ std::string newClock;
+ if (clockStr.find("boot") != std::string::npos) {
+ newClock = "boot";
+ } else if (clockStr.find("mono") != std::string::npos) {
+ newClock = "mono";
+ } else {
+ newClock = "global";
}
- return writeStr(k_traceClockPath, clock);
+ size_t begin = clockStr.find("[") + 1;
+ size_t end = clockStr.find("]");
+ if (newClock.compare(0, std::string::npos, clockStr, begin, end-begin) == 0) {
+ return true;
+ }
+ return writeStr(k_traceClockPath, newClock.c_str());
}
static bool setPrintTgidEnableIfPresent(bool enable)
@@ -781,7 +757,7 @@
ok &= setCategoriesEnableFromFile(g_categoriesFile);
ok &= setTraceOverwriteEnable(g_traceOverwrite);
ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
- ok &= setGlobalClockEnable(true);
+ ok &= setClock();
ok &= setPrintTgidEnableIfPresent(true);
ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
@@ -855,7 +831,6 @@
// Set the options back to their defaults.
setTraceOverwriteEnable(true);
setTraceBufferSizeKB(1);
- setGlobalClockEnable(false);
setPrintTgidEnableIfPresent(false);
setKernelTraceFuncs(NULL);
}
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 3bbe3a1..b20a807 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1703,10 +1703,20 @@
result = false;
continue;
}
+
+ // Delete oat/vdex/art files.
result = unlink_if_exists(oat_path) && result;
result = unlink_if_exists(create_vdex_filename(oat_path)) && result;
result = unlink_if_exists(create_image_filename(oat_path)) && result;
+ // Delete profiles.
+ std::string current_profile = create_current_profile_path(
+ multiuser_get_user_id(uid), dex_path, /*is_secondary*/true);
+ std::string reference_profile = create_reference_profile_path(
+ dex_path, /*is_secondary*/true);
+ result = unlink_if_exists(current_profile) && result;
+ result = unlink_if_exists(reference_profile) && result;
+
// Try removing the directories as well, they might be empty.
result = rmdir_if_empty(oat_isa_dir) && result;
result = rmdir_if_empty(oat_dir) && result;
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 43d0780..68cb0d7 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -64,6 +64,25 @@
namespace android {
namespace installd {
+// Check expected values for dexopt flags. If you need to change this:
+//
+// RUN AN A/B OTA TO MAKE SURE THINGS STILL WORK!
+//
+// You most likely need to increase the protocol version and all that entails!
+
+static_assert(DEXOPT_PUBLIC == 1 << 1, "DEXOPT_PUBLIC unexpected.");
+static_assert(DEXOPT_DEBUGGABLE == 1 << 2, "DEXOPT_DEBUGGABLE unexpected.");
+static_assert(DEXOPT_BOOTCOMPLETE == 1 << 3, "DEXOPT_BOOTCOMPLETE unexpected.");
+static_assert(DEXOPT_PROFILE_GUIDED == 1 << 4, "DEXOPT_PROFILE_GUIDED unexpected.");
+static_assert(DEXOPT_SECONDARY_DEX == 1 << 5, "DEXOPT_SECONDARY_DEX unexpected.");
+static_assert(DEXOPT_FORCE == 1 << 6, "DEXOPT_FORCE unexpected.");
+static_assert(DEXOPT_STORAGE_CE == 1 << 7, "DEXOPT_STORAGE_CE unexpected.");
+static_assert(DEXOPT_STORAGE_DE == 1 << 8, "DEXOPT_STORAGE_DE unexpected.");
+
+static_assert(DEXOPT_MASK == 0x1fe, "DEXOPT_MASK unexpected.");
+
+
+
template<typename T>
static constexpr T RoundDown(T x, typename std::decay<T>::type n) {
return DCHECK_CONSTEXPR(IsPowerOfTwo(n), , T(0))(x & -n);
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 6fefb38..aec8f10 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2547,16 +2547,8 @@
objectsSize = 0;
} else {
while (objectsSize > 0) {
- if (mObjects[objectsSize-1] < desired) {
- // Check for an object being sliced
- if (desired < mObjects[objectsSize-1] + sizeof(flat_binder_object)) {
- ALOGE("Attempt to shrink Parcel would slice an objects allocated memory");
- return UNKNOWN_ERROR + 0xBADF10;
- }
+ if (mObjects[objectsSize-1] < desired)
break;
- }
- // STOPSHIP: Above code to be replaced with following commented code:
- // if (mObjects[objectsSize-1] + sizeof(flat_binder_object) <= desired) break;
objectsSize--;
}
}
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 8159aef..3d57769 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -511,7 +511,7 @@
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
- if (graphicBuffer != NULL && !mCore->mIsAbandoned) {
+ if (error == NO_ERROR && !mCore->mIsAbandoned) {
graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
}
@@ -519,7 +519,7 @@
mCore->mIsAllocating = false;
mCore->mIsAllocatingCondition.broadcast();
- if (graphicBuffer == NULL) {
+ if (error != NO_ERROR) {
mCore->mFreeSlots.insert(*outSlot);
mCore->clearBufferSlotLocked(*outSlot);
BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
@@ -732,6 +732,7 @@
mSlots[*outSlot].mFence = Fence::NO_FENCE;
mSlots[*outSlot].mRequestBufferCalled = true;
mSlots[*outSlot].mAcquireCalled = false;
+ mSlots[*outSlot].mNeedsReallocation = false;
mCore->mActiveBuffers.insert(found);
VALIDATE_CONSISTENCY();
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index ecf27f4..6583a62 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -476,6 +476,9 @@
{
Mutex::Autolock lock(mMutex);
+ if (mReportRemovedBuffers) {
+ mRemovedBuffers.clear();
+ }
reqWidth = mReqWidth ? mReqWidth : mUserWidth;
reqHeight = mReqHeight ? mReqHeight : mUserHeight;
@@ -536,7 +539,6 @@
if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == nullptr) {
if (mReportRemovedBuffers && (gbuf != nullptr)) {
- mRemovedBuffers.clear();
mRemovedBuffers.push_back(gbuf);
}
result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
@@ -1208,6 +1210,9 @@
}
Mutex::Autolock lock(mMutex);
+ if (mReportRemovedBuffers) {
+ mRemovedBuffers.clear();
+ }
sp<GraphicBuffer> buffer(NULL);
sp<Fence> fence(NULL);
@@ -1224,13 +1229,9 @@
*outFence = Fence::NO_FENCE;
}
- if (mReportRemovedBuffers) {
- mRemovedBuffers.clear();
- }
-
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
if (mSlots[i].buffer != NULL &&
- mSlots[i].buffer->handle == buffer->handle) {
+ mSlots[i].buffer->getId() == buffer->getId()) {
if (mReportRemovedBuffers) {
mRemovedBuffers.push_back(mSlots[i].buffer);
}
@@ -1247,6 +1248,9 @@
ALOGV("Surface::attachBuffer");
Mutex::Autolock lock(mMutex);
+ if (mReportRemovedBuffers) {
+ mRemovedBuffers.clear();
+ }
sp<GraphicBuffer> graphicBuffer(static_cast<GraphicBuffer*>(buffer));
uint32_t priorGeneration = graphicBuffer->mGenerationNumber;
@@ -1260,7 +1264,6 @@
return result;
}
if (mReportRemovedBuffers && (mSlots[attachedSlot].buffer != nullptr)) {
- mRemovedBuffers.clear();
mRemovedBuffers.push_back(mSlots[attachedSlot].buffer);
}
mSlots[attachedSlot].buffer = graphicBuffer;
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 192bfc8..7efdb14 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -14,6 +14,7 @@
"FillBuffer.cpp",
"GLTest.cpp",
"IGraphicBufferProducer_test.cpp",
+ "Malicious.cpp",
"MultiTextureConsumer_test.cpp",
"StreamSplitter_test.cpp",
"SurfaceTextureClient_test.cpp",
diff --git a/libs/gui/tests/Malicious.cpp b/libs/gui/tests/Malicious.cpp
new file mode 100644
index 0000000..7ecf08c
--- /dev/null
+++ b/libs/gui/tests/Malicious.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2017 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 <gui/BufferQueue.h>
+#include <gui/IProducerListener.h>
+#include <gui/Surface.h>
+
+#include <android/native_window.h>
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace test {
+
+class ProxyBQP : public BnGraphicBufferProducer {
+public:
+ ProxyBQP(const sp<IGraphicBufferProducer>& producer) : mProducer(producer) {}
+
+ // Pass through calls to mProducer
+ status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override {
+ return mProducer->requestBuffer(slot, buf);
+ }
+ status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) override {
+ return mProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers);
+ }
+ status_t setAsyncMode(bool async) override { return mProducer->setAsyncMode(async); }
+ status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h, PixelFormat format,
+ uint32_t usage, FrameEventHistoryDelta* outTimestamps) override {
+ return mProducer->dequeueBuffer(slot, fence, w, h, format, usage, outTimestamps);
+ }
+ status_t detachBuffer(int slot) override { return mProducer->detachBuffer(slot); }
+ status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) override {
+ return mProducer->detachNextBuffer(outBuffer, outFence);
+ }
+ status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer) override {
+ return mProducer->attachBuffer(outSlot, buffer);
+ }
+ status_t queueBuffer(int slot, const QueueBufferInput& input,
+ QueueBufferOutput* output) override {
+ return mProducer->queueBuffer(slot, input, output);
+ }
+ status_t cancelBuffer(int slot, const sp<Fence>& fence) override {
+ return mProducer->cancelBuffer(slot, fence);
+ }
+ int query(int what, int* value) override { return mProducer->query(what, value); }
+ status_t connect(const sp<IProducerListener>& listener, int api, bool producerControlledByApp,
+ QueueBufferOutput* output) override {
+ return mProducer->connect(listener, api, producerControlledByApp, output);
+ }
+ status_t disconnect(int api, DisconnectMode mode) override {
+ return mProducer->disconnect(api, mode);
+ }
+ status_t setSidebandStream(const sp<NativeHandle>& stream) override {
+ return mProducer->setSidebandStream(stream);
+ }
+ void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format,
+ uint32_t usage) override {
+ mProducer->allocateBuffers(width, height, format, usage);
+ }
+ status_t allowAllocation(bool allow) override { return mProducer->allowAllocation(allow); }
+ status_t setGenerationNumber(uint32_t generationNumber) override {
+ return mProducer->setGenerationNumber(generationNumber);
+ }
+ String8 getConsumerName() const override { return mProducer->getConsumerName(); }
+ status_t setSharedBufferMode(bool sharedBufferMode) override {
+ return mProducer->setSharedBufferMode(sharedBufferMode);
+ }
+ status_t setAutoRefresh(bool autoRefresh) override {
+ return mProducer->setAutoRefresh(autoRefresh);
+ }
+ status_t setDequeueTimeout(nsecs_t timeout) override {
+ return mProducer->setDequeueTimeout(timeout);
+ }
+ status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence,
+ float outTransformMatrix[16]) override {
+ return mProducer->getLastQueuedBuffer(outBuffer, outFence, outTransformMatrix);
+ }
+ void getFrameTimestamps(FrameEventHistoryDelta*) override {}
+ status_t getUniqueId(uint64_t* outId) const override { return mProducer->getUniqueId(outId); }
+
+protected:
+ sp<IGraphicBufferProducer> mProducer;
+};
+
+class MaliciousBQP : public ProxyBQP {
+public:
+ MaliciousBQP(const sp<IGraphicBufferProducer>& producer) : ProxyBQP(producer) {}
+
+ void beMalicious(int32_t value) { mMaliciousValue = value; }
+
+ void setExpectedSlot(int32_t slot) { mExpectedSlot = slot; }
+
+ // Override dequeueBuffer, optionally corrupting the returned slot number
+ status_t dequeueBuffer(int* buf, sp<Fence>* fence, uint32_t width, uint32_t height,
+ PixelFormat format, uint32_t usage,
+ FrameEventHistoryDelta* outTimestamps) override {
+ EXPECT_EQ(BUFFER_NEEDS_REALLOCATION,
+ mProducer->dequeueBuffer(buf, fence, width, height, format, usage,
+ outTimestamps));
+ EXPECT_EQ(mExpectedSlot, *buf);
+ if (mMaliciousValue != 0) {
+ *buf = mMaliciousValue;
+ return NO_ERROR;
+ } else {
+ return BUFFER_NEEDS_REALLOCATION;
+ }
+ }
+
+private:
+ int32_t mMaliciousValue = 0;
+ int32_t mExpectedSlot = 0;
+};
+
+class DummyListener : public BnConsumerListener {
+public:
+ void onFrameAvailable(const BufferItem&) override {}
+ void onBuffersReleased() override {}
+ void onSidebandStreamChanged() override {}
+};
+
+sp<MaliciousBQP> getMaliciousBQP() {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ sp<IConsumerListener> listener = new DummyListener;
+ consumer->consumerConnect(listener, false);
+
+ sp<MaliciousBQP> malicious = new MaliciousBQP(producer);
+ return malicious;
+}
+
+TEST(Malicious, Bug36991414Max) {
+ sp<MaliciousBQP> malicious = getMaliciousBQP();
+ sp<Surface> surface = new Surface(malicious);
+
+ ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
+ ANativeWindow_Buffer buffer;
+ ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
+ ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
+
+ malicious->setExpectedSlot(1);
+ malicious->beMalicious(std::numeric_limits<int32_t>::max());
+ ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
+}
+
+TEST(Malicious, Bug36991414Min) {
+ sp<MaliciousBQP> malicious = getMaliciousBQP();
+ sp<Surface> surface = new Surface(malicious);
+
+ ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
+ ANativeWindow_Buffer buffer;
+ ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
+ ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
+
+ malicious->setExpectedSlot(1);
+ malicious->beMalicious(std::numeric_limits<int32_t>::min());
+ ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
+}
+
+TEST(Malicious, Bug36991414NegativeOne) {
+ sp<MaliciousBQP> malicious = getMaliciousBQP();
+ sp<Surface> surface = new Surface(malicious);
+
+ ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
+ ANativeWindow_Buffer buffer;
+ ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
+ ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
+
+ malicious->setExpectedSlot(1);
+ malicious->beMalicious(-1);
+ ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
+}
+
+TEST(Malicious, Bug36991414NumSlots) {
+ sp<MaliciousBQP> malicious = getMaliciousBQP();
+ sp<Surface> surface = new Surface(malicious);
+
+ ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
+ ANativeWindow_Buffer buffer;
+ ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
+ ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
+
+ malicious->setExpectedSlot(1);
+ malicious->beMalicious(BufferQueueDefs::NUM_BUFFER_SLOTS);
+ ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
+}
+
+} // namespace test
+} // namespace android
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 08d6715..fcaa23a 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -24,6 +24,7 @@
#include <cutils/properties.h>
#include <gui/BufferItemConsumer.h>
#include <gui/IDisplayEventConnection.h>
+#include <gui/IProducerListener.h>
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
@@ -320,6 +321,77 @@
ASSERT_EQ(NO_ERROR, window->queueBuffer(window.get(), buffer, fence));
}
+TEST_F(SurfaceTest, GetAndFlushRemovedBuffers) {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+
+ sp<DummyConsumer> dummyConsumer(new DummyConsumer);
+ consumer->consumerConnect(dummyConsumer, false);
+ consumer->setConsumerName(String8("TestConsumer"));
+
+ sp<Surface> surface = new Surface(producer);
+ sp<ANativeWindow> window(surface);
+ sp<DummyProducerListener> listener = new DummyProducerListener();
+ ASSERT_EQ(OK, surface->connect(
+ NATIVE_WINDOW_API_CPU,
+ /*listener*/listener,
+ /*reportBufferRemoval*/true));
+ const int BUFFER_COUNT = 4;
+ ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(window.get(), BUFFER_COUNT));
+
+ sp<GraphicBuffer> detachedBuffer;
+ sp<Fence> outFence;
+ int fences[BUFFER_COUNT];
+ ANativeWindowBuffer* buffers[BUFFER_COUNT];
+ // Allocate buffers because detachNextBuffer requires allocated buffers
+ for (int i = 0; i < BUFFER_COUNT; i++) {
+ ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffers[i], &fences[i]));
+ }
+ for (int i = 0; i < BUFFER_COUNT; i++) {
+ ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffers[i], fences[i]));
+ }
+
+ // Test detached buffer is correctly reported
+ ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&detachedBuffer, &outFence));
+ std::vector<sp<GraphicBuffer>> removedBuffers;
+ ASSERT_EQ(OK, surface->getAndFlushRemovedBuffers(&removedBuffers));
+ ASSERT_EQ(1u, removedBuffers.size());
+ ASSERT_EQ(detachedBuffer->handle, removedBuffers.at(0)->handle);
+ // Test the list is flushed one getAndFlushRemovedBuffers returns
+ ASSERT_EQ(OK, surface->getAndFlushRemovedBuffers(&removedBuffers));
+ ASSERT_EQ(0u, removedBuffers.size());
+
+
+ // Test removed buffer list is cleanup after next dequeueBuffer call
+ ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&detachedBuffer, &outFence));
+ ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffers[0], &fences[0]));
+ ASSERT_EQ(OK, surface->getAndFlushRemovedBuffers(&removedBuffers));
+ ASSERT_EQ(0u, removedBuffers.size());
+ ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffers[0], fences[0]));
+
+ // Test removed buffer list is cleanup after next detachNextBuffer call
+ ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&detachedBuffer, &outFence));
+ ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&detachedBuffer, &outFence));
+ ASSERT_EQ(OK, surface->getAndFlushRemovedBuffers(&removedBuffers));
+ ASSERT_EQ(1u, removedBuffers.size());
+ ASSERT_EQ(detachedBuffer->handle, removedBuffers.at(0)->handle);
+
+ // Re-allocate buffers since all buffers are detached up to now
+ for (int i = 0; i < BUFFER_COUNT; i++) {
+ ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffers[i], &fences[i]));
+ }
+ for (int i = 0; i < BUFFER_COUNT; i++) {
+ ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffers[i], fences[i]));
+ }
+
+ ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&detachedBuffer, &outFence));
+ ASSERT_EQ(NO_ERROR, surface->attachBuffer(detachedBuffer.get()));
+ ASSERT_EQ(OK, surface->getAndFlushRemovedBuffers(&removedBuffers));
+ // Depends on which slot GraphicBufferProducer impl pick, the attach call might
+ // get 0 or 1 buffer removed.
+ ASSERT_LE(removedBuffers.size(), 1u);
+}
class FakeConsumer : public BnConsumerListener {
public:
diff --git a/libs/hwc2on1adapter/Android.bp b/libs/hwc2on1adapter/Android.bp
index 5d7f660..ec9cbf8 100644
--- a/libs/hwc2on1adapter/Android.bp
+++ b/libs/hwc2on1adapter/Android.bp
@@ -14,7 +14,7 @@
cc_library_shared {
name: "libhwc2on1adapter",
- vendor_available: true,
+ vendor: true,
clang: true,
cppflags: [
diff --git a/libs/hwc2on1adapter/CleanSpec.mk b/libs/hwc2on1adapter/CleanSpec.mk
new file mode 100644
index 0000000..7fc2216
--- /dev/null
+++ b/libs/hwc2on1adapter/CleanSpec.mk
@@ -0,0 +1,52 @@
+# Copyright (C) 2017 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list. These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list. E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libhwc2on1adapter_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libhwc2on1adapter.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/libhwc2on1adapter.so)
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 5ccf178..406968d 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -72,6 +72,7 @@
"libhardware",
"libhidlbase",
"libhidltransport",
+ "libhwbinder",
"libsync",
"libutils",
"liblog",
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
index f8d9401..87dbaf4 100644
--- a/libs/ui/Gralloc2.cpp
+++ b/libs/ui/Gralloc2.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "Gralloc2"
+#include <hwbinder/IPCThreadState.h>
#include <ui/Gralloc2.h>
#include <log/log.h>
@@ -241,6 +242,9 @@
*outStride = tmpStride;
});
+ // make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
+ hardware::IPCThreadState::self()->flushCommands();
+
return (ret.isOk()) ? error : kTransactionError;
}
diff --git a/services/displayservice/Android.bp b/services/displayservice/Android.bp
new file mode 100644
index 0000000..3442cb2
--- /dev/null
+++ b/services/displayservice/Android.bp
@@ -0,0 +1,46 @@
+//
+// Copyright (C) 2017 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.
+//
+
+cc_library_shared {
+ name: "libdisplayservicehidl",
+
+ srcs: [
+ "DisplayService.cpp",
+ "DisplayEventReceiver.cpp",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libgui",
+ "libhidlbase",
+ "libhidltransport",
+ "libutils",
+ "android.frameworks.displayservice@1.0",
+ ],
+
+ export_include_dirs: ["include"],
+ export_shared_lib_headers: [
+ "android.frameworks.displayservice@1.0",
+ "libgui",
+ "libutils",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ]
+}
diff --git a/services/displayservice/DisplayEventReceiver.cpp b/services/displayservice/DisplayEventReceiver.cpp
new file mode 100644
index 0000000..5993e44
--- /dev/null
+++ b/services/displayservice/DisplayEventReceiver.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#define LOG_TAG "libdisplayservicehidl"
+
+#include <displayservice/DisplayEventReceiver.h>
+
+#include <android-base/logging.h>
+#include <android/frameworks/displayservice/1.0/BpHwEventCallback.h>
+
+#include <thread>
+
+namespace android {
+namespace frameworks {
+namespace displayservice {
+namespace V1_0 {
+namespace implementation {
+
+sp<Looper> getLooper() {
+ static sp<Looper> looper = []() {
+ sp<Looper> looper = new Looper(false /* allowNonCallbacks */);
+
+ std::thread{[&](){
+ int pollResult = looper->pollAll(-1 /* timeout */);
+ LOG(ERROR) << "Looper::pollAll returns unexpected " << pollResult;
+ }}.detach();
+
+ return looper;
+ }();
+
+ return looper;
+}
+
+DisplayEventReceiver::AttachedEvent::AttachedEvent(const sp<IEventCallback> &callback)
+ : mCallback(callback)
+{
+ mLooperAttached = getLooper()->addFd(mFwkReceiver.getFd(),
+ Looper::POLL_CALLBACK,
+ Looper::EVENT_INPUT,
+ this,
+ nullptr);
+}
+
+DisplayEventReceiver::AttachedEvent::~AttachedEvent() {
+ if (!detach()) {
+ LOG(ERROR) << "Could not remove fd from looper.";
+ }
+}
+
+bool DisplayEventReceiver::AttachedEvent::detach() {
+ if (!valid()) {
+ return true;
+ }
+
+ return getLooper()->removeFd(mFwkReceiver.getFd());
+}
+
+bool DisplayEventReceiver::AttachedEvent::valid() const {
+ return mFwkReceiver.initCheck() == OK && mLooperAttached;
+}
+
+DisplayEventReceiver::FwkReceiver &DisplayEventReceiver::AttachedEvent::receiver() {
+ return mFwkReceiver;
+}
+
+int DisplayEventReceiver::AttachedEvent::handleEvent(int fd, int events, void* /* data */) {
+ CHECK(fd == mFwkReceiver.getFd());
+
+ if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
+ LOG(ERROR) << "AttachedEvent handleEvent received error or hangup:" << events;
+ return 0; // remove the callback
+ }
+
+ if (!(events & Looper::EVENT_INPUT)) {
+ LOG(ERROR) << "AttachedEvent handleEvent unhandled poll event:" << events;
+ return 1; // keep the callback
+ }
+
+ constexpr size_t SIZE = 1;
+
+ ssize_t n;
+ FwkReceiver::Event buf[SIZE];
+ while ((n = mFwkReceiver.getEvents(buf, SIZE)) > 0) {
+ for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
+ const FwkReceiver::Event &event = buf[i];
+
+ uint32_t type = event.header.type;
+ uint64_t timestamp = event.header.timestamp;
+
+ switch(buf[i].header.type) {
+ case FwkReceiver::DISPLAY_EVENT_VSYNC: {
+ mCallback->onVsync(timestamp, event.vsync.count);
+ } break;
+ case FwkReceiver::DISPLAY_EVENT_HOTPLUG: {
+ mCallback->onHotplug(timestamp, event.hotplug.connected);
+ } break;
+ default: {
+ LOG(ERROR) << "AttachedEvent handleEvent unknown type: " << type;
+ }
+ }
+ }
+ }
+
+ return 1; // keep on going
+}
+
+Return<Status> DisplayEventReceiver::init(const sp<IEventCallback>& callback) {
+ std::unique_lock<std::mutex> lock(mMutex);
+
+ if (mAttached != nullptr || callback == nullptr) {
+ return Status::BAD_VALUE;
+ }
+
+ mAttached = new AttachedEvent(callback);
+
+ return mAttached->valid() ? Status::SUCCESS : Status::UNKNOWN;
+}
+
+Return<Status> DisplayEventReceiver::setVsyncRate(int32_t count) {
+ std::unique_lock<std::mutex> lock(mMutex);
+
+ if (mAttached == nullptr || count < 0) {
+ return Status::BAD_VALUE;
+ }
+
+ bool success = OK == mAttached->receiver().setVsyncRate(count);
+ return success ? Status::SUCCESS : Status::UNKNOWN;
+}
+
+Return<Status> DisplayEventReceiver::requestNextVsync() {
+ std::unique_lock<std::mutex> lock(mMutex);
+
+ if (mAttached == nullptr) {
+ return Status::BAD_VALUE;
+ }
+
+ bool success = OK == mAttached->receiver().requestNextVsync();
+ return success ? Status::SUCCESS : Status::UNKNOWN;
+}
+
+Return<Status> DisplayEventReceiver::close() {
+ std::unique_lock<std::mutex> lock(mMutex);
+ if (mAttached == nullptr) {
+ return Status::BAD_VALUE;
+ }
+
+ bool success = mAttached->detach();
+ mAttached = nullptr;
+
+ return success ? Status::SUCCESS : Status::UNKNOWN;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace displayservice
+} // namespace frameworks
+} // namespace android
diff --git a/services/displayservice/DisplayService.cpp b/services/displayservice/DisplayService.cpp
new file mode 100644
index 0000000..18418fd
--- /dev/null
+++ b/services/displayservice/DisplayService.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 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 <displayservice/DisplayService.h>
+#include <displayservice/DisplayEventReceiver.h>
+
+namespace android {
+namespace frameworks {
+namespace displayservice {
+namespace V1_0 {
+namespace implementation {
+
+Return<sp<IDisplayEventReceiver>> DisplayService::getEventReceiver() {
+ return new DisplayEventReceiver();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace displayservice
+} // namespace frameworks
+} // namespace android
diff --git a/services/displayservice/include/displayservice/DisplayEventReceiver.h b/services/displayservice/include/displayservice/DisplayEventReceiver.h
new file mode 100644
index 0000000..5d569b6
--- /dev/null
+++ b/services/displayservice/include/displayservice/DisplayEventReceiver.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYEVENTRECEIVER_H
+#define ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYEVENTRECEIVER_H
+
+#include <android/frameworks/displayservice/1.0/IDisplayEventReceiver.h>
+#include <gui/DisplayEventReceiver.h>
+#include <hidl/Status.h>
+#include <gui/DisplayEventReceiver.h>
+#include <utils/Looper.h>
+
+#include <mutex>
+
+namespace android {
+namespace frameworks {
+namespace displayservice {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+class DisplayEventReceiver : public IDisplayEventReceiver {
+public:
+ Return<Status> init(const sp<IEventCallback>& callback) override;
+ Return<Status> setVsyncRate(int32_t count) override;
+ Return<Status> requestNextVsync() override;
+ Return<Status> close() override;
+
+private:
+ using FwkReceiver = ::android::DisplayEventReceiver;
+
+ struct AttachedEvent : LooperCallback {
+ AttachedEvent(const sp<IEventCallback> &callback);
+ ~AttachedEvent();
+
+ bool detach();
+ bool valid() const;
+ FwkReceiver &receiver();
+ virtual int handleEvent(int fd, int events, void* /* data */) override;
+
+ private:
+ FwkReceiver mFwkReceiver;
+ sp<IEventCallback> mCallback;
+ bool mLooperAttached;
+ };
+
+ sp<AttachedEvent> mAttached;
+ std::mutex mMutex;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace displayservice
+} // namespace frameworks
+} // namespace android
+
+#endif // ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYEVENTRECEIVER_H
diff --git a/services/displayservice/include/displayservice/DisplayService.h b/services/displayservice/include/displayservice/DisplayService.h
new file mode 100644
index 0000000..9722e71
--- /dev/null
+++ b/services/displayservice/include/displayservice/DisplayService.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYSERVICE_H
+#define ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYSERVICE_H
+
+#include <android/frameworks/displayservice/1.0/IDisplayService.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace frameworks {
+namespace displayservice {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+struct DisplayService : public IDisplayService {
+ Return<sp<IDisplayEventReceiver>> getEventReceiver() override;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace displayservice
+} // namespace frameworks
+} // namespace android
+
+#endif // ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYSERVICE_H
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 7bb20ba..95a522d 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -54,11 +54,7 @@
LOCAL_SRC_FILES += \
SurfaceFlinger.cpp \
DisplayHardware/HWComposer.cpp
- ifeq ($(TARGET_USES_HWC2ON1ADAPTER), true)
- LOCAL_CFLAGS += -DBYPASS_IHWC
- endif
else
- LOCAL_CFLAGS += -DBYPASS_IHWC
LOCAL_SRC_FILES += \
SurfaceFlinger_hwc1.cpp \
DisplayHardware/HWComposer_hwc1.cpp
@@ -84,7 +80,6 @@
libdl \
libfmq \
libhardware \
- libhwc2on1adapter \
libhidlbase \
libhidltransport \
libhwbinder \
@@ -133,11 +128,13 @@
main_surfaceflinger.cpp
LOCAL_SHARED_LIBRARIES := \
+ android.frameworks.displayservice@1.0 \
android.hardware.configstore@1.0 \
android.hardware.configstore-utils \
android.hardware.graphics.allocator@2.0 \
libsurfaceflinger \
libcutils \
+ libdisplayservicehidl \
liblog \
libbinder \
libhidlbase \
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 8270c39..0366630 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -88,55 +88,8 @@
// Device methods
-#ifdef BYPASS_IHWC
-Device::Device(hwc2_device_t* device)
- : mHwcDevice(device),
- mCreateVirtualDisplay(nullptr),
- mDestroyVirtualDisplay(nullptr),
- mDump(nullptr),
- mGetMaxVirtualDisplayCount(nullptr),
- mRegisterCallback(nullptr),
- mAcceptDisplayChanges(nullptr),
- mCreateLayer(nullptr),
- mDestroyLayer(nullptr),
- mGetActiveConfig(nullptr),
- mGetChangedCompositionTypes(nullptr),
- mGetColorModes(nullptr),
- mGetDisplayAttribute(nullptr),
- mGetDisplayConfigs(nullptr),
- mGetDisplayName(nullptr),
- mGetDisplayRequests(nullptr),
- mGetDisplayType(nullptr),
- mGetDozeSupport(nullptr),
- mGetHdrCapabilities(nullptr),
- mGetReleaseFences(nullptr),
- mPresentDisplay(nullptr),
- mSetActiveConfig(nullptr),
- mSetClientTarget(nullptr),
- mSetColorMode(nullptr),
- mSetColorTransform(nullptr),
- mSetOutputBuffer(nullptr),
- mSetPowerMode(nullptr),
- mSetVsyncEnabled(nullptr),
- mValidateDisplay(nullptr),
- mSetCursorPosition(nullptr),
- mSetLayerBuffer(nullptr),
- mSetLayerSurfaceDamage(nullptr),
- mSetLayerBlendMode(nullptr),
- mSetLayerColor(nullptr),
- mSetLayerCompositionType(nullptr),
- mSetLayerDataspace(nullptr),
- mSetLayerDisplayFrame(nullptr),
- mSetLayerPlaneAlpha(nullptr),
- mSetLayerSidebandStream(nullptr),
- mSetLayerSourceCrop(nullptr),
- mSetLayerTransform(nullptr),
- mSetLayerVisibleRegion(nullptr),
- mSetLayerZOrder(nullptr),
-#else
Device::Device(bool useVrComposer)
: mComposer(std::make_unique<Hwc2::Composer>(useVrComposer)),
-#endif // BYPASS_IHWC
mCapabilities(),
mDisplays(),
mHotplug(),
@@ -147,18 +100,11 @@
mPendingVsyncs()
{
loadCapabilities();
- loadFunctionPointers();
registerCallbacks();
}
Device::~Device()
{
-#ifdef BYPASS_IHWC
- if (mHwcDevice == nullptr) {
- return;
- }
-#endif
-
for (auto element : mDisplays) {
auto display = element.second.lock();
if (!display) {
@@ -185,36 +131,18 @@
}
}
}
-
-#ifdef BYPASS_IHWC
- hwc2_close(mHwcDevice);
-#endif
}
// Required by HWC2 device
std::string Device::dump() const
{
-#ifdef BYPASS_IHWC
- uint32_t numBytes = 0;
- mDump(mHwcDevice, &numBytes, nullptr);
-
- std::vector<char> buffer(numBytes);
- mDump(mHwcDevice, &numBytes, buffer.data());
-
- return std::string(buffer.data(), buffer.size());
-#else
return mComposer->dumpDebugInfo();
-#endif
}
uint32_t Device::getMaxVirtualDisplayCount() const
{
-#ifdef BYPASS_IHWC
- return mGetMaxVirtualDisplayCount(mHwcDevice);
-#else
return mComposer->getMaxVirtualDisplayCount();
-#endif
}
Error Device::createVirtualDisplay(uint32_t width, uint32_t height,
@@ -223,15 +151,9 @@
ALOGI("Creating virtual display");
hwc2_display_t displayId = 0;
-#ifdef BYPASS_IHWC
- int32_t intFormat = static_cast<int32_t>(*format);
- int32_t intError = mCreateVirtualDisplay(mHwcDevice, width, height,
- &intFormat, &displayId);
-#else
auto intFormat = static_cast<Hwc2::PixelFormat>(*format);
auto intError = mComposer->createVirtualDisplay(width, height,
&intFormat, &displayId);
-#endif
auto error = static_cast<Error>(intError);
if (error != Error::None) {
return error;
@@ -285,9 +207,7 @@
{
if (connected == Connection::Connected) {
if (!display->isConnected()) {
-#ifndef BYPASS_IHWC
mComposer->setClientTargetSlotCount(display->getId());
-#endif
display->loadConfigs();
display->setConnected(true);
}
@@ -345,21 +265,10 @@
{
static_assert(sizeof(Capability) == sizeof(int32_t),
"Capability size has changed");
-#ifdef BYPASS_IHWC
- uint32_t numCapabilities = 0;
- mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, nullptr);
- std::vector<Capability> capabilities(numCapabilities);
- auto asInt = reinterpret_cast<int32_t*>(capabilities.data());
- mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, asInt);
- for (auto capability : capabilities) {
- mCapabilities.emplace(capability);
- }
-#else
auto capabilities = mComposer->getCapabilities();
for (auto capability : capabilities) {
mCapabilities.emplace(static_cast<Capability>(capability));
}
-#endif
}
bool Device::hasCapability(HWC2::Capability capability) const
@@ -368,105 +277,6 @@
capability) != mCapabilities.cend();
}
-void Device::loadFunctionPointers()
-{
-#ifdef BYPASS_IHWC
- // For all of these early returns, we log an error message inside
- // loadFunctionPointer specifying which function failed to load
-
- // Display function pointers
- if (!loadFunctionPointer(FunctionDescriptor::CreateVirtualDisplay,
- mCreateVirtualDisplay)) return;
- if (!loadFunctionPointer(FunctionDescriptor::DestroyVirtualDisplay,
- mDestroyVirtualDisplay)) return;
- if (!loadFunctionPointer(FunctionDescriptor::Dump, mDump)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetMaxVirtualDisplayCount,
- mGetMaxVirtualDisplayCount)) return;
- if (!loadFunctionPointer(FunctionDescriptor::RegisterCallback,
- mRegisterCallback)) return;
-
- // Device function pointers
- if (!loadFunctionPointer(FunctionDescriptor::AcceptDisplayChanges,
- mAcceptDisplayChanges)) return;
- if (!loadFunctionPointer(FunctionDescriptor::CreateLayer,
- mCreateLayer)) return;
- if (!loadFunctionPointer(FunctionDescriptor::DestroyLayer,
- mDestroyLayer)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetActiveConfig,
- mGetActiveConfig)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetChangedCompositionTypes,
- mGetChangedCompositionTypes)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetColorModes,
- mGetColorModes)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetDisplayAttribute,
- mGetDisplayAttribute)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetDisplayConfigs,
- mGetDisplayConfigs)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetDisplayName,
- mGetDisplayName)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetDisplayRequests,
- mGetDisplayRequests)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetDisplayType,
- mGetDisplayType)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetDozeSupport,
- mGetDozeSupport)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetHdrCapabilities,
- mGetHdrCapabilities)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetReleaseFences,
- mGetReleaseFences)) return;
- if (!loadFunctionPointer(FunctionDescriptor::PresentDisplay,
- mPresentDisplay)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetActiveConfig,
- mSetActiveConfig)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetClientTarget,
- mSetClientTarget)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetColorMode,
- mSetColorMode)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetColorTransform,
- mSetColorTransform)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetOutputBuffer,
- mSetOutputBuffer)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetPowerMode,
- mSetPowerMode)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetVsyncEnabled,
- mSetVsyncEnabled)) return;
- if (!loadFunctionPointer(FunctionDescriptor::ValidateDisplay,
- mValidateDisplay)) return;
-
- // Layer function pointers
- if (!loadFunctionPointer(FunctionDescriptor::SetCursorPosition,
- mSetCursorPosition)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerBuffer,
- mSetLayerBuffer)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerSurfaceDamage,
- mSetLayerSurfaceDamage)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerBlendMode,
- mSetLayerBlendMode)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerColor,
- mSetLayerColor)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerCompositionType,
- mSetLayerCompositionType)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerDataspace,
- mSetLayerDataspace)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerDisplayFrame,
- mSetLayerDisplayFrame)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerPlaneAlpha,
- mSetLayerPlaneAlpha)) return;
- if (hasCapability(Capability::SidebandStream)) {
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerSidebandStream,
- mSetLayerSidebandStream)) return;
- }
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerSourceCrop,
- mSetLayerSourceCrop)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerTransform,
- mSetLayerTransform)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerVisibleRegion,
- mSetLayerVisibleRegion)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerZOrder,
- mSetLayerZOrder)) return;
-#endif // BYPASS_IHWC
-}
-
namespace {
class ComposerCallback : public Hwc2::IComposerCallback {
public:
@@ -498,14 +308,8 @@
void Device::registerCallbacks()
{
-#ifdef BYPASS_IHWC
- registerCallback<HWC2_PFN_HOTPLUG>(Callback::Hotplug, hotplug_hook);
- registerCallback<HWC2_PFN_REFRESH>(Callback::Refresh, refresh_hook);
- registerCallback<HWC2_PFN_VSYNC>(Callback::Vsync, vsync_hook);
-#else
sp<ComposerCallback> callback = new ComposerCallback(this);
mComposer->registerCallback(callback);
-#endif
}
@@ -514,11 +318,7 @@
void Device::destroyVirtualDisplay(hwc2_display_t display)
{
ALOGI("Destroying virtual display");
-#ifdef BYPASS_IHWC
- int32_t intError = mDestroyVirtualDisplay(mHwcDevice, display);
-#else
auto intError = mComposer->destroyVirtualDisplay(display);
-#endif
auto error = static_cast<Error>(intError);
ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64 ") failed:"
" %s (%d)", display, to_string(error).c_str(), intError);
@@ -535,13 +335,8 @@
{
ALOGV("Created display %" PRIu64, id);
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
- reinterpret_cast<int32_t *>(&mType));
-#else
auto intError = mDevice.mComposer->getDisplayType(mId,
reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(&mType));
-#endif
auto error = static_cast<Error>(intError);
if (error != Error::None) {
ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d)",
@@ -588,22 +383,14 @@
Error Display::acceptChanges()
{
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mAcceptDisplayChanges(mDevice.mHwcDevice, mId);
-#else
auto intError = mDevice.mComposer->acceptDisplayChanges(mId);
-#endif
return static_cast<Error>(intError);
}
Error Display::createLayer(std::shared_ptr<Layer>* outLayer)
{
hwc2_layer_t layerId = 0;
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mCreateLayer(mDevice.mHwcDevice, mId, &layerId);
-#else
auto intError = mDevice.mComposer->createLayer(mId, &layerId);
-#endif
auto error = static_cast<Error>(intError);
if (error != Error::None) {
return error;
@@ -620,12 +407,7 @@
{
ALOGV("[%" PRIu64 "] getActiveConfig", mId);
hwc2_config_t configId = 0;
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mGetActiveConfig(mDevice.mHwcDevice, mId,
- &configId);
-#else
auto intError = mDevice.mComposer->getActiveConfig(mId, &configId);
-#endif
auto error = static_cast<Error>(intError);
if (error != Error::None) {
@@ -650,27 +432,12 @@
Error Display::getChangedCompositionTypes(
std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes)
{
-#ifdef BYPASS_IHWC
- uint32_t numElements = 0;
- int32_t intError = mDevice.mGetChangedCompositionTypes(mDevice.mHwcDevice,
- mId, &numElements, nullptr, nullptr);
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- return error;
- }
-
- std::vector<hwc2_layer_t> layerIds(numElements);
- std::vector<int32_t> types(numElements);
- intError = mDevice.mGetChangedCompositionTypes(mDevice.mHwcDevice, mId,
- &numElements, layerIds.data(), types.data());
-#else
std::vector<Hwc2::Layer> layerIds;
std::vector<Hwc2::IComposerClient::Composition> types;
auto intError = mDevice.mComposer->getChangedCompositionTypes(mId,
&layerIds, &types);
uint32_t numElements = layerIds.size();
auto error = static_cast<Error>(intError);
-#endif
error = static_cast<Error>(intError);
if (error != Error::None) {
return error;
@@ -696,25 +463,10 @@
Error Display::getColorModes(std::vector<android_color_mode_t>* outModes) const
{
-#ifdef BYPASS_IHWC
- uint32_t numModes = 0;
- int32_t intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId,
- &numModes, nullptr);
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- return error;
- }
-
- std::vector<int32_t> modes(numModes);
- intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId, &numModes,
- modes.data());
- error = static_cast<Error>(intError);
-#else
std::vector<Hwc2::ColorMode> modes;
auto intError = mDevice.mComposer->getColorModes(mId, &modes);
uint32_t numModes = modes.size();
auto error = static_cast<Error>(intError);
-#endif
if (error != Error::None) {
return error;
}
@@ -737,52 +489,14 @@
Error Display::getName(std::string* outName) const
{
-#ifdef BYPASS_IHWC
- uint32_t size;
- int32_t intError = mDevice.mGetDisplayName(mDevice.mHwcDevice, mId, &size,
- nullptr);
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- return error;
- }
-
- std::vector<char> rawName(size);
- intError = mDevice.mGetDisplayName(mDevice.mHwcDevice, mId, &size,
- rawName.data());
- error = static_cast<Error>(intError);
- if (error != Error::None) {
- return error;
- }
-
- *outName = std::string(rawName.cbegin(), rawName.cend());
- return Error::None;
-#else
auto intError = mDevice.mComposer->getDisplayName(mId, outName);
return static_cast<Error>(intError);
-#endif
}
Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests,
std::unordered_map<std::shared_ptr<Layer>, LayerRequest>*
outLayerRequests)
{
-#ifdef BYPASS_IHWC
- int32_t intDisplayRequests = 0;
- uint32_t numElements = 0;
- int32_t intError = mDevice.mGetDisplayRequests(mDevice.mHwcDevice, mId,
- &intDisplayRequests, &numElements, nullptr, nullptr);
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- return error;
- }
-
- std::vector<hwc2_layer_t> layerIds(numElements);
- std::vector<int32_t> layerRequests(numElements);
- intError = mDevice.mGetDisplayRequests(mDevice.mHwcDevice, mId,
- &intDisplayRequests, &numElements, layerIds.data(),
- layerRequests.data());
- error = static_cast<Error>(intError);
-#else
uint32_t intDisplayRequests;
std::vector<Hwc2::Layer> layerIds;
std::vector<uint32_t> layerRequests;
@@ -790,7 +504,6 @@
&intDisplayRequests, &layerIds, &layerRequests);
uint32_t numElements = layerIds.size();
auto error = static_cast<Error>(intError);
-#endif
if (error != Error::None) {
return error;
}
@@ -821,14 +534,8 @@
Error Display::supportsDoze(bool* outSupport) const
{
-#ifdef BYPASS_IHWC
- int32_t intSupport = 0;
- int32_t intError = mDevice.mGetDozeSupport(mDevice.mHwcDevice, mId,
- &intSupport);
-#else
bool intSupport = false;
auto intError = mDevice.mComposer->getDozeSupport(mId, &intSupport);
-#endif
auto error = static_cast<Error>(intError);
if (error != Error::None) {
return error;
@@ -844,20 +551,6 @@
float maxLuminance = -1.0f;
float maxAverageLuminance = -1.0f;
float minLuminance = -1.0f;
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId,
- &numTypes, nullptr, &maxLuminance, &maxAverageLuminance,
- &minLuminance);
- auto error = static_cast<HWC2::Error>(intError);
- if (error != Error::None) {
- return error;
- }
-
- std::vector<int32_t> types(numTypes);
- intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId, &numTypes,
- types.data(), &maxLuminance, &maxAverageLuminance, &minLuminance);
- error = static_cast<HWC2::Error>(intError);
-#else
std::vector<Hwc2::Hdr> intTypes;
auto intError = mDevice.mComposer->getHdrCapabilities(mId, &intTypes,
&maxLuminance, &maxAverageLuminance, &minLuminance);
@@ -868,7 +561,6 @@
types.push_back(static_cast<int32_t>(type));
}
numTypes = types.size();
-#endif
if (error != Error::None) {
return error;
}
@@ -881,28 +573,12 @@
Error Display::getReleaseFences(
std::unordered_map<std::shared_ptr<Layer>, sp<Fence>>* outFences) const
{
-#ifdef BYPASS_IHWC
- uint32_t numElements = 0;
- int32_t intError = mDevice.mGetReleaseFences(mDevice.mHwcDevice, mId,
- &numElements, nullptr, nullptr);
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- return error;
- }
-
- std::vector<hwc2_layer_t> layerIds(numElements);
- std::vector<int32_t> fenceFds(numElements);
- intError = mDevice.mGetReleaseFences(mDevice.mHwcDevice, mId, &numElements,
- layerIds.data(), fenceFds.data());
- error = static_cast<Error>(intError);
-#else
std::vector<Hwc2::Layer> layerIds;
std::vector<int> fenceFds;
auto intError = mDevice.mComposer->getReleaseFences(mId,
&layerIds, &fenceFds);
auto error = static_cast<Error>(intError);
uint32_t numElements = layerIds.size();
-#endif
if (error != Error::None) {
return error;
}
@@ -917,6 +593,9 @@
} else {
ALOGE("getReleaseFences: invalid layer %" PRIu64
" found on display %" PRIu64, layerIds[element], mId);
+ for (; element < numElements; ++element) {
+ close(fenceFds[element]);
+ }
return Error::BadLayer;
}
}
@@ -928,12 +607,7 @@
Error Display::present(sp<Fence>* outPresentFence)
{
int32_t presentFenceFd = -1;
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mPresentDisplay(mDevice.mHwcDevice, mId,
- &presentFenceFd);
-#else
auto intError = mDevice.mComposer->presentDisplay(mId, &presentFenceFd);
-#endif
auto error = static_cast<Error>(intError);
if (error != Error::None) {
return error;
@@ -951,12 +625,7 @@
config->getDisplayId(), mId);
return Error::BadConfig;
}
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mSetActiveConfig(mDevice.mHwcDevice, mId,
- config->getId());
-#else
auto intError = mDevice.mComposer->setActiveConfig(mId, config->getId());
-#endif
return static_cast<Error>(intError);
}
@@ -965,44 +634,24 @@
{
// TODO: Properly encode client target surface damage
int32_t fenceFd = acquireFence->dup();
-#ifdef BYPASS_IHWC
- (void) slot;
- buffer_handle_t handle = nullptr;
- if (target.get() && target->getNativeBuffer()) {
- handle = target->getNativeBuffer()->handle;
- }
-
- int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, handle,
- fenceFd, static_cast<int32_t>(dataspace), {0, nullptr});
-#else
auto intError = mDevice.mComposer->setClientTarget(mId, slot, target,
fenceFd, static_cast<Hwc2::Dataspace>(dataspace),
std::vector<Hwc2::IComposerClient::Rect>());
-#endif
return static_cast<Error>(intError);
}
Error Display::setColorMode(android_color_mode_t mode)
{
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mSetColorMode(mDevice.mHwcDevice, mId, mode);
-#else
auto intError = mDevice.mComposer->setColorMode(mId,
static_cast<Hwc2::ColorMode>(mode));
-#endif
return static_cast<Error>(intError);
}
Error Display::setColorTransform(const android::mat4& matrix,
android_color_transform_t hint)
{
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mSetColorTransform(mDevice.mHwcDevice, mId,
- matrix.asArray(), static_cast<int32_t>(hint));
-#else
auto intError = mDevice.mComposer->setColorTransform(mId,
matrix.asArray(), static_cast<Hwc2::ColorTransform>(hint));
-#endif
return static_cast<Error>(intError);
}
@@ -1011,38 +660,22 @@
{
int32_t fenceFd = releaseFence->dup();
auto handle = buffer->getNativeBuffer()->handle;
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mSetOutputBuffer(mDevice.mHwcDevice, mId, handle,
- fenceFd);
-#else
auto intError = mDevice.mComposer->setOutputBuffer(mId, handle, fenceFd);
-#endif
close(fenceFd);
return static_cast<Error>(intError);
}
Error Display::setPowerMode(PowerMode mode)
{
-#ifdef BYPASS_IHWC
- auto intMode = static_cast<int32_t>(mode);
- int32_t intError = mDevice.mSetPowerMode(mDevice.mHwcDevice, mId, intMode);
-#else
auto intMode = static_cast<Hwc2::IComposerClient::PowerMode>(mode);
auto intError = mDevice.mComposer->setPowerMode(mId, intMode);
-#endif
return static_cast<Error>(intError);
}
Error Display::setVsyncEnabled(Vsync enabled)
{
-#ifdef BYPASS_IHWC
- auto intEnabled = static_cast<int32_t>(enabled);
- int32_t intError = mDevice.mSetVsyncEnabled(mDevice.mHwcDevice, mId,
- intEnabled);
-#else
auto intEnabled = static_cast<Hwc2::IComposerClient::Vsync>(enabled);
auto intError = mDevice.mComposer->setVsyncEnabled(mId, intEnabled);
-#endif
return static_cast<Error>(intError);
}
@@ -1050,13 +683,8 @@
{
uint32_t numTypes = 0;
uint32_t numRequests = 0;
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mValidateDisplay(mDevice.mHwcDevice, mId,
- &numTypes, &numRequests);
-#else
auto intError = mDevice.mComposer->validateDisplay(mId,
&numTypes, &numRequests);
-#endif
auto error = static_cast<Error>(intError);
if (error != Error::None && error != Error::HasChanges) {
return error;
@@ -1072,14 +700,9 @@
int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute)
{
int32_t value = 0;
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mGetDisplayAttribute(mDevice.mHwcDevice, mId,
- configId, static_cast<int32_t>(attribute), &value);
-#else
auto intError = mDevice.mComposer->getDisplayAttribute(mId, configId,
static_cast<Hwc2::IComposerClient::Attribute>(attribute),
&value);
-#endif
auto error = static_cast<Error>(intError);
if (error != Error::None) {
ALOGE("getDisplayAttribute(%" PRIu64 ", %u, %s) failed: %s (%d)", mId,
@@ -1108,26 +731,9 @@
{
ALOGV("[%" PRIu64 "] loadConfigs", mId);
-#ifdef BYPASS_IHWC
- uint32_t numConfigs = 0;
- int32_t intError = mDevice.mGetDisplayConfigs(mDevice.mHwcDevice, mId,
- &numConfigs, nullptr);
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- ALOGE("[%" PRIu64 "] getDisplayConfigs [1] failed: %s (%d)", mId,
- to_string(error).c_str(), intError);
- return;
- }
-
- std::vector<hwc2_config_t> configIds(numConfigs);
- intError = mDevice.mGetDisplayConfigs(mDevice.mHwcDevice, mId, &numConfigs,
- configIds.data());
- error = static_cast<Error>(intError);
-#else
std::vector<Hwc2::Config> configIds;
auto intError = mDevice.mComposer->getDisplayConfigs(mId, &configIds);
auto error = static_cast<Error>(intError);
-#endif
if (error != Error::None) {
ALOGE("[%" PRIu64 "] getDisplayConfigs [2] failed: %s (%d)", mId,
to_string(error).c_str(), intError);
@@ -1143,11 +749,7 @@
void Display::destroyLayer(hwc2_layer_t layerId)
{
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mDestroyLayer(mDevice.mHwcDevice, mId, layerId);
-#else
auto intError =mDevice.mComposer->destroyLayer(mId, layerId);
-#endif
auto error = static_cast<Error>(intError);
ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
" failed: %s (%d)", mId, layerId, to_string(error).c_str(),
@@ -1189,13 +791,8 @@
Error Layer::setCursorPosition(int32_t x, int32_t y)
{
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mSetCursorPosition(mDevice.mHwcDevice,
- mDisplayId, mId, x, y);
-#else
auto intError = mDevice.mComposer->setCursorPosition(mDisplayId,
mId, x, y);
-#endif
return static_cast<Error>(intError);
}
@@ -1203,19 +800,8 @@
const sp<Fence>& acquireFence)
{
int32_t fenceFd = acquireFence->dup();
-#ifdef BYPASS_IHWC
- (void) slot;
- buffer_handle_t handle = nullptr;
- if (buffer.get() && buffer->getNativeBuffer()) {
- handle = buffer->getNativeBuffer()->handle;
- }
-
- int32_t intError = mDevice.mSetLayerBuffer(mDevice.mHwcDevice, mDisplayId,
- mId, handle, fenceFd);
-#else
auto intError = mDevice.mComposer->setLayerBuffer(mDisplayId,
mId, slot, buffer, fenceFd);
-#endif
return static_cast<Error>(intError);
}
@@ -1223,44 +809,22 @@
{
// We encode default full-screen damage as INVALID_RECT upstream, but as 0
// rects for HWC
-#ifdef BYPASS_IHWC
- int32_t intError = 0;
-#else
Hwc2::Error intError = Hwc2::Error::NONE;
-#endif
if (damage.isRect() && damage.getBounds() == Rect::INVALID_RECT) {
-#ifdef BYPASS_IHWC
- intError = mDevice.mSetLayerSurfaceDamage(mDevice.mHwcDevice,
- mDisplayId, mId, {0, nullptr});
-#else
intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
mId, std::vector<Hwc2::IComposerClient::Rect>());
-#endif
} else {
size_t rectCount = 0;
auto rectArray = damage.getArray(&rectCount);
-#ifdef BYPASS_IHWC
- std::vector<hwc_rect_t> hwcRects;
-#else
std::vector<Hwc2::IComposerClient::Rect> hwcRects;
-#endif
for (size_t rect = 0; rect < rectCount; ++rect) {
hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
rectArray[rect].right, rectArray[rect].bottom});
}
-#ifdef BYPASS_IHWC
- hwc_region_t hwcRegion = {};
- hwcRegion.numRects = rectCount;
- hwcRegion.rects = hwcRects.data();
-
- intError = mDevice.mSetLayerSurfaceDamage(mDevice.mHwcDevice,
- mDisplayId, mId, hwcRegion);
-#else
intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
mId, hwcRects);
-#endif
}
return static_cast<Error>(intError);
@@ -1268,83 +832,49 @@
Error Layer::setBlendMode(BlendMode mode)
{
-#ifdef BYPASS_IHWC
- auto intMode = static_cast<int32_t>(mode);
- int32_t intError = mDevice.mSetLayerBlendMode(mDevice.mHwcDevice,
- mDisplayId, mId, intMode);
-#else
auto intMode = static_cast<Hwc2::IComposerClient::BlendMode>(mode);
auto intError = mDevice.mComposer->setLayerBlendMode(mDisplayId,
mId, intMode);
-#endif
return static_cast<Error>(intError);
}
Error Layer::setColor(hwc_color_t color)
{
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mSetLayerColor(mDevice.mHwcDevice, mDisplayId,
- mId, color);
-#else
Hwc2::IComposerClient::Color hwcColor{color.r, color.g, color.b, color.a};
auto intError = mDevice.mComposer->setLayerColor(mDisplayId,
mId, hwcColor);
-#endif
return static_cast<Error>(intError);
}
Error Layer::setCompositionType(Composition type)
{
-#ifdef BYPASS_IHWC
- auto intType = static_cast<int32_t>(type);
- int32_t intError = mDevice.mSetLayerCompositionType(mDevice.mHwcDevice,
- mDisplayId, mId, intType);
-#else
auto intType = static_cast<Hwc2::IComposerClient::Composition>(type);
auto intError = mDevice.mComposer->setLayerCompositionType(mDisplayId,
mId, intType);
-#endif
return static_cast<Error>(intError);
}
Error Layer::setDataspace(android_dataspace_t dataspace)
{
-#ifdef BYPASS_IHWC
- auto intDataspace = static_cast<int32_t>(dataspace);
- int32_t intError = mDevice.mSetLayerDataspace(mDevice.mHwcDevice,
- mDisplayId, mId, intDataspace);
-#else
auto intDataspace = static_cast<Hwc2::Dataspace>(dataspace);
auto intError = mDevice.mComposer->setLayerDataspace(mDisplayId,
mId, intDataspace);
-#endif
return static_cast<Error>(intError);
}
Error Layer::setDisplayFrame(const Rect& frame)
{
-#ifdef BYPASS_IHWC
- hwc_rect_t hwcRect{frame.left, frame.top, frame.right, frame.bottom};
- int32_t intError = mDevice.mSetLayerDisplayFrame(mDevice.mHwcDevice,
- mDisplayId, mId, hwcRect);
-#else
Hwc2::IComposerClient::Rect hwcRect{frame.left, frame.top,
frame.right, frame.bottom};
auto intError = mDevice.mComposer->setLayerDisplayFrame(mDisplayId,
mId, hwcRect);
-#endif
return static_cast<Error>(intError);
}
Error Layer::setPlaneAlpha(float alpha)
{
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mSetLayerPlaneAlpha(mDevice.mHwcDevice,
- mDisplayId, mId, alpha);
-#else
auto intError = mDevice.mComposer->setLayerPlaneAlpha(mDisplayId,
mId, alpha);
-#endif
return static_cast<Error>(intError);
}
@@ -1355,42 +885,25 @@
"device supports sideband streams");
return Error::Unsupported;
}
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mSetLayerSidebandStream(mDevice.mHwcDevice,
- mDisplayId, mId, stream);
-#else
auto intError = mDevice.mComposer->setLayerSidebandStream(mDisplayId,
mId, stream);
-#endif
return static_cast<Error>(intError);
}
Error Layer::setSourceCrop(const FloatRect& crop)
{
-#ifdef BYPASS_IHWC
- hwc_frect_t hwcRect{crop.left, crop.top, crop.right, crop.bottom};
- int32_t intError = mDevice.mSetLayerSourceCrop(mDevice.mHwcDevice,
- mDisplayId, mId, hwcRect);
-#else
Hwc2::IComposerClient::FRect hwcRect{
crop.left, crop.top, crop.right, crop.bottom};
auto intError = mDevice.mComposer->setLayerSourceCrop(mDisplayId,
mId, hwcRect);
-#endif
return static_cast<Error>(intError);
}
Error Layer::setTransform(Transform transform)
{
-#ifdef BYPASS_IHWC
- auto intTransform = static_cast<int32_t>(transform);
- int32_t intError = mDevice.mSetLayerTransform(mDevice.mHwcDevice,
- mDisplayId, mId, intTransform);
-#else
auto intTransform = static_cast<Hwc2::Transform>(transform);
auto intError = mDevice.mComposer->setLayerTransform(mDisplayId,
mId, intTransform);
-#endif
return static_cast<Error>(intError);
}
@@ -1399,50 +912,26 @@
size_t rectCount = 0;
auto rectArray = region.getArray(&rectCount);
-#ifdef BYPASS_IHWC
- std::vector<hwc_rect_t> hwcRects;
-#else
std::vector<Hwc2::IComposerClient::Rect> hwcRects;
-#endif
for (size_t rect = 0; rect < rectCount; ++rect) {
hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
rectArray[rect].right, rectArray[rect].bottom});
}
-#ifdef BYPASS_IHWC
- hwc_region_t hwcRegion = {};
- hwcRegion.numRects = rectCount;
- hwcRegion.rects = hwcRects.data();
-
- int32_t intError = mDevice.mSetLayerVisibleRegion(mDevice.mHwcDevice,
- mDisplayId, mId, hwcRegion);
-#else
auto intError = mDevice.mComposer->setLayerVisibleRegion(mDisplayId,
mId, hwcRects);
-#endif
return static_cast<Error>(intError);
}
Error Layer::setZOrder(uint32_t z)
{
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mSetLayerZOrder(mDevice.mHwcDevice, mDisplayId,
- mId, z);
-#else
auto intError = mDevice.mComposer->setLayerZOrder(mDisplayId, mId, z);
-#endif
return static_cast<Error>(intError);
}
Error Layer::setInfo(uint32_t type, uint32_t appId)
{
-#ifdef BYPASS_IHWC
- (void)type;
- (void)appId;
- int32_t intError = 0;
-#else
auto intError = mDevice.mComposer->setLayerInfo(mDisplayId, mId, type, appId);
-#endif
return static_cast<Error>(intError);
}
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 643b1e0..97582a7 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -62,14 +62,10 @@
class Device
{
public:
-#ifdef BYPASS_IHWC
- explicit Device(hwc2_device_t* device);
-#else
// useVrComposer is passed to the composer HAL. When true, the composer HAL
// will use the vr composer service, otherwise it uses the real hardware
// composer.
Device(bool useVrComposer);
-#endif
~Device();
friend class HWC2::Display;
@@ -107,43 +103,12 @@
bool hasCapability(HWC2::Capability capability) const;
-#ifdef BYPASS_IHWC
- android::Hwc2::Composer* getComposer() { return nullptr; }
-#else
android::Hwc2::Composer* getComposer() { return mComposer.get(); }
-#endif
private:
// Initialization methods
-#ifdef BYPASS_IHWC
- template <typename PFN>
- [[clang::warn_unused_result]] bool loadFunctionPointer(
- FunctionDescriptor desc, PFN& outPFN) {
- auto intDesc = static_cast<int32_t>(desc);
- auto pfn = mHwcDevice->getFunction(mHwcDevice, intDesc);
- if (pfn != nullptr) {
- outPFN = reinterpret_cast<PFN>(pfn);
- return true;
- } else {
- ALOGE("Failed to load function %s", to_string(desc).c_str());
- return false;
- }
- }
-
- template <typename PFN, typename HOOK>
- void registerCallback(Callback callback, HOOK hook) {
- static_assert(std::is_same<PFN, HOOK>::value,
- "Incompatible function pointer");
- auto intCallback = static_cast<int32_t>(callback);
- auto callbackData = static_cast<hwc2_callback_data_t>(this);
- auto pfn = reinterpret_cast<hwc2_function_pointer_t>(hook);
- mRegisterCallback(mHwcDevice, intCallback, callbackData, pfn);
- }
-#endif
-
void loadCapabilities();
- void loadFunctionPointers();
void registerCallbacks();
// For use by Display
@@ -151,60 +116,7 @@
void destroyVirtualDisplay(hwc2_display_t display);
// Member variables
-
-#ifdef BYPASS_IHWC
- hwc2_device_t* mHwcDevice;
-
- // Device function pointers
- HWC2_PFN_CREATE_VIRTUAL_DISPLAY mCreateVirtualDisplay;
- HWC2_PFN_DESTROY_VIRTUAL_DISPLAY mDestroyVirtualDisplay;
- HWC2_PFN_DUMP mDump;
- HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT mGetMaxVirtualDisplayCount;
- HWC2_PFN_REGISTER_CALLBACK mRegisterCallback;
-
- // Display function pointers
- HWC2_PFN_ACCEPT_DISPLAY_CHANGES mAcceptDisplayChanges;
- HWC2_PFN_CREATE_LAYER mCreateLayer;
- HWC2_PFN_DESTROY_LAYER mDestroyLayer;
- HWC2_PFN_GET_ACTIVE_CONFIG mGetActiveConfig;
- HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES mGetChangedCompositionTypes;
- HWC2_PFN_GET_COLOR_MODES mGetColorModes;
- HWC2_PFN_GET_DISPLAY_ATTRIBUTE mGetDisplayAttribute;
- HWC2_PFN_GET_DISPLAY_CONFIGS mGetDisplayConfigs;
- HWC2_PFN_GET_DISPLAY_NAME mGetDisplayName;
- HWC2_PFN_GET_DISPLAY_REQUESTS mGetDisplayRequests;
- HWC2_PFN_GET_DISPLAY_TYPE mGetDisplayType;
- HWC2_PFN_GET_DOZE_SUPPORT mGetDozeSupport;
- HWC2_PFN_GET_HDR_CAPABILITIES mGetHdrCapabilities;
- HWC2_PFN_GET_RELEASE_FENCES mGetReleaseFences;
- HWC2_PFN_PRESENT_DISPLAY mPresentDisplay;
- HWC2_PFN_SET_ACTIVE_CONFIG mSetActiveConfig;
- HWC2_PFN_SET_CLIENT_TARGET mSetClientTarget;
- HWC2_PFN_SET_COLOR_MODE mSetColorMode;
- HWC2_PFN_SET_COLOR_TRANSFORM mSetColorTransform;
- HWC2_PFN_SET_OUTPUT_BUFFER mSetOutputBuffer;
- HWC2_PFN_SET_POWER_MODE mSetPowerMode;
- HWC2_PFN_SET_VSYNC_ENABLED mSetVsyncEnabled;
- HWC2_PFN_VALIDATE_DISPLAY mValidateDisplay;
-
- // Layer function pointers
- HWC2_PFN_SET_CURSOR_POSITION mSetCursorPosition;
- HWC2_PFN_SET_LAYER_BUFFER mSetLayerBuffer;
- HWC2_PFN_SET_LAYER_SURFACE_DAMAGE mSetLayerSurfaceDamage;
- HWC2_PFN_SET_LAYER_BLEND_MODE mSetLayerBlendMode;
- HWC2_PFN_SET_LAYER_COLOR mSetLayerColor;
- HWC2_PFN_SET_LAYER_COMPOSITION_TYPE mSetLayerCompositionType;
- HWC2_PFN_SET_LAYER_DATASPACE mSetLayerDataspace;
- HWC2_PFN_SET_LAYER_DISPLAY_FRAME mSetLayerDisplayFrame;
- HWC2_PFN_SET_LAYER_PLANE_ALPHA mSetLayerPlaneAlpha;
- HWC2_PFN_SET_LAYER_SIDEBAND_STREAM mSetLayerSidebandStream;
- HWC2_PFN_SET_LAYER_SOURCE_CROP mSetLayerSourceCrop;
- HWC2_PFN_SET_LAYER_TRANSFORM mSetLayerTransform;
- HWC2_PFN_SET_LAYER_VISIBLE_REGION mSetLayerVisibleRegion;
- HWC2_PFN_SET_LAYER_Z_ORDER mSetLayerZOrder;
-#else
std::unique_ptr<android::Hwc2::Composer> mComposer;
-#endif // BYPASS_IHWC
std::unordered_set<Capability> mCapabilities;
std::unordered_map<hwc2_display_t, std::weak_ptr<Display>> mDisplays;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 04ab78f..42be935 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -47,7 +47,6 @@
#include <log/log.h>
#include "HWComposer.h"
-#include "hwc2on1adapter/HWC2On1Adapter.h"
#include "HWC2.h"
#include "ComposerHal.h"
@@ -61,8 +60,7 @@
// ---------------------------------------------------------------------------
HWComposer::HWComposer(bool useVrComposer)
- : mAdapter(),
- mHwcDevice(),
+ : mHwcDevice(),
mDisplayData(2),
mFreeDisplaySlots(),
mHwcDisplaySlots(),
@@ -108,45 +106,7 @@
void HWComposer::loadHwcModule(bool useVrComposer)
{
ALOGV("loadHwcModule");
-
-#ifdef BYPASS_IHWC
- (void)useVrComposer; // Silence unused parameter warning.
-
- hw_module_t const* module;
-
- if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {
- ALOGE("%s module not found, aborting", HWC_HARDWARE_MODULE_ID);
- abort();
- }
-
- hw_device_t* device = nullptr;
- int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device);
- if (error != 0) {
- ALOGE("Failed to open HWC device (%s), aborting", strerror(-error));
- abort();
- }
-
- uint32_t majorVersion = (device->version >> 24) & 0xF;
- if (majorVersion == 2) {
- mHwcDevice = std::make_unique<HWC2::Device>(
- reinterpret_cast<hwc2_device_t*>(device));
- } else {
- mAdapter = std::make_unique<HWC2On1Adapter>(
- reinterpret_cast<hwc_composer_device_1_t*>(device));
- uint8_t minorVersion = mAdapter->getHwc1MinorVersion();
- if (minorVersion < 1) {
- ALOGE("Cannot adapt to HWC version %d.%d",
- static_cast<int32_t>((minorVersion >> 8) & 0xF),
- static_cast<int32_t>(minorVersion & 0xF));
- abort();
- }
- mHwcDevice = std::make_unique<HWC2::Device>(
- static_cast<hwc2_device_t*>(mAdapter.get()));
- }
-#else
mHwcDevice = std::make_unique<HWC2::Device>(useVrComposer);
-#endif
-
mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
}
@@ -870,11 +830,7 @@
*/
bool HWComposer::isUsingVrComposer() const {
-#ifdef BYPASS_IHWC
- return false;
-#else
return getComposer()->isUsingVrComposer();
-#endif
}
void HWComposer::dump(String8& result) const {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 631af14..3eb968d 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -58,7 +58,6 @@
class Fence;
class FloatRect;
class GraphicBuffer;
-class HWC2On1Adapter;
class NativeHandle;
class Region;
class String8;
@@ -205,7 +204,6 @@
HWC2::Vsync vsyncEnabled;
};
- std::unique_ptr<HWC2On1Adapter> mAdapter;
std::unique_ptr<HWC2::Device> mHwcDevice;
std::vector<DisplayData> mDisplayData;
std::set<size_t> mFreeDisplaySlots;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp b/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp
index 6b91224..a234b63 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp
@@ -29,10 +29,6 @@
const sp<GraphicBuffer>& buffer,
uint32_t* outSlot, sp<GraphicBuffer>* outBuffer)
{
-#ifdef BYPASS_IHWC
- *outSlot = slot;
- *outBuffer = buffer;
-#else
if (slot == BufferQueue::INVALID_BUFFER_SLOT || slot < 0) {
// default to slot 0
slot = 0;
@@ -53,7 +49,6 @@
// update cache
mBuffers[slot] = buffer;
}
-#endif
}
} // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 06a0765..d5498ed 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -103,7 +103,7 @@
mLastFrameNumberReceived(0),
mUpdateTexImageFailed(false),
mAutoRefresh(false),
- mFreezePositionUpdates(false)
+ mFreezeGeometryUpdates(false)
{
#ifdef USE_HWC2
ALOGV("Creating Layer %s", name.string());
@@ -131,6 +131,8 @@
mCurrentState.active.transform.set(0, 0);
mCurrentState.crop.makeInvalid();
mCurrentState.finalCrop.makeInvalid();
+ mCurrentState.requestedFinalCrop = mCurrentState.finalCrop;
+ mCurrentState.requestedCrop = mCurrentState.crop;
mCurrentState.z = 0;
#ifdef USE_HWC2
mCurrentState.alpha = 1.0f;
@@ -296,6 +298,11 @@
}
mSurfaceFlingerConsumer->abandon();
+
+#ifdef USE_HWC2
+ clearHwcLayers();
+#endif
+
for (const auto& child : mCurrentChildren) {
child->onRemoved();
}
@@ -1636,12 +1643,25 @@
}
}
- // always set active to requested, unless we're asked not to
- // this is used by Layer, which special cases resizes.
- if (flags & eDontUpdateGeometryState) {
- } else {
+ // Here we apply various requested geometry states, depending on our
+ // latching configuration. See Layer.h for a detailed discussion of
+ // how geometry latching is controlled.
+ if (!(flags & eDontUpdateGeometryState)) {
Layer::State& editCurrentState(getCurrentState());
- if (mFreezePositionUpdates) {
+
+ // If mFreezeGeometryUpdates is true we are in the setGeometryAppliesWithResize
+ // mode, which causes attributes which normally latch regardless of scaling mode,
+ // to be delayed. We copy the requested state to the active state making sure
+ // to respect these rules (again see Layer.h for a detailed discussion).
+ //
+ // There is an awkward asymmetry in the handling of the crop states in the position
+ // states, as can be seen below. Largely this arises from position and transform
+ // being stored in the same data structure while having different latching rules.
+ // b/38182305
+ //
+ // Careful that "c" and editCurrentState may not begin as equivalent due to
+ // applyPendingStates in the presence of deferred transactions.
+ if (mFreezeGeometryUpdates) {
float tx = c.active.transform.tx();
float ty = c.active.transform.ty();
c.active = c.requested;
@@ -1702,10 +1722,14 @@
// we want to apply the position portion of the transform matrix immediately,
// but still delay scaling when resizing a SCALING_MODE_FREEZE layer.
mCurrentState.requested.transform.set(x, y);
- if (immediate && !mFreezePositionUpdates) {
+ if (immediate && !mFreezeGeometryUpdates) {
+ // Here we directly update the active state
+ // unlike other setters, because we store it within
+ // the transform, but use different latching rules.
+ // b/38182305
mCurrentState.active.transform.set(x, y);
}
- mFreezePositionUpdates = mFreezePositionUpdates || !immediate;
+ mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
@@ -1828,26 +1852,30 @@
}
bool Layer::setCrop(const Rect& crop, bool immediate) {
- if (mCurrentState.crop == crop)
+ if (mCurrentState.requestedCrop == crop)
return false;
mCurrentState.sequence++;
mCurrentState.requestedCrop = crop;
- if (immediate) {
+ if (immediate && !mFreezeGeometryUpdates) {
mCurrentState.crop = crop;
}
+ mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
+
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
bool Layer::setFinalCrop(const Rect& crop, bool immediate) {
- if (mCurrentState.finalCrop == crop)
+ if (mCurrentState.requestedFinalCrop == crop)
return false;
mCurrentState.sequence++;
mCurrentState.requestedFinalCrop = crop;
- if (immediate) {
+ if (immediate && !mFreezeGeometryUpdates) {
mCurrentState.finalCrop = crop;
}
+ mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
+
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
@@ -2137,7 +2165,7 @@
bool queuedBuffer = false;
LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
getProducerStickyTransform() != 0, mName.string(),
- mOverrideScalingMode, mFreezePositionUpdates);
+ mOverrideScalingMode, mFreezeGeometryUpdates);
status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer,
mLastFrameNumberReceived);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 9f45435..05c367d 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -169,25 +169,64 @@
// the this layer's size and format
status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
- // modify current state
+ // ------------------------------------------------------------------------
+ // Geometry setting functions.
+ //
+ // The following group of functions are used to specify the layers
+ // bounds, and the mapping of the texture on to those bounds. According
+ // to various settings changes to them may apply immediately, or be delayed until
+ // a pending resize is completed by the producer submitting a buffer. For example
+ // if we were to change the buffer size, and update the matrix ahead of the
+ // new buffer arriving, then we would be stretching the buffer to a different
+ // aspect before and after the buffer arriving, which probably isn't what we wanted.
+ //
+ // The first set of geometry functions are controlled by the scaling mode, described
+ // in window.h. The scaling mode may be set by the client, as it submits buffers.
+ // This value may be overriden through SurfaceControl, with setOverrideScalingMode.
+ //
+ // Put simply, if our scaling mode is SCALING_MODE_FREEZE, then
+ // matrix updates will not be applied while a resize is pending
+ // and the size and transform will remain in their previous state
+ // until a new buffer is submitted. If the scaling mode is another value
+ // then the old-buffer will immediately be scaled to the pending size
+ // and the new matrix will be immediately applied following this scaling
+ // transformation.
- // These members of state (position, crop, and finalCrop)
- // may be updated immediately or have the update delayed
- // until a pending surface resize completes (if applicable).
+ // Set the default buffer size for the assosciated Producer, in pixels. This is
+ // also the rendered size of the layer prior to any transformations. Parent
+ // or local matrix transformations will not affect the size of the buffer,
+ // but may affect it's on-screen size or clipping.
+ bool setSize(uint32_t w, uint32_t h);
+ // Set a 2x2 transformation matrix on the layer. This transform
+ // will be applied after parent transforms, but before any final
+ // producer specified transform.
+ bool setMatrix(const layer_state_t::matrix22_t& matrix);
+
+ // This second set of geometry attributes are controlled by
+ // setGeometryAppliesWithResize, and their default mode is to be
+ // immediate. If setGeometryAppliesWithResize is specified
+ // while a resize is pending, then update of these attributes will
+ // be delayed until the resize completes.
+
+ // setPosition operates in parent buffer space (pre parent-transform) or display
+ // space for top-level layers.
bool setPosition(float x, float y, bool immediate);
+ // Buffer space
bool setCrop(const Rect& crop, bool immediate);
+ // Parent buffer space/display space
bool setFinalCrop(const Rect& crop, bool immediate);
+ // TODO(b/38182121): Could we eliminate the various latching modes by
+ // using the layer hierarchy?
+ // -----------------------------------------------------------------------
bool setLayer(int32_t z);
bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ);
- bool setSize(uint32_t w, uint32_t h);
#ifdef USE_HWC2
bool setAlpha(float alpha);
#else
bool setAlpha(uint8_t alpha);
#endif
- bool setMatrix(const layer_state_t::matrix22_t& matrix);
bool setTransparentRegionHint(const Region& transparent);
bool setFlags(uint8_t flags, uint8_t mask);
bool setLayerStack(uint32_t layerStack);
@@ -754,7 +793,7 @@
bool mUpdateTexImageFailed; // This is only accessed on the main thread.
bool mAutoRefresh;
- bool mFreezePositionUpdates;
+ bool mFreezeGeometryUpdates;
// Child list about to be committed/used for editing.
LayerVector mCurrentChildren;
diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp
index 0b302eb..6e37b45 100644
--- a/services/surfaceflinger/LayerRejecter.cpp
+++ b/services/surfaceflinger/LayerRejecter.cpp
@@ -37,7 +37,7 @@
mStickyTransformSet(stickySet),
mName(name),
mOverrideScalingMode(overrideScalingMode),
- mFreezePositionUpdates(freezePositionUpdates) {}
+ mFreezeGeometryUpdates(freezePositionUpdates) {}
bool LayerRejecter::reject(const sp<GraphicBuffer>& buf, const BufferItem& item) {
if (buf == NULL) {
@@ -73,6 +73,19 @@
// recompute visible region
mRecomputeVisibleRegions = true;
+
+ mFreezeGeometryUpdates = false;
+
+ if (mFront.crop != mFront.requestedCrop) {
+ mFront.crop = mFront.requestedCrop;
+ mCurrent.crop = mFront.requestedCrop;
+ mRecomputeVisibleRegions = true;
+ }
+ if (mFront.finalCrop != mFront.requestedFinalCrop) {
+ mFront.finalCrop = mFront.requestedFinalCrop;
+ mCurrent.finalCrop = mFront.requestedFinalCrop;
+ mRecomputeVisibleRegions = true;
+ }
}
ALOGD_IF(DEBUG_RESIZE,
@@ -100,6 +113,10 @@
// conservative, but that's fine, worst case we're doing
// a bit of extra work), we latch the new one and we
// trigger a visible-region recompute.
+ //
+ // We latch the transparent region here, instead of above where we latch
+ // the rest of the geometry because it is only content but not necessarily
+ // resize dependent.
if (!mFront.activeTransparentRegion.isTriviallyEqual(mFront.requestedTransparentRegion)) {
mFront.activeTransparentRegion = mFront.requestedTransparentRegion;
@@ -115,18 +132,6 @@
mRecomputeVisibleRegions = true;
}
- if (mFront.crop != mFront.requestedCrop) {
- mFront.crop = mFront.requestedCrop;
- mCurrent.crop = mFront.requestedCrop;
- mRecomputeVisibleRegions = true;
- }
- if (mFront.finalCrop != mFront.requestedFinalCrop) {
- mFront.finalCrop = mFront.requestedFinalCrop;
- mCurrent.finalCrop = mFront.requestedFinalCrop;
- mRecomputeVisibleRegions = true;
- }
- mFreezePositionUpdates = false;
-
return false;
}
diff --git a/services/surfaceflinger/LayerRejecter.h b/services/surfaceflinger/LayerRejecter.h
index c2a9483..828cd8b 100644
--- a/services/surfaceflinger/LayerRejecter.h
+++ b/services/surfaceflinger/LayerRejecter.h
@@ -40,8 +40,8 @@
bool mStickyTransformSet;
const char *mName;
int32_t mOverrideScalingMode;
- bool &mFreezePositionUpdates;
+ bool &mFreezeGeometryUpdates;
};
} // namespace android
-#endif // ANDROID_LAYER_REJECTER_H
\ No newline at end of file
+#endif // ANDROID_LAYER_REJECTER_H
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index d15376e..e50f3ce 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -18,6 +18,7 @@
#include <sched.h>
+#include <android/frameworks/displayservice/1.0/IDisplayService.h>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
#include <cutils/sched_policy.h>
@@ -25,6 +26,7 @@
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
+#include <displayservice/DisplayService.h>
#include <hidl/LegacySupport.h>
#include <configstore/Utils.h>
#include "GpuService.h"
@@ -32,14 +34,9 @@
using namespace android;
-using android::hardware::graphics::allocator::V2_0::IAllocator;
-using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
-using android::hardware::configstore::getBool;
-using android::hardware::configstore::getBool;
-
static status_t startGraphicsAllocatorService() {
- hardware::configureRpcThreadpool( 1 /* maxThreads */,
- false /* callerWillJoin */);
+ using android::hardware::graphics::allocator::V2_0::IAllocator;
+
status_t result =
hardware::registerPassthroughServiceImplementation<IAllocator>();
if (result != OK) {
@@ -50,12 +47,38 @@
return OK;
}
-int main(int, char**) {
+static status_t startHidlServices() {
+ using android::frameworks::displayservice::V1_0::implementation::DisplayService;
+ using android::frameworks::displayservice::V1_0::IDisplayService;
+ using android::hardware::configstore::getBool;
+ using android::hardware::configstore::getBool;
+ using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
+ hardware::configureRpcThreadpool(1 /* maxThreads */,
+ false /* callerWillJoin */);
+
+ status_t err;
+
if (getBool<ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::startGraphicsAllocatorService>(false)) {
- startGraphicsAllocatorService();
+ err = startGraphicsAllocatorService();
+ if (err != OK) {
+ return err;
+ }
}
+ sp<IDisplayService> displayservice = new DisplayService();
+ err = displayservice->registerAsService();
+
+ if (err != OK) {
+ ALOGE("Could not register IDisplayService service.");
+ }
+
+ return err;
+}
+
+int main(int, char**) {
+ startHidlServices();
+
signal(SIGPIPE, SIG_IGN);
// When SF is launched in its own process, limit the number of
// binder threads to 4.
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 1b17e55..68519a1 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -33,7 +33,7 @@
// Fill an RGBA_8888 formatted surface with a single color.
static void fillSurfaceRGBA8(const sp<SurfaceControl>& sc,
- uint8_t r, uint8_t g, uint8_t b) {
+ uint8_t r, uint8_t g, uint8_t b, bool unlock=true) {
ANativeWindow_Buffer outBuffer;
sp<Surface> s = sc->getSurface();
ASSERT_TRUE(s != NULL);
@@ -48,7 +48,9 @@
pixel[3] = 255;
}
}
- ASSERT_EQ(NO_ERROR, s->unlockAndPost());
+ if (unlock) {
+ ASSERT_EQ(NO_ERROR, s->unlockAndPost());
+ }
}
// A ScreenCapture is a screenshot from SurfaceFlinger that can be used to check
@@ -479,6 +481,17 @@
sc->expectFGColor(127, 127);
sc->expectBGColor(128, 128);
}
+
+ void lockAndFillFGBuffer() {
+ fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63, false);
+ }
+
+ void unlockFGBuffer() {
+ sp<Surface> s = mFGSurfaceControl->getSurface();
+ ASSERT_EQ(NO_ERROR, s->unlockAndPost());
+ waitForPostedBuffers();
+ }
+
void completeFGResize() {
fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
waitForPostedBuffers();
@@ -605,6 +618,65 @@
EXPECT_CROPPED_STATE("after the resize finishes");
}
+// In this test we ensure that setGeometryAppliesWithResize actually demands
+// a buffer of the new size, and not just any size.
+TEST_F(CropLatchingTest, FinalCropLatchingBufferOldSize) {
+ EXPECT_INITIAL_STATE("before anything");
+ // Normally the crop applies immediately even while a resize is pending.
+ SurfaceComposerClient::openGlobalTransaction();
+ mFGSurfaceControl->setSize(128, 128);
+ mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+ EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)");
+
+ restoreInitialState();
+
+ // In order to prepare to submit a buffer at the wrong size, we acquire it prior to
+ // initiating the resize.
+ lockAndFillFGBuffer();
+
+ SurfaceComposerClient::openGlobalTransaction();
+ mFGSurfaceControl->setSize(128, 128);
+ mFGSurfaceControl->setGeometryAppliesWithResize();
+ mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+ EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)");
+
+ // We now submit our old buffer, at the old size, and ensure it doesn't
+ // trigger geometry latching.
+ unlockFGBuffer();
+
+ EXPECT_INITIAL_STATE("after unlocking FG buffer (with geometryAppliesWithResize)");
+
+ completeFGResize();
+
+ EXPECT_CROPPED_STATE("after the resize finishes");
+}
+
+TEST_F(CropLatchingTest, FinalCropLatchingRegressionForb37531386) {
+ EXPECT_INITIAL_STATE("before anything");
+ // In this scenario, we attempt to set the final crop a second time while the resize
+ // is still pending, and ensure we are successful. Success meaning the second crop
+ // is the one which eventually latches and not the first.
+ SurfaceComposerClient::openGlobalTransaction();
+ mFGSurfaceControl->setSize(128, 128);
+ mFGSurfaceControl->setGeometryAppliesWithResize();
+ mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+ SurfaceComposerClient::openGlobalTransaction();
+ mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+ EXPECT_INITIAL_STATE("after setting crops with geometryAppliesWithResize");
+
+ completeFGResize();
+
+ EXPECT_INITIAL_STATE("after the resize finishes");
+}
+
TEST_F(LayerUpdateTest, DeferredTransactionTest) {
sp<ScreenCapture> sc;
{
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 0005a90..6f425f5 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -39,9 +39,6 @@
android_namespace_t* android_get_exported_namespace(const char*);
}
-// Set to true to enable exposing unratified extensions for development
-static const bool kEnableUnratifiedExtensions = false;
-
// #define ENABLE_ALLOC_CALLSTACKS 1
#if ENABLE_ALLOC_CALLSTACKS
#include <utils/CallStack.h>
@@ -717,12 +714,9 @@
loader_extensions.push_back({
VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME,
VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION});
-
- if (kEnableUnratifiedExtensions) {
- loader_extensions.push_back({
- VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
- VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION});
- }
+ loader_extensions.push_back({
+ VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
+ VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION});
static const VkExtensionProperties loader_debug_report_extension = {
VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION,
@@ -818,15 +812,12 @@
VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION});
- if (kEnableUnratifiedExtensions) {
- // conditionally add shared_presentable_image if supportable
- VkPhysicalDevicePresentationPropertiesANDROID presentation_properties;
- if (QueryPresentationProperties(physicalDevice, &presentation_properties) &&
- presentation_properties.sharedImage) {
- loader_extensions.push_back({
- VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME,
- VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION});
- }
+ VkPhysicalDevicePresentationPropertiesANDROID presentation_properties;
+ if (QueryPresentationProperties(physicalDevice, &presentation_properties) &&
+ presentation_properties.sharedImage) {
+ loader_extensions.push_back({
+ VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME,
+ VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION});
}
// conditionally add VK_GOOGLE_display_timing if present timestamps are
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index caa2674..e2c8c06 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1092,12 +1092,9 @@
image_native_buffer.stride = img.buffer->stride;
image_native_buffer.format = img.buffer->format;
image_native_buffer.usage = img.buffer->usage;
- // TODO: Adjust once ANativeWindowBuffer supports gralloc1-style usage.
- // For now, this is the same translation Gralloc1On0Adapter does.
- image_native_buffer.usage2.consumer =
- static_cast<uint64_t>(img.buffer->usage);
- image_native_buffer.usage2.producer =
- static_cast<uint64_t>(img.buffer->usage);
+ android_convertGralloc0To1Usage(img.buffer->usage,
+ &image_native_buffer.usage2.producer,
+ &image_native_buffer.usage2.consumer);
result =
dispatch.CreateImage(device, &image_create, nullptr, &img.image);