Merge "vkjson: Use Vulkan API version 1.1 on VkJsonGetInstance" into pie-vts-dev am: 2e4003ba01
Change-Id: I91d8112bd6f25af79ee18837e697e7d33dd4dfd3
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index fe9dd56..31e73fb 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -200,7 +200,7 @@
{ REQ, "events/vmscan/mm_vmscan_direct_reclaim_end/enable" },
{ REQ, "events/vmscan/mm_vmscan_kswapd_wake/enable" },
{ REQ, "events/vmscan/mm_vmscan_kswapd_sleep/enable" },
- { REQ, "events/lowmemorykiller/enable" },
+ { OPT, "events/lowmemorykiller/enable" },
} },
{ "regulators", "Voltage and Current Regulators", 0, {
{ REQ, "events/regulator/enable" },
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 9d897f5..1d951be 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1537,6 +1537,12 @@
DUMPSYS_COMPONENTS_OPTIONS);
printf("========================================================\n");
+ printf("== Checkins\n");
+ printf("========================================================\n");
+
+ RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
+
+ printf("========================================================\n");
printf("== dumpstate: done (id %d)\n", ds.id_);
printf("========================================================\n");
}
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 1ea2c2c..ecdc075 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -41,6 +41,13 @@
*
* Note that this structure is used for IPCs so its layout must be identical
* on 64 and 32 bit processes. This is tested in StructLayout_test.cpp.
+ *
+ * Since the struct must be aligned to an 8-byte boundary, there could be uninitialized bytes
+ * in-between the defined fields. This padding data should be explicitly accounted for by adding
+ * "empty" fields into the struct. This data is memset to zero before sending the struct across
+ * the socket. Adding the explicit fields ensures that the memset is not optimized away by the
+ * compiler. When a new field is added to the struct, the corresponding change
+ * in StructLayout_test should be made.
*/
struct InputMessage {
enum {
@@ -61,6 +68,7 @@
union Body {
struct Key {
uint32_t seq;
+ uint32_t empty1;
nsecs_t eventTime __attribute__((aligned(8)));
int32_t deviceId;
int32_t source;
@@ -71,6 +79,7 @@
int32_t scanCode;
int32_t metaState;
int32_t repeatCount;
+ uint32_t empty2;
nsecs_t downTime __attribute__((aligned(8)));
inline size_t size() const {
@@ -80,6 +89,7 @@
struct Motion {
uint32_t seq;
+ uint32_t empty1;
nsecs_t eventTime __attribute__((aligned(8)));
int32_t deviceId;
int32_t source;
@@ -90,12 +100,14 @@
int32_t metaState;
int32_t buttonState;
int32_t edgeFlags;
+ uint32_t empty2;
nsecs_t downTime __attribute__((aligned(8)));
float xOffset;
float yOffset;
float xPrecision;
float yPrecision;
uint32_t pointerCount;
+ uint32_t empty3;
// Note that PointerCoords requires 8 byte alignment.
struct Pointer {
PointerProperties properties;
@@ -126,6 +138,7 @@
bool isValid(size_t actualSize) const;
size_t size() const;
+ void getSanitizedCopy(InputMessage* msg) const;
};
/*
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index be3bbf7..4896f68 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -149,12 +149,13 @@
const bool isVendorService =
strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0;
const long timeout = uptimeMillis() + 5000;
- if (!gSystemBootCompleted) {
+ if (!gSystemBootCompleted && !isVendorService) {
+ // Vendor code can't access system properties
char bootCompleted[PROPERTY_VALUE_MAX];
property_get("sys.boot_completed", bootCompleted, "0");
gSystemBootCompleted = strcmp(bootCompleted, "1") == 0 ? true : false;
}
- // retry interval in millisecond.
+ // retry interval in millisecond; note that vendor services stay at 100ms
const long sleepTime = gSystemBootCompleted ? 1000 : 100;
int n = 0;
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 2e7edd7..43e4580 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2013,8 +2013,8 @@
const char* Parcel::readCString() const
{
- const size_t avail = mDataSize-mDataPos;
- if (avail > 0) {
+ if (mDataPos < mDataSize) {
+ const size_t avail = mDataSize-mDataPos;
const char* str = reinterpret_cast<const char*>(mData+mDataPos);
// is the string's trailing NUL within the parcel's valid bounds?
const char* eos = reinterpret_cast<const char*>(memchr(str, 0, avail));
@@ -2709,10 +2709,18 @@
}
release_object(proc, *flat, this, &mOpenAshmemSize);
}
- binder_size_t* objects =
- (binder_size_t*)realloc(mObjects, objectsSize*sizeof(binder_size_t));
- if (objects) {
- mObjects = objects;
+
+ if (objectsSize == 0) {
+ free(mObjects);
+ mObjects = nullptr;
+ mObjectsCapacity = 0;
+ } else {
+ binder_size_t* objects =
+ (binder_size_t*)realloc(mObjects, objectsSize*sizeof(binder_size_t));
+ if (objects) {
+ mObjects = objects;
+ mObjectsCapacity = objectsSize;
+ }
}
mObjectsSize = objectsSize;
mNextObjectHint = 0;
diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp
index a9d5055..fe0e592 100644
--- a/libs/binder/Status.cpp
+++ b/libs/binder/Status.cpp
@@ -76,13 +76,23 @@
// Skip over fat response headers. Not used (or propagated) in native code.
if (mException == EX_HAS_REPLY_HEADER) {
// Note that the header size includes the 4 byte size field.
- const int32_t header_start = parcel.dataPosition();
+ const size_t header_start = parcel.dataPosition();
+ // Get available size before reading more
+ const size_t header_avail = parcel.dataAvail();
+
int32_t header_size;
status = parcel.readInt32(&header_size);
if (status != OK) {
setFromStatusT(status);
return status;
}
+
+ if (header_size < 0 || static_cast<size_t>(header_size) > header_avail) {
+ android_errorWriteLog(0x534e4554, "132650049");
+ setFromStatusT(UNKNOWN_ERROR);
+ return UNKNOWN_ERROR;
+ }
+
parcel.setDataPosition(header_start + header_size);
// And fat response headers are currently only used when there are no
// exceptions, so act like there was no error.
@@ -109,19 +119,36 @@
setFromStatusT(status);
return status;
}
+ if (remote_stack_trace_header_size < 0 ||
+ static_cast<size_t>(remote_stack_trace_header_size) > parcel.dataAvail()) {
+
+ android_errorWriteLog(0x534e4554, "132650049");
+ setFromStatusT(UNKNOWN_ERROR);
+ return UNKNOWN_ERROR;
+ }
parcel.setDataPosition(parcel.dataPosition() + remote_stack_trace_header_size);
if (mException == EX_SERVICE_SPECIFIC) {
status = parcel.readInt32(&mErrorCode);
} else if (mException == EX_PARCELABLE) {
// Skip over the blob of Parcelable data
- const int32_t header_start = parcel.dataPosition();
+ const size_t header_start = parcel.dataPosition();
+ // Get available size before reading more
+ const size_t header_avail = parcel.dataAvail();
+
int32_t header_size;
status = parcel.readInt32(&header_size);
if (status != OK) {
setFromStatusT(status);
return status;
}
+
+ if (header_size < 0 || static_cast<size_t>(header_size) > header_avail) {
+ android_errorWriteLog(0x534e4554, "132650049");
+ setFromStatusT(UNKNOWN_ERROR);
+ return UNKNOWN_ERROR;
+ }
+
parcel.setDataPosition(header_start + header_size);
}
if (status != OK) {
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index c8021e4..9d7f14c 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -381,7 +381,6 @@
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
- mCore->waitWhileAllocatingLocked();
if (format == 0) {
format = mCore->mDefaultBufferFormat;
@@ -990,14 +989,6 @@
mCallbackCondition.broadcast();
}
- // Wait without lock held
- if (connectedApi == NATIVE_WINDOW_API_EGL) {
- // Waiting here allows for two full buffers to be queued but not a
- // third. In the event that frames take varying time, this makes a
- // small trade-off in favor of latency rather than throughput.
- lastQueuedFence->waitForever("Throttling EGL Production");
- }
-
// Update and get FrameEventHistory.
nsecs_t postedTime = systemTime(SYSTEM_TIME_MONOTONIC);
NewFrameEventsEntry newFrameEventsEntry = {
@@ -1009,6 +1000,14 @@
addAndGetFrameTimestamps(&newFrameEventsEntry,
getFrameTimestamps ? &output->frameTimestamps : nullptr);
+ // Wait without lock held
+ if (connectedApi == NATIVE_WINDOW_API_EGL) {
+ // Waiting here allows for two full buffers to be queued but not a
+ // third. In the event that frames take varying time, this makes a
+ // small trade-off in favor of latency rather than throughput.
+ lastQueuedFence->waitForever("Throttling EGL Production");
+ }
+
return NO_ERROR;
}
@@ -1345,7 +1344,9 @@
return;
}
- newBufferCount = mCore->mFreeSlots.size();
+ // Only allocate one buffer at a time to reduce risks of overlapping an allocation from
+ // both allocateBuffers and dequeueBuffer.
+ newBufferCount = mCore->mFreeSlots.empty() ? 0 : 1;
if (newBufferCount == 0) {
return;
}
@@ -1360,7 +1361,7 @@
} // Autolock scope
Vector<sp<GraphicBuffer>> buffers;
- for (size_t i = 0; i < newBufferCount; ++i) {
+ for (size_t i = 0; i < newBufferCount; ++i) {
sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT,
allocUsage, allocName);
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 0749fde..0b37960 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -355,7 +355,7 @@
data.writeUint32(height);
data.writeInt32(static_cast<int32_t>(format));
data.writeUint64(usage);
- status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply);
+ status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply, TF_ONE_WAY);
if (result != NO_ERROR) {
ALOGE("allocateBuffers failed to transact: %d", result);
}
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index e22bc70..cec86e2 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -103,9 +103,10 @@
}
virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
+ bool& outCapturedSecureLayers,
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
- ISurfaceComposer::Rotation rotation) {
+ ISurfaceComposer::Rotation rotation, bool captureSecureLayers) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
@@ -116,6 +117,7 @@
data.writeInt32(maxLayerZ);
data.writeInt32(static_cast<int32_t>(useIdentityTransform));
data.writeInt32(static_cast<int32_t>(rotation));
+ data.writeInt32(static_cast<int32_t>(captureSecureLayers));
status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
if (err != NO_ERROR) {
@@ -129,6 +131,8 @@
*outBuffer = new GraphicBuffer();
reply.read(**outBuffer);
+ outCapturedSecureLayers = reply.readBool();
+
return err;
}
@@ -332,6 +336,34 @@
return result;
}
+ virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) {
+ Parcel data, reply;
+ status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ if (result != NO_ERROR) {
+ ALOGE("getDisplayViewport failed to writeInterfaceToken: %d", result);
+ return result;
+ }
+ result = data.writeStrongBinder(display);
+ if (result != NO_ERROR) {
+ ALOGE("getDisplayViewport failed to writeStrongBinder: %d", result);
+ return result;
+ }
+ result = remote()->transact(BnSurfaceComposer::GET_DISPLAY_VIEWPORT, data, &reply);
+ if (result != NO_ERROR) {
+ ALOGE("getDisplayViewport failed to transact: %d", result);
+ return result;
+ }
+ result = reply.readInt32();
+ if (result == NO_ERROR) {
+ result = reply.read(*outViewport);
+ if (result != NO_ERROR) {
+ ALOGE("getDisplayViewport failed to read: %d", result);
+ return result;
+ }
+ }
+ return result;
+ }
+
virtual int getActiveConfig(const sp<IBinder>& display)
{
Parcel data, reply;
@@ -615,13 +647,17 @@
int32_t maxLayerZ = data.readInt32();
bool useIdentityTransform = static_cast<bool>(data.readInt32());
int32_t rotation = data.readInt32();
+ bool captureSecureLayers = static_cast<bool>(data.readInt32());
- status_t res = captureScreen(display, &outBuffer, sourceCrop, reqWidth, reqHeight,
- minLayerZ, maxLayerZ, useIdentityTransform,
- static_cast<ISurfaceComposer::Rotation>(rotation));
+ bool capturedSecureLayers = false;
+ status_t res = captureScreen(display, &outBuffer, capturedSecureLayers, sourceCrop, reqWidth,
+ reqHeight, minLayerZ, maxLayerZ, useIdentityTransform,
+ static_cast<ISurfaceComposer::Rotation>(rotation), captureSecureLayers);
+
reply->writeInt32(res);
if (res == NO_ERROR) {
reply->write(*outBuffer);
+ reply->writeBool(capturedSecureLayers);
}
return NO_ERROR;
}
@@ -724,6 +760,26 @@
}
return NO_ERROR;
}
+ case GET_DISPLAY_VIEWPORT: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ Rect outViewport;
+ sp<IBinder> display = nullptr;
+ status_t result = data.readStrongBinder(&display);
+ if (result != NO_ERROR) {
+ ALOGE("getDisplayViewport failed to readStrongBinder: %d", result);
+ return result;
+ }
+ result = getDisplayViewport(display, &outViewport);
+ result = reply->writeInt32(result);
+ if (result == NO_ERROR) {
+ result = reply->write(outViewport);
+ if (result != NO_ERROR) {
+ ALOGE("getDisplayViewport failed to write: %d", result);
+ return result;
+ }
+ }
+ return NO_ERROR;
+ }
case GET_ACTIVE_CONFIG: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> display = data.readStrongBinder();
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 339bd0f..2de14c8 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -464,8 +464,12 @@
if (interval > maxSwapInterval)
interval = maxSwapInterval;
+ const bool wasSwapIntervalZero = mSwapIntervalZero;
mSwapIntervalZero = (interval == 0);
- mGraphicBufferProducer->setAsyncMode(mSwapIntervalZero);
+
+ if (mSwapIntervalZero != wasSwapIntervalZero) {
+ mGraphicBufferProducer->setAsyncMode(mSwapIntervalZero);
+ }
return NO_ERROR;
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 63560c4..1002576 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -718,6 +718,10 @@
return NO_ERROR;
}
+status_t SurfaceComposerClient::getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) {
+ return ComposerService::getComposerService()->getDisplayViewport(display, outViewport);
+}
+
int SurfaceComposerClient::getActiveConfig(const sp<IBinder>& display) {
return ComposerService::getComposerService()->getActiveConfig(display);
}
@@ -764,18 +768,29 @@
status_t ScreenshotClient::capture(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth,
uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ,
bool useIdentityTransform, uint32_t rotation,
- sp<GraphicBuffer>* outBuffer) {
+ bool captureSecureLayers, sp<GraphicBuffer>* outBuffer,
+ bool& outCapturedSecureLayers) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
if (s == NULL) return NO_INIT;
- status_t ret = s->captureScreen(display, outBuffer, sourceCrop, reqWidth, reqHeight, minLayerZ,
- maxLayerZ, useIdentityTransform,
- static_cast<ISurfaceComposer::Rotation>(rotation));
+ status_t ret = s->captureScreen(display, outBuffer, outCapturedSecureLayers, sourceCrop,
+ reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform,
+ static_cast<ISurfaceComposer::Rotation>(rotation),
+ captureSecureLayers);
if (ret != NO_ERROR) {
return ret;
}
return ret;
}
+status_t ScreenshotClient::capture(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth,
+ uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ,
+ bool useIdentityTransform, uint32_t rotation,
+ sp<GraphicBuffer>* outBuffer) {
+ bool ignored;
+ return capture(display, sourceCrop, reqWidth, reqHeight,
+ minLayerZ, maxLayerZ, useIdentityTransform, rotation, false, outBuffer, ignored);
+}
+
status_t ScreenshotClient::captureLayers(const sp<IBinder>& layerHandle, Rect sourceCrop,
float frameScale, sp<GraphicBuffer>* outBuffer) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
diff --git a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
index 3b89291..fe99620 100644
--- a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
+++ b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
@@ -1056,7 +1056,7 @@
status_t H2BGraphicBufferProducer::attachBuffer(
int* outSlot, const sp<GraphicBuffer>& buffer) {
- AnwBuffer tBuffer;
+ AnwBuffer tBuffer{};
wrapAs(&tBuffer, *buffer);
status_t fnStatus;
status_t transStatus = toStatusT(mBase->attachBuffer(tBuffer,
@@ -1071,7 +1071,7 @@
int slot,
const QueueBufferInput& input,
QueueBufferOutput* output) {
- HGraphicBufferProducer::QueueBufferInput tInput;
+ HGraphicBufferProducer::QueueBufferInput tInput{};
native_handle_t* nh;
if (!wrapAs(&tInput, &nh, input)) {
ALOGE("H2BGraphicBufferProducer::queueBuffer - "
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index e401572..0db21a5 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -157,6 +157,9 @@
virtual status_t getDisplayStats(const sp<IBinder>& display,
DisplayStatInfo* stats) = 0;
+ /* returns display viewport information of the given display */
+ virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) = 0;
+
/* indicates which of the configurations returned by getDisplayInfo is
* currently active */
virtual int getActiveConfig(const sp<IBinder>& display) = 0;
@@ -175,10 +178,22 @@
* This function will fail if there is a secure window on screen.
*/
virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
- Rotation rotation = eRotateNone) = 0;
+ bool& outCapturedSecureLayers, Rect sourceCrop,
+ uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ,
+ int32_t maxLayerZ, bool useIdentityTransform,
+ Rotation rotation = eRotateNone,
+ bool captureSecureLayers = false) = 0;
+ virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
+ Rect sourceCrop,
+ uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ,
+ int32_t maxLayerZ, bool useIdentityTransform,
+ Rotation rotation = eRotateNone,
+ bool captureSecureLayers = false) {
+ bool ignored;
+ return captureScreen(display, outBuffer, ignored, sourceCrop, reqWidth, reqHeight, minLayerZ,
+ maxLayerZ, useIdentityTransform, rotation, captureSecureLayers);
+ }
/**
* Capture a subtree of the layer hierarchy, potentially ignoring the root node.
*/
@@ -250,7 +265,8 @@
ENABLE_VSYNC_INJECTIONS,
INJECT_VSYNC,
GET_LAYER_DEBUG_INFO,
- CREATE_SCOPED_CONNECTION
+ CREATE_SCOPED_CONNECTION,
+ GET_DISPLAY_VIEWPORT
};
virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 377fe68..49bb687 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -79,6 +79,9 @@
static status_t getDisplayInfo(const sp<IBinder>& display,
DisplayInfo* info);
+ // Get the display viewport for the given display
+ static status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport);
+
// Get the index of the current active configuration (relative to the list
// returned by getDisplayInfo)
static int getActiveConfig(const sp<IBinder>& display);
@@ -312,6 +315,11 @@
static status_t capture(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth,
uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ,
bool useIdentityTransform, uint32_t rotation,
+ bool captureSecureLayers, sp<GraphicBuffer>* outBuffer,
+ bool& outCapturedSecureLayers);
+ static status_t capture(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth,
+ uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ,
+ bool useIdentityTransform, uint32_t rotation,
sp<GraphicBuffer>* outBuffer);
static status_t captureLayers(const sp<IBinder>& layerHandle, Rect sourceCrop, float frameScale,
sp<GraphicBuffer>* outBuffer);
diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h
index bd987dd..38de299 100644
--- a/libs/gui/include/gui/SurfaceControl.h
+++ b/libs/gui/include/gui/SurfaceControl.h
@@ -76,6 +76,10 @@
sp<SurfaceComposerClient> getClient() const;
+ SurfaceControl(const sp<SurfaceComposerClient>& client,
+ const sp<IBinder>& handle,
+ const sp<IGraphicBufferProducer>& gbp,
+ bool owned);
private:
// can't be copied
SurfaceControl& operator = (SurfaceControl& rhs);
@@ -84,12 +88,6 @@
friend class SurfaceComposerClient;
friend class Surface;
- SurfaceControl(
- const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& handle,
- const sp<IGraphicBufferProducer>& gbp,
- bool owned);
-
~SurfaceControl();
sp<Surface> generateSurfaceLocked() const;
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 2c02ba6..04686e5 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -126,7 +126,7 @@
}
// This test probably doesn't belong here.
-TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) {
+TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersDontSucceed) {
sp<ANativeWindow> anw(mSurface);
// Verify the screenshot works with no protected buffers.
@@ -134,7 +134,8 @@
sp<IBinder> display(sf->getBuiltInDisplay(
ISurfaceComposer::eDisplayIdMain));
sp<GraphicBuffer> outBuffer;
- ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(),
+ bool ignored;
+ ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, ignored, Rect(),
64, 64, 0, 0x7fffffff, false));
ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(),
@@ -165,7 +166,7 @@
&buf));
ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1));
}
- ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(),
+ ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, ignored, Rect(),
64, 64, 0, 0x7fffffff, false));
}
@@ -581,6 +582,9 @@
Vector<DisplayInfo>* /*configs*/) override { return NO_ERROR; }
status_t getDisplayStats(const sp<IBinder>& /*display*/,
DisplayStatInfo* /*stats*/) override { return NO_ERROR; }
+ status_t getDisplayViewport(const sp<IBinder>& /*display*/, Rect* /*outViewport*/) override {
+ return NO_ERROR;
+ }
int getActiveConfig(const sp<IBinder>& /*display*/) override { return 0; }
status_t setActiveConfig(const sp<IBinder>& /*display*/, int /*id*/)
override {
@@ -598,10 +602,12 @@
ColorMode /*colorMode*/) override { return NO_ERROR; }
status_t captureScreen(const sp<IBinder>& /*display*/,
sp<GraphicBuffer>* /*outBuffer*/,
+ bool& /* outCapturedSecureLayers */,
Rect /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/,
int32_t /*minLayerZ*/, int32_t /*maxLayerZ*/,
bool /*useIdentityTransform*/,
- Rotation /*rotation*/) override { return NO_ERROR; }
+ Rotation /*rotation*/,
+ bool /*captureSecureLayers*/) override { return NO_ERROR; }
virtual status_t captureLayers(const sp<IBinder>& /*parentHandle*/,
sp<GraphicBuffer>* /*outBuffer*/, const Rect& /*sourceCrop*/,
float /*frameScale*/, bool /*childrenOnly*/) override {
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index aa0bf17..03f593f 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -96,6 +96,106 @@
return sizeof(Header);
}
+/**
+ * There could be non-zero bytes in-between InputMessage fields. Force-initialize the entire
+ * memory to zero, then only copy the valid bytes on a per-field basis.
+ */
+void InputMessage::getSanitizedCopy(InputMessage* msg) const {
+ memset(msg, 0, sizeof(*msg));
+
+ // Write the header
+ msg->header.type = header.type;
+
+ // Write the body
+ switch(header.type) {
+ case InputMessage::TYPE_KEY: {
+ // uint32_t seq
+ msg->body.key.seq = body.key.seq;
+ // nsecs_t eventTime
+ msg->body.key.eventTime = body.key.eventTime;
+ // int32_t deviceId
+ msg->body.key.deviceId = body.key.deviceId;
+ // int32_t source
+ msg->body.key.source = body.key.source;
+ // int32_t displayId
+ msg->body.key.displayId = body.key.displayId;
+ // int32_t action
+ msg->body.key.action = body.key.action;
+ // int32_t flags
+ msg->body.key.flags = body.key.flags;
+ // int32_t keyCode
+ msg->body.key.keyCode = body.key.keyCode;
+ // int32_t scanCode
+ msg->body.key.scanCode = body.key.scanCode;
+ // int32_t metaState
+ msg->body.key.metaState = body.key.metaState;
+ // int32_t repeatCount
+ msg->body.key.repeatCount = body.key.repeatCount;
+ // nsecs_t downTime
+ msg->body.key.downTime = body.key.downTime;
+ break;
+ }
+ case InputMessage::TYPE_MOTION: {
+ // uint32_t seq
+ msg->body.motion.seq = body.motion.seq;
+ // nsecs_t eventTime
+ msg->body.motion.eventTime = body.motion.eventTime;
+ // int32_t deviceId
+ msg->body.motion.deviceId = body.motion.deviceId;
+ // int32_t source
+ msg->body.motion.source = body.motion.source;
+ // int32_t displayId
+ msg->body.motion.displayId = body.motion.displayId;
+ // int32_t action
+ msg->body.motion.action = body.motion.action;
+ // int32_t actionButton
+ msg->body.motion.actionButton = body.motion.actionButton;
+ // int32_t flags
+ msg->body.motion.flags = body.motion.flags;
+ // int32_t metaState
+ msg->body.motion.metaState = body.motion.metaState;
+ // int32_t buttonState
+ msg->body.motion.buttonState = body.motion.buttonState;
+ // int32_t edgeFlags
+ msg->body.motion.edgeFlags = body.motion.edgeFlags;
+ // nsecs_t downTime
+ msg->body.motion.downTime = body.motion.downTime;
+ // float xOffset
+ msg->body.motion.xOffset = body.motion.xOffset;
+ // float yOffset
+ msg->body.motion.yOffset = body.motion.yOffset;
+ // float xPrecision
+ msg->body.motion.xPrecision = body.motion.xPrecision;
+ // float yPrecision
+ msg->body.motion.yPrecision = body.motion.yPrecision;
+ // uint32_t pointerCount
+ msg->body.motion.pointerCount = body.motion.pointerCount;
+ //struct Pointer pointers[MAX_POINTERS]
+ for (size_t i = 0; i < body.motion.pointerCount; i++) {
+ // PointerProperties properties
+ msg->body.motion.pointers[i].properties.id = body.motion.pointers[i].properties.id;
+ msg->body.motion.pointers[i].properties.toolType =
+ body.motion.pointers[i].properties.toolType,
+ // PointerCoords coords
+ msg->body.motion.pointers[i].coords.bits = body.motion.pointers[i].coords.bits;
+ const uint32_t count = BitSet64::count(body.motion.pointers[i].coords.bits);
+ memcpy(&msg->body.motion.pointers[i].coords.values[0],
+ &body.motion.pointers[i].coords.values[0],
+ count * (sizeof(body.motion.pointers[i].coords.values[0])));
+ }
+ break;
+ }
+ case InputMessage::TYPE_FINISHED: {
+ msg->body.finished.seq = body.finished.seq;
+ msg->body.finished.handled = body.finished.handled;
+ break;
+ }
+ default: {
+ LOG_FATAL("Unexpected message type %i", header.type);
+ break;
+ }
+ }
+}
// --- InputChannel ---
@@ -149,10 +249,12 @@
}
status_t InputChannel::sendMessage(const InputMessage* msg) {
- size_t msgLength = msg->size();
+ const size_t msgLength = msg->size();
+ InputMessage cleanMsg;
+ msg->getSanitizedCopy(&cleanMsg);
ssize_t nWrite;
do {
- nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
+ nWrite = ::send(mFd, &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
} while (nWrite == -1 && errno == EINTR);
if (nWrite < 0) {
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index c07a812..c70ace0 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -325,8 +325,8 @@
eventTime = event->getHistoricalEventTime(h);
for (size_t i = 0; i < pointerCount; i++) {
uint32_t index = pointerIndex[i];
- positions[index].x = event->getHistoricalRawX(i, h);
- positions[index].y = event->getHistoricalRawY(i, h);
+ positions[index].x = event->getHistoricalX(i, h);
+ positions[index].y = event->getHistoricalY(i, h);
}
addMovement(eventTime, idBits, positions);
}
@@ -334,8 +334,8 @@
eventTime = event->getEventTime();
for (size_t i = 0; i < pointerCount; i++) {
uint32_t index = pointerIndex[i];
- positions[index].x = event->getRawX(i);
- positions[index].y = event->getRawY(i);
+ positions[index].x = event->getX(i);
+ positions[index].y = event->getY(i);
}
addMovement(eventTime, idBits, positions);
}
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index d19f3b8..12a6782 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -65,6 +65,9 @@
CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 76);
CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 80);
CHECK_OFFSET(InputMessage::Body::Motion, pointers, 88);
+
+ CHECK_OFFSET(InputMessage::Body::Finished, seq, 0);
+ CHECK_OFFSET(InputMessage::Body::Finished, handled, 4);
}
} // namespace android
diff --git a/libs/sensor/Sensor.cpp b/libs/sensor/Sensor.cpp
index a0e368c..2383516 100644
--- a/libs/sensor/Sensor.cpp
+++ b/libs/sensor/Sensor.cpp
@@ -562,7 +562,8 @@
uint32_t len = static_cast<uint32_t>(string8.length());
FlattenableUtils::write(buffer, size, len);
memcpy(static_cast<char*>(buffer), string8.string(), len);
- FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len));
+ FlattenableUtils::advance(buffer, size, len);
+ size -= FlattenableUtils::align<4>(buffer);
}
bool Sensor::unflattenString8(void const*& buffer, size_t& size, String8& outputString8) {
diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp
index b9ae524..c97e4da 100644
--- a/libs/sensor/SensorManager.cpp
+++ b/libs/sensor/SensorManager.cpp
@@ -94,7 +94,7 @@
SensorManager::SensorManager(const String16& opPackageName)
: mSensorList(0), mOpPackageName(opPackageName), mDirectConnectionHandle(1) {
- // okay we're not locked here, but it's not needed during construction
+ Mutex::Autolock _l(mLock);
assertStateLocked();
}
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 254038b..7670ac6 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -377,6 +377,10 @@
status_t GraphicBuffer::unflatten(
void const*& buffer, size_t& size, int const*& fds, size_t& count) {
+ if (size < 12 * sizeof(int)) {
+ android_errorWriteLog(0x534e4554, "114223584");
+ return NO_MEMORY;
+ }
int const* buf = static_cast<int const*>(buffer);
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 9a449fa..91e017d 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -105,36 +105,6 @@
return value ? "true" : "false";
}
-static std::string motionActionToString(int32_t action) {
- // Convert MotionEvent action to string
- switch(action & AMOTION_EVENT_ACTION_MASK) {
- case AMOTION_EVENT_ACTION_DOWN:
- return "DOWN";
- case AMOTION_EVENT_ACTION_MOVE:
- return "MOVE";
- case AMOTION_EVENT_ACTION_UP:
- return "UP";
- case AMOTION_EVENT_ACTION_POINTER_DOWN:
- return "POINTER_DOWN";
- case AMOTION_EVENT_ACTION_POINTER_UP:
- return "POINTER_UP";
- }
- return StringPrintf("%" PRId32, action);
-}
-
-static std::string keyActionToString(int32_t action) {
- // Convert KeyEvent action to string
- switch(action) {
- case AKEY_EVENT_ACTION_DOWN:
- return "DOWN";
- case AKEY_EVENT_ACTION_UP:
- return "UP";
- case AKEY_EVENT_ACTION_MULTIPLE:
- return "MULTIPLE";
- }
- return StringPrintf("%" PRId32, action);
-}
-
static inline int32_t getMotionEventActionPointerIndex(int32_t action) {
return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
>> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
@@ -4006,11 +3976,7 @@
}
void InputDispatcher::KeyEntry::appendDescription(std::string& msg) const {
- msg += StringPrintf("KeyEvent(deviceId=%d, source=0x%08x, action=%s, "
- "flags=0x%08x, keyCode=%d, scanCode=%d, metaState=0x%08x, "
- "repeatCount=%d), policyFlags=0x%08x",
- deviceId, source, keyActionToString(action).c_str(), flags, keyCode,
- scanCode, metaState, repeatCount, policyFlags);
+ msg += StringPrintf("KeyEvent");
}
void InputDispatcher::KeyEntry::recycle() {
@@ -4051,19 +4017,7 @@
}
void InputDispatcher::MotionEntry::appendDescription(std::string& msg) const {
- msg += StringPrintf("MotionEvent(deviceId=%d, source=0x%08x, action=%s, actionButton=0x%08x, "
- "flags=0x%08x, metaState=0x%08x, buttonState=0x%08x, "
- "edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, displayId=%d, pointers=[",
- deviceId, source, motionActionToString(action).c_str(), actionButton, flags, metaState,
- buttonState, edgeFlags, xPrecision, yPrecision, displayId);
- for (uint32_t i = 0; i < pointerCount; i++) {
- if (i) {
- msg += ", ";
- }
- msg += StringPrintf("%d: (%.1f, %.1f)", pointerProperties[i].id,
- pointerCoords[i].getX(), pointerCoords[i].getY());
- }
- msg += StringPrintf("]), policyFlags=0x%08x", policyFlags);
+ msg += StringPrintf("MotionEvent");
}
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index e0cd8a0..0b7e850 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -3089,6 +3089,7 @@
InputMapper(device),
mSource(0), mDeviceMode(DEVICE_MODE_DISABLED),
mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0),
+ mPhysicalWidth(-1), mPhysicalHeight(-1), mPhysicalLeft(0), mPhysicalTop(0),
mSurfaceOrientation(DISPLAY_ORIENTATION_0) {
}
@@ -3596,6 +3597,11 @@
break;
}
+ mPhysicalWidth = naturalPhysicalWidth;
+ mPhysicalHeight = naturalPhysicalHeight;
+ mPhysicalLeft = naturalPhysicalLeft;
+ mPhysicalTop = naturalPhysicalTop;
+
mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth;
@@ -3604,6 +3610,11 @@
mSurfaceOrientation = mParameters.orientationAware ?
mViewport.orientation : DISPLAY_ORIENTATION_0;
} else {
+ mPhysicalWidth = rawWidth;
+ mPhysicalHeight = rawHeight;
+ mPhysicalLeft = 0;
+ mPhysicalTop = 0;
+
mSurfaceWidth = rawWidth;
mSurfaceHeight = rawHeight;
mSurfaceLeft = 0;
@@ -3914,6 +3925,10 @@
dump += StringPrintf(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
dump += StringPrintf(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
dump += StringPrintf(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
+ dump += StringPrintf(INDENT3 "PhysicalWidth: %dpx\n", mPhysicalWidth);
+ dump += StringPrintf(INDENT3 "PhysicalHeight: %dpx\n", mPhysicalHeight);
+ dump += StringPrintf(INDENT3 "PhysicalLeft: %d\n", mPhysicalLeft);
+ dump += StringPrintf(INDENT3 "PhysicalTop: %d\n", mPhysicalTop);
dump += StringPrintf(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
}
@@ -5118,10 +5133,10 @@
}
break;
case DISPLAY_ORIENTATION_180:
- x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;
+ x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale;
y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
- left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
- right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
+ left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale;
+ right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
orientation -= M_PI;
@@ -5130,10 +5145,10 @@
}
break;
case DISPLAY_ORIENTATION_270:
- x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
+ x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale;
y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
- right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
+ left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale;
+ right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
orientation += M_PI_2;
@@ -6531,8 +6546,12 @@
}
bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
+ const float scaledX = x * mXScale;
+ const float scaledY = y * mYScale;
return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue
- && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue;
+ && scaledX >= mPhysicalLeft && scaledX <= mPhysicalLeft + mPhysicalWidth
+ && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue
+ && scaledY >= mPhysicalTop && scaledY <= mPhysicalTop + mPhysicalHeight;
}
const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index cef3212..2f98e69 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -1517,13 +1517,21 @@
// in the natural orientation.
// The surface origin specifies how the surface coordinates should be translated
// to align with the logical display coordinate space.
- // The orientation may be different from the viewport orientation as it specifies
- // the rotation of the surface coordinates required to produce the viewport's
- // requested orientation, so it will depend on whether the device is orientation aware.
int32_t mSurfaceWidth;
int32_t mSurfaceHeight;
int32_t mSurfaceLeft;
int32_t mSurfaceTop;
+
+ // Similar to the surface coordinates, but in the raw display coordinate space rather than in
+ // the logical coordinate space.
+ int32_t mPhysicalWidth;
+ int32_t mPhysicalHeight;
+ int32_t mPhysicalLeft;
+ int32_t mPhysicalTop;
+
+ // The orientation may be different from the viewport orientation as it specifies
+ // the rotation of the surface coordinates required to produce the viewport's
+ // requested orientation, so it will depend on whether the device is orientation aware.
int32_t mSurfaceOrientation;
// Translation and scaling factors, orientation-independent.
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index c2bb6ad..320e11f 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -27,6 +27,7 @@
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.2",
"android.hardware.power@1.0",
+ "android.hardware.power@1.3",
"libbase",
"libbinder",
"libbufferhubqueue",
@@ -69,6 +70,7 @@
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.2",
+ "android.hardware.power@1.3",
"libhidlbase",
"libhidltransport",
"libhwbinder",
@@ -96,6 +98,7 @@
"DisplayHardware/HWC2.cpp",
"DisplayHardware/HWComposer.cpp",
"DisplayHardware/HWComposerBufferCache.cpp",
+ "DisplayHardware/PowerAdvisor.cpp",
"DisplayHardware/VirtualDisplaySurface.cpp",
"DispSync.cpp",
"Effects/Daltonizer.cpp",
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index fda7906..7ac1432 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -63,7 +63,7 @@
mRefreshPending(false) {
ALOGV("Creating Layer %s", name.string());
- mFlinger->getRenderEngine().genTextures(1, &mTextureName);
+ mTextureName = mFlinger->getNewTexture();
mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName);
if (flags & ISurfaceComposerClient::eNonPremultiplied) mPremultipliedAlpha = false;
@@ -701,13 +701,19 @@
}
void BufferLayer::onFirstRef() {
+ Layer::onFirstRef();
+
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer, true);
mProducer = new MonitoredProducer(producer, mFlinger, this);
- mConsumer = new BufferLayerConsumer(consumer,
- mFlinger->getRenderEngine(), mTextureName, this);
+ {
+ // Grab the SF state lock during this since it's the only safe way to access RenderEngine
+ Mutex::Autolock lock(mFlinger->mStateLock);
+ mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName,
+ this);
+ }
mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
mConsumer->setContentsChangedListener(this);
mConsumer->setName(mName);
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 077469b..6b54a14 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -106,19 +106,18 @@
}
}
}
-sp<Layer> Client::getLayerUser(const sp<IBinder>& handle) const
+
+bool Client::isAttached(const sp<IBinder>& handle) const
{
Mutex::Autolock _l(mLock);
sp<Layer> lbc;
wp<Layer> layer(mLayers.valueFor(handle));
if (layer != 0) {
- lbc = layer.promote();
- ALOGE_IF(lbc==0, "getLayerUser(name=%p) is dead", handle.get());
+ return true;
}
- return lbc;
+ return false;
}
-
status_t Client::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
@@ -144,74 +143,20 @@
return BnSurfaceComposerClient::onTransact(code, data, reply, flags);
}
-
status_t Client::createSurface(
const String8& name,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
const sp<IBinder>& parentHandle, int32_t windowType, int32_t ownerUid,
sp<IBinder>* handle,
- sp<IGraphicBufferProducer>* gbp)
-{
- sp<Layer> parent = nullptr;
- if (parentHandle != nullptr) {
- auto layerHandle = reinterpret_cast<Layer::Handle*>(parentHandle.get());
- parent = layerHandle->owner.promote();
- if (parent == nullptr) {
- return NAME_NOT_FOUND;
- }
+ sp<IGraphicBufferProducer>* gbp) {
+ bool parentDied;
+ sp<Layer> parentLayer;
+ if (!parentHandle) parentLayer = getParentLayer(&parentDied);
+ if (parentHandle == nullptr && parentDied) {
+ return NAME_NOT_FOUND;
}
- if (parent == nullptr) {
- bool parentDied;
- parent = getParentLayer(&parentDied);
- // If we had a parent, but it died, we've lost all
- // our capabilities.
- if (parentDied) {
- return NAME_NOT_FOUND;
- }
- }
-
- /*
- * createSurface must be called from the GL thread so that it can
- * have access to the GL context.
- */
- class MessageCreateLayer : public MessageBase {
- SurfaceFlinger* flinger;
- Client* client;
- sp<IBinder>* handle;
- sp<IGraphicBufferProducer>* gbp;
- status_t result;
- const String8& name;
- uint32_t w, h;
- PixelFormat format;
- uint32_t flags;
- sp<Layer>* parent;
- int32_t windowType;
- int32_t ownerUid;
- public:
- MessageCreateLayer(SurfaceFlinger* flinger,
- const String8& name, Client* client,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
- sp<IBinder>* handle, int32_t windowType, int32_t ownerUid,
- sp<IGraphicBufferProducer>* gbp,
- sp<Layer>* parent)
- : flinger(flinger), client(client),
- handle(handle), gbp(gbp), result(NO_ERROR),
- name(name), w(w), h(h), format(format), flags(flags),
- parent(parent), windowType(windowType), ownerUid(ownerUid) {
- }
- status_t getResult() const { return result; }
- virtual bool handler() {
- result = flinger->createLayer(name, client, w, h, format, flags,
- windowType, ownerUid, handle, gbp, parent);
- return true;
- }
- };
-
- sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
- name, this, w, h, format, flags, handle,
- windowType, ownerUid, gbp, &parent);
- mFlinger->postMessageSync(msg);
- return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
+ return mFlinger->createLayer(name, this, w, h, format, flags, windowType,
+ ownerUid, handle, gbp, parentHandle, parentLayer);
}
status_t Client::destroySurface(const sp<IBinder>& handle) {
@@ -219,21 +164,11 @@
}
status_t Client::clearLayerFrameStats(const sp<IBinder>& handle) const {
- sp<Layer> layer = getLayerUser(handle);
- if (layer == nullptr) {
- return NAME_NOT_FOUND;
- }
- layer->clearFrameStats();
- return NO_ERROR;
+ return mFlinger->clearLayerFrameStats(this, handle);
}
status_t Client::getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const {
- sp<Layer> layer = getLayerUser(handle);
- if (layer == nullptr) {
- return NAME_NOT_FOUND;
- }
- layer->getFrameStats(outStats);
- return NO_ERROR;
+ return mFlinger->getLayerFrameStats(this, handle, outStats);
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h
index 49437ed..c8da528 100644
--- a/services/surfaceflinger/Client.h
+++ b/services/surfaceflinger/Client.h
@@ -49,7 +49,7 @@
void detachLayer(const Layer* layer);
- sp<Layer> getLayerUser(const sp<IBinder>& handle) const;
+ bool isAttached (const sp<IBinder>& handle) const;
void updateParent(const sp<Layer>& parentLayer);
@@ -58,7 +58,7 @@
virtual status_t createSurface(
const String8& name,
uint32_t w, uint32_t h,PixelFormat format, uint32_t flags,
- const sp<IBinder>& parent, int32_t windowType, int32_t ownerUid,
+ const sp<IBinder>& parentHandle, int32_t windowType, int32_t ownerUid,
sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp);
diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h
index 543f60a..b352b96 100644
--- a/services/surfaceflinger/ContainerLayer.h
+++ b/services/surfaceflinger/ContainerLayer.h
@@ -35,6 +35,8 @@
bool isVisible() const override;
void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override;
+
+ bool isCreatedFromMainThread() const override { return true; }
};
} // namespace android
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index 7acbd11..37dc27d 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -222,7 +222,13 @@
// Pretend that the last time this event was handled at the same frame but with the
// new offset to allow for a seamless offset change without double-firing or
// skipping.
- listener.mLastEventTime -= (oldPhase - phase);
+ nsecs_t diff = oldPhase - phase;
+ if (diff > mPeriod / 2) {
+ diff -= mPeriod;
+ } else if (diff < -mPeriod / 2) {
+ diff += mPeriod;
+ }
+ listener.mLastEventTime -= diff;
mCond.signal();
return NO_ERROR;
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 6c3bd91..1262209 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -341,21 +341,24 @@
: DisplayRenderArea(device, device->getBounds(), device->getHeight(), device->getWidth(),
rotation) {}
DisplayRenderArea(const sp<const DisplayDevice> device, Rect sourceCrop, uint32_t reqHeight,
- uint32_t reqWidth, ISurfaceComposer::Rotation rotation)
+ uint32_t reqWidth, ISurfaceComposer::Rotation rotation,
+ bool allowSecureLayers = true)
: RenderArea(reqHeight, reqWidth, CaptureFill::OPAQUE, rotation), mDevice(device),
- mSourceCrop(sourceCrop) {}
+ mSourceCrop(sourceCrop),
+ mAllowSecureLayers(allowSecureLayers) {}
const Transform& getTransform() const override { return mDevice->getTransform(); }
Rect getBounds() const override { return mDevice->getBounds(); }
int getHeight() const override { return mDevice->getHeight(); }
int getWidth() const override { return mDevice->getWidth(); }
- bool isSecure() const override { return mDevice->isSecure(); }
+ bool isSecure() const override { return mAllowSecureLayers && mDevice->isSecure(); }
bool needsFiltering() const override { return mDevice->needsFiltering(); }
Rect getSourceCrop() const override { return mSourceCrop; }
private:
const sp<const DisplayDevice> mDevice;
const Rect mSourceCrop;
+ const bool mAllowSecureLayers;
};
}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 61758b6..1a60c83 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -138,7 +138,7 @@
}
auto display = std::make_unique<Display>(
- *mComposer.get(), mCapabilities, displayId, DisplayType::Virtual);
+ *mComposer.get(), mPowerAdvisor, mCapabilities, displayId, DisplayType::Virtual);
display->setConnected(true);
*outDisplay = display.get();
mDisplays.emplace(displayId, std::move(display));
@@ -177,7 +177,7 @@
}
auto newDisplay = std::make_unique<Display>(
- *mComposer.get(), mCapabilities, displayId, displayType);
+ *mComposer.get(), mPowerAdvisor, mCapabilities, displayId, displayType);
newDisplay->setConnected(true);
mDisplays.emplace(displayId, std::move(newDisplay));
} else if (connection == Connection::Disconnected) {
@@ -219,10 +219,11 @@
// Display methods
-Display::Display(android::Hwc2::Composer& composer,
+Display::Display(android::Hwc2::Composer& composer, android::Hwc2::PowerAdvisor& advisor,
const std::unordered_set<Capability>& capabilities, hwc2_display_t id,
DisplayType type)
: mComposer(composer),
+ mPowerAdvisor(advisor),
mCapabilities(capabilities),
mId(id),
mIsConnected(false),
@@ -605,6 +606,12 @@
Error Display::setColorMode(ColorMode mode, RenderIntent renderIntent)
{
+ // When the color mode is switched to DISPLAY_P3, we want to boost the GPU frequency
+ // so that GPU composition can finish in time. When color mode is switched from
+ // DISPLAY_P3, we want to reset GPU frequency.
+ const bool expensiveRenderingExpected = (mode == ColorMode::DISPLAY_P3);
+ mPowerAdvisor.setExpensiveRenderingExpected(mId, expensiveRenderingExpected);
+
auto intError = mComposer.setColorMode(mId, mode, renderIntent);
return static_cast<Error>(intError);
}
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 29d7a47..e423167 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -37,6 +37,8 @@
#include <unordered_set>
#include <vector>
+#include "PowerAdvisor.h"
+
namespace android {
class Fence;
class FloatRect;
@@ -119,6 +121,7 @@
std::unique_ptr<android::Hwc2::Composer> mComposer;
std::unordered_set<Capability> mCapabilities;
std::unordered_map<hwc2_display_t, std::unique_ptr<Display>> mDisplays;
+ android::Hwc2::impl::PowerAdvisor mPowerAdvisor;
bool mRegisteredCallback = false;
};
@@ -126,7 +129,8 @@
class Display
{
public:
- Display(android::Hwc2::Composer& composer, const std::unordered_set<Capability>& capabilities,
+ Display(android::Hwc2::Composer& composer, android::Hwc2::PowerAdvisor& advisor,
+ const std::unordered_set<Capability>& capabilities,
hwc2_display_t id, DisplayType type);
~Display();
@@ -282,6 +286,7 @@
// this HWC2::Display, so these references are guaranteed to be valid for
// the lifetime of this object.
android::Hwc2::Composer& mComposer;
+ android::Hwc2::PowerAdvisor& mPowerAdvisor;
const std::unordered_set<Capability>& mCapabilities;
hwc2_display_t mId;
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
new file mode 100644
index 0000000..12bbae2
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "PowerAdvisor"
+
+#include <cinttypes>
+
+#include <utils/Log.h>
+#include <utils/Mutex.h>
+
+#include "PowerAdvisor.h"
+
+namespace android {
+namespace Hwc2 {
+
+PowerAdvisor::~PowerAdvisor() = default;
+
+namespace impl {
+
+namespace V1_0 = android::hardware::power::V1_0;
+using V1_3::PowerHint;
+
+PowerAdvisor::~PowerAdvisor() = default;
+
+PowerAdvisor::PowerAdvisor() = default;
+
+void PowerAdvisor::setExpensiveRenderingExpected(hwc2_display_t displayId, bool expected) {
+ if (expected) {
+ mExpensiveDisplays.insert(displayId);
+ } else {
+ mExpensiveDisplays.erase(displayId);
+ }
+
+ const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
+ if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
+ const sp<V1_3::IPower> powerHal = getPowerHal();
+ if (powerHal == nullptr) {
+ return;
+ }
+ auto ret = powerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING,
+ expectsExpensiveRendering);
+ // If Power HAL 1.3 was available previously but now fails,
+ // it may restart, so attempt to reconnect next time
+ if (!ret.isOk()) {
+ mReconnectPowerHal = true;
+ return;
+ }
+ mNotifiedExpensiveRendering = expectsExpensiveRendering;
+ }
+}
+
+sp<V1_3::IPower> PowerAdvisor::getPowerHal() {
+ static sp<V1_3::IPower> sPowerHal_1_3 = nullptr;
+ static bool sHasPowerHal_1_3 = true;
+
+ if (mReconnectPowerHal) {
+ sPowerHal_1_3 = nullptr;
+ mReconnectPowerHal = false;
+ }
+
+ // Power HAL 1.3 is not guaranteed to be available, thus we need to query
+ // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
+ // Power HAL 1.0 is always available, thus if we fail to query it, it means
+ // Power HAL is not available temporarily and we should retry later. However,
+ // if Power HAL 1.0 is available and we can't cast it to Power HAL 1.3,
+ // it means Power HAL 1.3 is not available at all, so we should stop trying.
+ if (sHasPowerHal_1_3 && sPowerHal_1_3 == nullptr) {
+ sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
+ if (powerHal_1_0 != nullptr) {
+ // Try to cast to Power HAL 1.3
+ sPowerHal_1_3 = V1_3::IPower::castFrom(powerHal_1_0);
+ if (sPowerHal_1_3 == nullptr) {
+ ALOGW("No Power HAL 1.3 service in system");
+ sHasPowerHal_1_3 = false;
+ } else {
+ ALOGI("Loaded Power HAL 1.3 service");
+ }
+ }
+ }
+ return sPowerHal_1_3;
+}
+
+} // namespace impl
+} // namespace Hwc2
+} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
new file mode 100644
index 0000000..573a1a9
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include <android/hardware/power/1.3/IPower.h>
+#include <utils/StrongPointer.h>
+
+#include <unordered_set>
+
+namespace android {
+namespace Hwc2 {
+
+class PowerAdvisor {
+public:
+ virtual ~PowerAdvisor();
+
+ virtual void setExpensiveRenderingExpected(hwc2_display_t displayId, bool expected) = 0;
+};
+
+namespace impl {
+
+namespace V1_3 = android::hardware::power::V1_3;
+
+// PowerAdvisor is a wrapper around IPower HAL which takes into account the
+// full state of the system when sending out power hints to things like the GPU.
+class PowerAdvisor final : public Hwc2::PowerAdvisor {
+public:
+ PowerAdvisor();
+ ~PowerAdvisor() override;
+
+ void setExpensiveRenderingExpected(hwc2_display_t displayId, bool expected) override;
+
+private:
+ sp<V1_3::IPower> getPowerHal();
+
+ std::unordered_set<hwc2_display_t> mExpensiveDisplays;
+ bool mNotifiedExpensiveRendering = false;
+ bool mReconnectPowerHal = false;
+};
+
+} // namespace impl
+} // namespace Hwc2
+} // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2595ec1..a062aa1 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -130,17 +130,26 @@
// drawing state & current state are identical
mDrawingState = mCurrentState;
- const auto& hwc = flinger->getHwComposer();
- const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY);
- nsecs_t displayPeriod = activeConfig->getVsyncPeriod();
- mFrameTracker.setDisplayRefreshPeriod(displayPeriod);
-
CompositorTiming compositorTiming;
flinger->getCompositorTiming(&compositorTiming);
mFrameEventHistory.initializeCompositorTiming(compositorTiming);
}
-void Layer::onFirstRef() {}
+void Layer::onFirstRef() NO_THREAD_SAFETY_ANALYSIS {
+ if (!isCreatedFromMainThread()) {
+ // Grab the SF state lock during this since it's the only way to safely access HWC
+ mFlinger->mStateLock.lock();
+ }
+
+ const auto& hwc = mFlinger->getHwComposer();
+ const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY);
+ nsecs_t displayPeriod = activeConfig->getVsyncPeriod();
+ mFrameTracker.setDisplayRefreshPeriod(displayPeriod);
+
+ if (!isCreatedFromMainThread()) {
+ mFlinger->mStateLock.unlock();
+ }
+}
Layer::~Layer() {
sp<Client> c(mClientRef.promote());
@@ -170,7 +179,6 @@
void Layer::onRemovedFromCurrentState() {
// the layer is removed from SF mCurrentState to mLayersPendingRemoval
-
mPendingRemoval = true;
if (mCurrentState.zOrderRelativeOf != nullptr) {
@@ -212,6 +220,11 @@
sp<IBinder> Layer::getHandle() {
Mutex::Autolock _l(mLock);
+ if (mGetHandleCalled) {
+ ALOGE("Get handle called twice" );
+ return nullptr;
+ }
+ mGetHandleCalled = true;
return new Handle(mFlinger, this);
}
@@ -345,20 +358,25 @@
win.intersect(s.crop, &win);
}
- Rect bounds = win;
const auto& p = mDrawingParent.promote();
+ FloatRect floatWin = win.toFloatRect();
+ FloatRect parentBounds = floatWin;
if (p != nullptr) {
- // Look in computeScreenBounds recursive call for explanation of
- // why we pass false here.
- bounds = p->computeScreenBounds(false /* reduceTransparentRegion */);
+ // We pass an empty Region here for reasons mirroring that of the case described in
+ // the computeScreenBounds reduceTransparentRegion=false case.
+ parentBounds = p->computeBounds(Region());
}
- Transform t = getTransform();
+ Transform t = s.active.transform;
- FloatRect floatWin = win.toFloatRect();
- if (p != nullptr) {
+
+ if (p != nullptr || !s.finalCrop.isEmpty()) {
floatWin = t.transform(floatWin);
- floatWin = floatWin.intersect(bounds.toFloatRect());
+ floatWin = floatWin.intersect(parentBounds);
+
+ if (!s.finalCrop.isEmpty()) {
+ floatWin = floatWin.intersect(s.finalCrop.toFloatRect());
+ }
floatWin = t.inverse().transform(floatWin);
}
@@ -1249,7 +1267,15 @@
return true;
}
-bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) {
+bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix,
+ bool allowNonRectPreservingTransforms) {
+ Transform t;
+ t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
+
+ if (!allowNonRectPreservingTransforms && !t.preserveRects()) {
+ ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER ignored");
+ return false;
+ }
mCurrentState.sequence++;
mCurrentState.requested.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
mCurrentState.modified = true;
@@ -1974,6 +2000,16 @@
layerInfo->set_refresh_pending(isBufferLatched());
layerInfo->set_window_type(state.type);
layerInfo->set_app_id(state.appId);
+ layerInfo->set_curr_frame(mCurrentFrameNumber);
+
+ for (const auto& pendingState : mPendingStates) {
+ auto barrierLayer = pendingState.barrierLayer.promote();
+ if (barrierLayer != nullptr) {
+ BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer();
+ barrierLayerProto->set_id(barrierLayer->sequence);
+ barrierLayerProto->set_frame_number(pendingState.frameNumber);
+ }
+ }
}
void Layer::writeToProto(LayerProto* layerInfo, int32_t hwcId) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 34811fb..bd483e8 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -258,7 +258,7 @@
// 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);
+ bool setMatrix(const layer_state_t::matrix22_t& matrix, bool allowNonRectPreservingTransforms);
// This second set of geometry attributes are controlled by
// setGeometryAppliesWithResize, and their default mode is to be
@@ -360,6 +360,11 @@
*/
virtual bool isFixedSize() const { return true; }
+ // Most layers aren't created from the main thread, and therefore need to
+ // grab the SF state lock to access HWC, but ContainerLayer does, so we need
+ // to avoid grabbing the lock again to avoid deadlock
+ virtual bool isCreatedFromMainThread() const { return false; }
+
bool isPendingRemoval() const { return mPendingRemoval; }
@@ -699,6 +704,8 @@
wp<Layer> owner;
};
+ // Creates a new handle each time, so we only expect
+ // this to be called once.
sp<IBinder> getHandle();
const String8& getName() const;
virtual void notifyAvailableFrames() {}
@@ -803,6 +810,7 @@
const LayerVector::Visitor& visitor);
LayerVector makeChildrenTraversalList(LayerVector::StateSet stateSet,
const std::vector<Layer*>& layersInTree);
+ bool mGetHandleCalled = false;
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp
index 09414fd..c218e4d 100644
--- a/services/surfaceflinger/RenderEngine/Description.cpp
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -51,10 +51,6 @@
mProjectionMatrix = mtx;
}
-void Description::setSaturationMatrix(const mat4& mtx) {
- mSaturationMatrix = mtx;
-}
-
void Description::setColorMatrix(const mat4& mtx) {
mColorMatrix = mtx;
}
@@ -82,11 +78,6 @@
return mColorMatrix != identity;
}
-bool Description::hasSaturationMatrix() const {
- const mat4 identity;
- return mSaturationMatrix != identity;
-}
-
const mat4& Description::getColorMatrix() const {
return mColorMatrix;
}
diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h
index 06eaf35..6ebb340 100644
--- a/services/surfaceflinger/RenderEngine/Description.h
+++ b/services/surfaceflinger/RenderEngine/Description.h
@@ -42,14 +42,12 @@
void disableTexture();
void setColor(const half4& color);
void setProjectionMatrix(const mat4& mtx);
- void setSaturationMatrix(const mat4& mtx);
void setColorMatrix(const mat4& mtx);
void setInputTransformMatrix(const mat3& matrix);
void setOutputTransformMatrix(const mat4& matrix);
bool hasInputTransformMatrix() const;
bool hasOutputTransformMatrix() const;
bool hasColorMatrix() const;
- bool hasSaturationMatrix() const;
const mat4& getColorMatrix() const;
void setY410BT2020(bool enable);
@@ -92,7 +90,6 @@
// projection matrix
mat4 mProjectionMatrix;
mat4 mColorMatrix;
- mat4 mSaturationMatrix;
mat3 mInputTransformMatrix;
mat4 mOutputTransformMatrix;
};
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 0048000..744a70c 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -267,10 +267,6 @@
mState.setColorMatrix(colorTransform);
}
-void GLES20RenderEngine::setSaturationMatrix(const mat4& saturationMatrix) {
- mState.setSaturationMatrix(saturationMatrix);
-}
-
void GLES20RenderEngine::disableTexturing() {
mState.disableTexture();
}
@@ -383,11 +379,10 @@
// we need to convert the RGB value to linear space and convert it back when:
// - there is a color matrix that is not an identity matrix, or
- // - there is a saturation matrix that is not an identity matrix, or
// - there is an output transform matrix that is not an identity matrix, or
// - the input transfer function doesn't match the output transfer function.
- if (wideColorState.hasColorMatrix() || wideColorState.hasSaturationMatrix() ||
- wideColorState.hasOutputTransformMatrix() || inputTransfer != outputTransfer) {
+ if (wideColorState.hasColorMatrix() || wideColorState.hasOutputTransformMatrix() ||
+ inputTransfer != outputTransfer) {
switch (inputTransfer) {
case Dataspace::TRANSFER_ST2084:
wideColorState.setInputTransferFunction(Description::TransferFunction::ST2084);
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index de5761b..cc8eb1d 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -81,7 +81,6 @@
virtual void setupLayerBlackedOut();
virtual void setupFillWithColor(float r, float g, float b, float a);
virtual void setupColorTransform(const mat4& colorTransform);
- virtual void setSaturationMatrix(const mat4& saturationMatrix);
virtual void disableTexturing();
virtual void disableBlending();
diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp
index 95adaca..fe536f0 100644
--- a/services/surfaceflinger/RenderEngine/Program.cpp
+++ b/services/surfaceflinger/RenderEngine/Program.cpp
@@ -135,22 +135,13 @@
glUniform4fv(mColorLoc, 1, color);
}
if (mInputTransformMatrixLoc >= 0) {
- // If the input transform matrix is not identity matrix, we want to merge
- // the saturation matrix with input transform matrix so that the saturation
- // matrix is applied at the correct stage.
- mat4 inputTransformMatrix = mat4(desc.mInputTransformMatrix) * desc.mSaturationMatrix;
+ mat4 inputTransformMatrix = mat4(desc.mInputTransformMatrix);
glUniformMatrix4fv(mInputTransformMatrixLoc, 1, GL_FALSE, inputTransformMatrix.asArray());
}
if (mOutputTransformMatrixLoc >= 0) {
// The output transform matrix and color matrix can be combined as one matrix
// that is applied right before applying OETF.
mat4 outputTransformMatrix = desc.mColorMatrix * desc.mOutputTransformMatrix;
- // If there is no input transform matrix, we want to merge the saturation
- // matrix with output transform matrix to avoid extra matrix multiplication
- // in shader.
- if (mInputTransformMatrixLoc < 0) {
- outputTransformMatrix *= desc.mSaturationMatrix;
- }
glUniformMatrix4fv(mOutputTransformMatrixLoc, 1, GL_FALSE,
outputTransformMatrix.asArray());
}
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index 796901a..46402d5 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -149,8 +149,7 @@
description.hasInputTransformMatrix() ?
Key::INPUT_TRANSFORM_MATRIX_ON : Key::INPUT_TRANSFORM_MATRIX_OFF)
.set(Key::Key::OUTPUT_TRANSFORM_MATRIX_MASK,
- description.hasOutputTransformMatrix() || description.hasColorMatrix() ||
- (!description.hasInputTransformMatrix() && description.hasSaturationMatrix()) ?
+ description.hasOutputTransformMatrix() || description.hasColorMatrix() ?
Key::OUTPUT_TRANSFORM_MATRIX_ON : Key::OUTPUT_TRANSFORM_MATRIX_OFF);
needs.set(Key::Y410_BT2020_MASK,
@@ -221,7 +220,7 @@
const highp float c2 = (2413.0 / 4096.0) * 32.0;
const highp float c3 = (2392.0 / 4096.0) * 32.0;
- highp vec3 tmp = pow(color, 1.0 / vec3(m2));
+ highp vec3 tmp = pow(clamp(color, 0.0, 1.0), 1.0 / vec3(m2));
tmp = max(tmp - c1, 0.0) / (c2 - c3 * tmp);
return pow(tmp, 1.0 / vec3(m1));
}
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 1196216..1786155 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -113,7 +113,6 @@
virtual void setupFillWithColor(float r, float g, float b, float a) = 0;
virtual void setupColorTransform(const mat4& /* colorTransform */) = 0;
- virtual void setSaturationMatrix(const mat4& /* saturationMatrix */) = 0;
virtual void disableTexturing() = 0;
virtual void disableBlending() = 0;
@@ -228,7 +227,6 @@
void checkErrors() const override;
void setupColorTransform(const mat4& /* colorTransform */) override {}
- void setSaturationMatrix(const mat4& /* saturationMatrix */) override {}
// internal to RenderEngine
EGLDisplay getEGLDisplay() const;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 87baf8c..2c7f8c4 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -37,6 +37,7 @@
#include <dvr/vr_flinger.h>
+#include <ui/ColorSpace.h>
#include <ui/DebugUtils.h>
#include <ui/DisplayInfo.h>
#include <ui/DisplayStatInfo.h>
@@ -222,6 +223,7 @@
mVisibleRegionsDirty(false),
mGeometryInvalid(false),
mAnimCompositionPending(false),
+ mBootStage(BootStage::BOOTLOADER),
mDebugRegion(0),
mDebugDDMS(0),
mDebugDisableHWC(0),
@@ -230,7 +232,6 @@
mLastSwapBufferTime(0),
mDebugInTransaction(0),
mLastTransactionTime(0),
- mBootFinished(false),
mForceFullDamage(false),
mPrimaryDispSync("PrimaryDispSync"),
mPrimaryHWVsyncEnabled(false),
@@ -331,11 +332,26 @@
auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize));
mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize;
- property_get("debug.sf.early_phase_offset_ns", value, "0");
- const int earlyWakeupOffsetOffsetNs = atoi(value);
- ALOGI_IF(earlyWakeupOffsetOffsetNs != 0, "Enabling separate early offset");
- mVsyncModulator.setPhaseOffsets(sfVsyncPhaseOffsetNs - earlyWakeupOffsetOffsetNs,
- sfVsyncPhaseOffsetNs);
+ property_get("debug.sf.early_phase_offset_ns", value, "-1");
+ const int earlySfOffsetNs = atoi(value);
+
+ property_get("debug.sf.early_gl_phase_offset_ns", value, "-1");
+ const int earlyGlSfOffsetNs = atoi(value);
+
+ property_get("debug.sf.early_app_phase_offset_ns", value, "-1");
+ const int earlyAppOffsetNs = atoi(value);
+
+ property_get("debug.sf.early_gl_app_phase_offset_ns", value, "-1");
+ const int earlyGlAppOffsetNs = atoi(value);
+
+ const VSyncModulator::Offsets earlyOffsets =
+ {earlySfOffsetNs != -1 ? earlySfOffsetNs : sfVsyncPhaseOffsetNs,
+ earlyAppOffsetNs != -1 ? earlyAppOffsetNs : vsyncPhaseOffsetNs};
+ const VSyncModulator::Offsets earlyGlOffsets =
+ {earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs : sfVsyncPhaseOffsetNs,
+ earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs : vsyncPhaseOffsetNs};
+ mVsyncModulator.setPhaseOffsets(earlyOffsets, earlyGlOffsets,
+ {sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs});
// We should be reading 'persist.sys.sf.color_saturation' here
// but since /data may be encrypted, we need to wait until after vold
@@ -482,10 +498,32 @@
sp<LambdaMessage> readProperties = new LambdaMessage([&]() {
readPersistentProperties();
+ mBootStage = BootStage::FINISHED;
});
postMessageAsync(readProperties);
}
+uint32_t SurfaceFlinger::getNewTexture() {
+ {
+ std::lock_guard lock(mTexturePoolMutex);
+ if (!mTexturePool.empty()) {
+ uint32_t name = mTexturePool.back();
+ mTexturePool.pop_back();
+ ATRACE_INT("TexturePoolSize", mTexturePool.size());
+ return name;
+ }
+
+ // The pool was too small, so increase it for the future
+ ++mTexturePoolSize;
+ }
+
+ // The pool was empty, so we need to get a new texture name directly using a
+ // blocking call to the main thread
+ uint32_t name = 0;
+ postMessageSync(new LambdaMessage([&]() { getRenderEngine().genTextures(1, &name); }));
+ return name;
+}
+
void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
class MessageDestroyGLTexture : public MessageBase {
RE::RenderEngine& engine;
@@ -662,7 +700,7 @@
},
"sfEventThread");
mEventQueue->setEventThread(mSFEventThread.get());
- mVsyncModulator.setEventThread(mSFEventThread.get());
+ mVsyncModulator.setEventThreads(mSFEventThread.get(), mEventThread.get());
// Get a RenderEngine for the given display / config (can't fail)
getBE().mRenderEngine =
@@ -732,9 +770,24 @@
ALOGE("Run StartPropertySetThread failed!");
}
- mLegacySrgbSaturationMatrix = getBE().mHwc->getDataspaceSaturationMatrix(HWC_DISPLAY_PRIMARY,
+ // This is a hack. Per definition of getDataspaceSaturationMatrix, the returned matrix
+ // is used to saturate legacy sRGB content. However, to make sure the same color under
+ // Display P3 will be saturated to the same color, we intentionally break the API spec
+ // and apply this saturation matrix on Display P3 content. Unless the risk of applying
+ // such saturation matrix on Display P3 is understood fully, the API should always return
+ // identify matrix.
+ mEnhancedSaturationMatrix = getBE().mHwc->getDataspaceSaturationMatrix(HWC_DISPLAY_PRIMARY,
Dataspace::SRGB_LINEAR);
+ // we will apply this on Display P3.
+ if (mEnhancedSaturationMatrix != mat4()) {
+ ColorSpace srgb(ColorSpace::sRGB());
+ ColorSpace displayP3(ColorSpace::DisplayP3());
+ mat4 srgbToP3 = mat4(ColorSpaceConnector(srgb, displayP3).getTransform());
+ mat4 p3ToSrgb = mat4(ColorSpaceConnector(displayP3, srgb).getTransform());
+ mEnhancedSaturationMatrix = srgbToP3 * mEnhancedSaturationMatrix * p3ToSrgb;
+ }
+
ALOGV("Done initializing");
}
@@ -928,6 +981,21 @@
return NO_ERROR;
}
+status_t SurfaceFlinger::getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) {
+ if (outViewport == nullptr || display.get() == nullptr) {
+ return BAD_VALUE;
+ }
+
+ sp<const DisplayDevice> device(getDisplayDevice(display));
+ if (device == nullptr) {
+ return BAD_VALUE;
+ }
+
+ *outViewport = device->getViewport();
+
+ return NO_ERROR;
+}
+
int SurfaceFlinger::getActiveConfig(const sp<IBinder>& display) {
if (display == nullptr) {
ALOGE("%s : display is nullptr", __func__);
@@ -1496,7 +1564,7 @@
bool refreshNeeded = handleMessageTransaction();
refreshNeeded |= handleMessageInvalidate();
refreshNeeded |= mRepaintEverything;
- if (refreshNeeded) {
+ if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) {
// Signal a refresh if a transaction modified the window state,
// a new buffer was latched, or if HWC has requested a full
// repaint
@@ -1809,6 +1877,17 @@
getBE().mTotalTime += elapsedTime;
}
getBE().mLastSwapTime = currentTime;
+
+ {
+ std::lock_guard lock(mTexturePoolMutex);
+ const size_t refillCount = mTexturePoolSize - mTexturePool.size();
+ if (refillCount > 0) {
+ const size_t offset = mTexturePool.size();
+ mTexturePool.resize(mTexturePoolSize);
+ getRenderEngine().genTextures(refillCount, mTexturePool.data() + offset);
+ ATRACE_INT("TexturePoolSize", mTexturePool.size());
+ }
+ }
}
void SurfaceFlinger::rebuildLayerStacks() {
@@ -2116,11 +2195,15 @@
displayDevice->onSwapBuffersCompleted();
displayDevice->makeCurrent();
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+ sp<Fence> releaseFence = Fence::NO_FENCE;
+
// The layer buffer from the previous frame (if any) is released
// by HWC only when the release fence from this frame (if any) is
// signaled. Always get the release fence from HWC first.
auto hwcLayer = layer->getHwcLayer(hwcId);
- sp<Fence> releaseFence = getBE().mHwc->getLayerReleaseFence(hwcId, hwcLayer);
+ if (hwcId >= 0) {
+ releaseFence = getBE().mHwc->getLayerReleaseFence(hwcId, hwcLayer);
+ }
// If the layer was client composited in the previous frame, we
// need to merge with the previous client target acquire fence.
@@ -2267,8 +2350,10 @@
const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) {
bool hasWideColorGamut = false;
std::unordered_map<ColorMode, std::vector<RenderIntent>> hwcColorModes;
+ HdrCapabilities hdrCapabilities;
+ int32_t supportedPerFrameMetadata = 0;
- if (hasWideColorDisplay) {
+ if (hasWideColorDisplay && hwcId >= 0) {
std::vector<ColorMode> modes = getHwComposer().getColorModes(hwcId);
for (ColorMode colorMode : modes) {
switch (colorMode) {
@@ -2287,8 +2372,10 @@
}
}
- HdrCapabilities hdrCapabilities;
- getHwComposer().getHdrCapabilities(hwcId, &hdrCapabilities);
+ if (hwcId >= 0) {
+ getHwComposer().getHdrCapabilities(hwcId, &hdrCapabilities);
+ supportedPerFrameMetadata = getHwComposer().getSupportedPerFrameMetadata(hwcId);
+ }
auto nativeWindowSurface = mCreateNativeWindowSurface(producer);
auto nativeWindow = nativeWindowSurface->getNativeWindow();
@@ -2322,8 +2409,7 @@
new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow,
dispSurface, std::move(renderSurface), displayWidth, displayHeight,
hasWideColorGamut, hdrCapabilities,
- getHwComposer().getSupportedPerFrameMetadata(hwcId),
- hwcColorModes, initialPowerMode);
+ supportedPerFrameMetadata, hwcColorModes, initialPowerMode);
if (maxFrameBufferAcquiredBuffers >= 3) {
nativeWindowSurface->preallocateBuffers();
@@ -2855,6 +2941,12 @@
signalLayerUpdate();
}
+ // enter boot animation on first buffer latch
+ if (CC_UNLIKELY(mBootStage == BootStage::BOOTLOADER && newDataLatched)) {
+ ALOGI("Enter boot animation");
+ mBootStage = BootStage::BOOTANIMATION;
+ }
+
// Only continue with the refresh if there is actually new work to do
return !mLayersWithQueuedFrames.empty() && newDataLatched;
}
@@ -2897,8 +2989,7 @@
ATRACE_INT("hasClientComposition", hasClientComposition);
bool applyColorMatrix = false;
- bool needsLegacyColorMatrix = false;
- bool legacyColorMatrixApplied = false;
+ bool needsEnhancedColorMatrix = false;
if (hasClientComposition) {
ALOGV("hasClientComposition");
@@ -2915,15 +3006,23 @@
const bool skipClientColorTransform = getBE().mHwc->hasCapability(
HWC2::Capability::SkipClientColorTransform);
+ mat4 colorMatrix;
applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform;
if (applyColorMatrix) {
- getRenderEngine().setupColorTransform(mDrawingState.colorMatrix);
+ colorMatrix = mDrawingState.colorMatrix;
}
- needsLegacyColorMatrix =
+ // The current enhanced saturation matrix is designed to enhance Display P3,
+ // thus we only apply this matrix when the render intent is not colorimetric
+ // and the output color space is Display P3.
+ needsEnhancedColorMatrix =
(displayDevice->getActiveRenderIntent() >= RenderIntent::ENHANCE &&
- outputDataspace != Dataspace::UNKNOWN &&
- outputDataspace != Dataspace::SRGB);
+ outputDataspace == Dataspace::DISPLAY_P3);
+ if (needsEnhancedColorMatrix) {
+ colorMatrix *= mEnhancedSaturationMatrix;
+ }
+
+ getRenderEngine().setupColorTransform(colorMatrix);
if (!displayDevice->makeCurrent()) {
ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
@@ -2961,22 +3060,17 @@
}
}
- if (displayDevice->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) {
- // just to be on the safe side, we don't set the
- // scissor on the main display. It should never be needed
- // anyways (though in theory it could since the API allows it).
- const Rect& bounds(displayDevice->getBounds());
- const Rect& scissor(displayDevice->getScissor());
- if (scissor != bounds) {
- // scissor doesn't match the screen's dimensions, so we
- // need to clear everything outside of it and enable
- // the GL scissor so we don't draw anything where we shouldn't
+ const Rect& bounds(displayDevice->getBounds());
+ const Rect& scissor(displayDevice->getScissor());
+ if (scissor != bounds) {
+ // scissor doesn't match the screen's dimensions, so we
+ // need to clear everything outside of it and enable
+ // the GL scissor so we don't draw anything where we shouldn't
- // enable scissor for this frame
- const uint32_t height = displayDevice->getHeight();
- getBE().mRenderEngine->setScissor(scissor.left, height - scissor.bottom,
- scissor.getWidth(), scissor.getHeight());
- }
+ // enable scissor for this frame
+ const uint32_t height = displayDevice->getHeight();
+ getBE().mRenderEngine->setScissor(scissor.left, height - scissor.bottom,
+ scissor.getWidth(), scissor.getHeight());
}
}
@@ -3010,17 +3104,6 @@
break;
}
case HWC2::Composition::Client: {
- // switch color matrices lazily
- if (layer->isLegacyDataSpace() && needsLegacyColorMatrix) {
- if (!legacyColorMatrixApplied) {
- getRenderEngine().setSaturationMatrix(mLegacySrgbSaturationMatrix);
- legacyColorMatrixApplied = true;
- }
- } else if (legacyColorMatrixApplied) {
- getRenderEngine().setSaturationMatrix(mat4());
- legacyColorMatrixApplied = false;
- }
-
layer->draw(renderArea, clip);
break;
}
@@ -3033,12 +3116,9 @@
firstLayer = false;
}
- if (applyColorMatrix) {
+ if (applyColorMatrix || needsEnhancedColorMatrix) {
getRenderEngine().setupColorTransform(mat4());
}
- if (needsLegacyColorMatrix && legacyColorMatrixApplied) {
- getRenderEngine().setSaturationMatrix(mat4());
- }
// disable scissor at the end of the frame
getBE().mRenderEngine->disableScissor();
@@ -3051,20 +3131,34 @@
engine.fillRegionWithColor(region, height, 0, 0, 0, 0);
}
-status_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
- const sp<IBinder>& handle,
- const sp<IGraphicBufferProducer>& gbc,
- const sp<Layer>& lbc,
- const sp<Layer>& parent)
-{
+status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
+ const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc,
+ const sp<IBinder>& parentHandle,
+ const sp<Layer>& parentLayer) {
// add this layer to the current state list
{
Mutex::Autolock _l(mStateLock);
+ sp<Layer> parent;
+
+ if (parentHandle != nullptr) {
+ parent = fromHandle(parentHandle);
+ if (parent == nullptr) {
+ return NAME_NOT_FOUND;
+ }
+ } else {
+ parent = parentLayer;
+ }
+
if (mNumLayers >= MAX_LAYERS) {
ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers,
MAX_LAYERS);
return NO_MEMORY;
}
+
+ auto [itr, inserted] = mLayersByLocalBinderToken.emplace(handle->localBinder(), lbc);
+ if (!inserted) {
+ ALOGE("-----------ERROR REGISTERING HANDLE, layer pair: handle is already a key");
+ }
if (parent == nullptr) {
mCurrentState.layersSortedByZ.add(lbc);
} else {
@@ -3093,6 +3187,23 @@
return NO_ERROR;
}
+status_t SurfaceFlinger::removeLayerFromMap(const wp<Layer>& layer) {
+ auto it = mLayersByLocalBinderToken.begin();
+ while (it != mLayersByLocalBinderToken.end()) {
+ if (it->second == layer) {
+ it = mLayersByLocalBinderToken.erase(it);
+ break;
+ } else {
+ it++;
+ }
+ }
+ if (it == mLayersByLocalBinderToken.end()) {
+ ALOGE("Failed to remove layer from mapping - could not find matching layer");
+ return BAD_VALUE;
+ }
+ return NO_ERROR;
+}
+
status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer, bool topLevelOnly) {
Mutex::Autolock _l(mStateLock);
return removeLayerLocked(mStateLock, layer, topLevelOnly);
@@ -3327,12 +3438,24 @@
return flags;
}
+bool callingThreadHasUnscopedSurfaceFlingerAccess() {
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+
+ if ((uid != AID_GRAPHICS && uid != AID_SYSTEM) &&
+ !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
+ return false;
+ }
+ return true;
+}
+
uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState) {
const layer_state_t& s = composerState.state;
sp<Client> client(static_cast<Client*>(composerState.client.get()));
- sp<Layer> layer(client->getLayerUser(s.surface));
- if (layer == nullptr) {
+ sp<Layer> layer = fromHandle(s.surface);
+ if (layer == nullptr || !(client->isAttached(s.surface))) {
return 0;
}
@@ -3408,7 +3531,22 @@
flags |= eTraversalNeeded;
}
if (what & layer_state_t::eMatrixChanged) {
- if (layer->setMatrix(s.matrix))
+ // TODO: b/109894387
+ //
+ // SurfaceFlinger's renderer is not prepared to handle cropping in the face of arbitrary
+ // rotation. To see the problem observe that if we have a square parent, and a child
+ // of the same size, then we rotate the child 45 degrees around it's center, the child
+ // must now be cropped to a non rectangular 8 sided region.
+ //
+ // Of course we can fix this in the future. For now, we are lucky, SurfaceControl is
+ // private API, and the WindowManager only uses rotation in one case, which is on a top
+ // level layer in which cropping is not an issue.
+ //
+ // However given that abuse of rotation matrices could lead to surfaces extending outside
+ // of cropped areas, we need to prevent non-root clients without permission ACCESS_SURFACE_FLINGER
+ // (a.k.a. everyone except WindowManager and tests) from setting non rectangle preserving
+ // transformations.
+ if (layer->setMatrix(s.matrix, callingThreadHasUnscopedSurfaceFlingerAccess()))
flags |= eTraversalNeeded;
}
if (what & layer_state_t::eTransparentRegionChanged) {
@@ -3492,8 +3630,8 @@
const layer_state_t& state = composerState.state;
sp<Client> client(static_cast<Client*>(composerState.client.get()));
- sp<Layer> layer(client->getLayerUser(state.surface));
- if (layer == nullptr) {
+ sp<Layer> layer = fromHandle(state.surface);
+ if (layer == nullptr || !(client->isAttached(state.surface))) {
return;
}
@@ -3507,13 +3645,12 @@
}
}
-status_t SurfaceFlinger::createLayer(
- const String8& name,
- const sp<Client>& client,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
- int32_t windowType, int32_t ownerUid, sp<IBinder>* handle,
- sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent)
-{
+status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w,
+ uint32_t h, PixelFormat format, uint32_t flags,
+ int32_t windowType, int32_t ownerUid, sp<IBinder>* handle,
+ sp<IGraphicBufferProducer>* gbp,
+ const sp<IBinder>& parentHandle,
+ const sp<Layer>& parentLayer) {
if (int32_t(w|h) < 0) {
ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
int(w), int(h));
@@ -3556,7 +3693,7 @@
layer->setInfo(windowType, ownerUid);
- result = addClientLayer(client, *handle, *gbp, layer, *parent);
+ result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer);
if (result != NO_ERROR) {
return result;
}
@@ -3574,10 +3711,13 @@
// Tack on our counter whether there is a hit or not, so everyone gets a tag
String8 uniqueName = name + "#" + String8(std::to_string(dupeCounter).c_str());
+ // Grab the state lock since we're accessing mCurrentState
+ Mutex::Autolock lock(mStateLock);
+
// Loop over layers until we're sure there is no matching name
while (matchFound) {
matchFound = false;
- mDrawingState.traverseInZOrder([&](Layer* layer) {
+ mCurrentState.traverseInZOrder([&](Layer* layer) {
if (layer->getName() == uniqueName) {
matchFound = true;
uniqueName = name + "#" + String8(std::to_string(++dupeCounter).c_str());
@@ -3626,14 +3766,35 @@
return NO_ERROR;
}
+status_t SurfaceFlinger::clearLayerFrameStats(const sp<const Client>& client, const sp<IBinder>& handle) {
+ Mutex::Autolock _l(mStateLock);
+ sp<Layer> layer = fromHandle(handle);
+ if (layer == nullptr || !(client->isAttached(handle))) {
+ return NAME_NOT_FOUND;
+ }
+ layer->clearFrameStats();
+ return NO_ERROR;
+}
+
+status_t SurfaceFlinger::getLayerFrameStats(const sp<const Client>& client, const sp<IBinder>& handle, FrameStats* outStats) {
+ Mutex::Autolock _l(mStateLock);
+ sp<Layer> layer = fromHandle(handle);
+ if (layer == nullptr || !(client->isAttached(handle))) {
+ return NAME_NOT_FOUND;
+ }
+ layer->getFrameStats(outStats);
+ return NO_ERROR;
+}
+
status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
{
+ Mutex::Autolock _l(mStateLock);
// called by a client when it wants to remove a Layer
status_t err = NO_ERROR;
- sp<Layer> l(client->getLayerUser(handle));
- if (l != nullptr) {
+ sp<Layer> l = fromHandle(handle);
+ if (l != nullptr || client->isAttached(handle)) {
mInterceptor->saveSurfaceDeletion(l);
- err = removeLayer(l);
+ err = removeLayerLocked(mStateLock, l);
ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
"error removing layer=%p (%s)", l.get(), strerror(-err));
}
@@ -3642,15 +3803,18 @@
status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer)
{
+ Mutex::Autolock _l(mStateLock);
// called by ~LayerCleaner() when all references to the IBinder (handle)
// are gone
sp<Layer> l = layer.promote();
if (l == nullptr) {
+ removeLayerFromMap(layer);
// The layer has already been removed, carry on
return NO_ERROR;
}
+ removeLayerFromMap(layer);
// If we have a parent, then we can continue to live as long as it does.
- return removeLayer(l, true);
+ return removeLayerLocked(mStateLock, l, true);
}
// ---------------------------------------------------------------------------
@@ -4207,9 +4371,22 @@
colorizer.bold(result);
result.append("DispSync configuration: ");
colorizer.reset(result);
- result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, early sf phase %" PRId64
- " ns, present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
- vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, mVsyncModulator.getEarlyPhaseOffset(),
+ const auto [sfEarlyOffset, appEarlyOffset] = mVsyncModulator.getEarlyOffsets();
+ const auto [sfEarlyGlOffset, appEarlyGlOffset] = mVsyncModulator.getEarlyGlOffsets();
+ result.appendFormat(
+ "app phase %" PRId64 " ns, "
+ "sf phase %" PRId64 " ns, "
+ "early app phase %" PRId64 " ns, "
+ "early sf phase %" PRId64 " ns, "
+ "early app gl phase %" PRId64 " ns, "
+ "early sf gl phase %" PRId64 " ns, "
+ "present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
+ vsyncPhaseOffsetNs,
+ sfVsyncPhaseOffsetNs,
+ appEarlyOffset,
+ sfEarlyOffset,
+ appEarlyGlOffset,
+ sfEarlyOffset,
dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod());
result.append("\n");
@@ -4295,6 +4472,12 @@
result.append("\n");
/*
+ * Tracing state
+ */
+ mTracing.dump(result);
+ result.append("\n");
+
+ /*
* HWC layer minidump
*/
for (size_t d = 0; d < mDisplays.size(); d++) {
@@ -4412,12 +4595,10 @@
case INJECT_VSYNC:
{
// codes that require permission check
- IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
- if ((uid != AID_GRAPHICS && uid != AID_SYSTEM) &&
- !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
- ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
+ if (!callingThreadHasUnscopedSurfaceFlingerAccess()) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d",
+ ipc->getCallingPid(), ipc->getCallingUid());
return PERMISSION_DENIED;
}
break;
@@ -4643,12 +4824,12 @@
case 1025: { // Set layer tracing
n = data.readInt32();
if (n) {
- ALOGV("LayerTracing enabled");
+ ALOGD("LayerTracing enabled");
mTracing.enable();
doTracing("tracing.enable");
reply->writeInt32(NO_ERROR);
} else {
- ALOGV("LayerTracing disabled");
+ ALOGD("LayerTracing disabled");
status_t err = mTracing.disable();
reply->writeInt32(err);
}
@@ -4705,11 +4886,13 @@
const int mApi;
};
-status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
+status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
+ sp<GraphicBuffer>* outBuffer, bool& outCapturedSecureLayers,
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
int32_t minLayerZ, int32_t maxLayerZ,
bool useIdentityTransform,
- ISurfaceComposer::Rotation rotation) {
+ ISurfaceComposer::Rotation rotation,
+ bool captureSecureLayers) {
ATRACE_CALL();
if (CC_UNLIKELY(display == 0)) return BAD_VALUE;
@@ -4717,11 +4900,23 @@
const sp<const DisplayDevice> device(getDisplayDeviceLocked(display));
if (CC_UNLIKELY(device == 0)) return BAD_VALUE;
- DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation);
+ const Rect& dispScissor = device->getScissor();
+ if (!dispScissor.isEmpty()) {
+ sourceCrop.set(dispScissor);
+ // adb shell screencap will default reqWidth and reqHeight to zeros.
+ if (reqWidth == 0 || reqHeight == 0) {
+ reqWidth = uint32_t(device->getViewport().width());
+ reqHeight = uint32_t(device->getViewport().height());
+ }
+ }
+
+ DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation,
+ captureSecureLayers);
auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this,
device, minLayerZ, maxLayerZ, std::placeholders::_1);
- return captureScreenCommon(renderArea, traverseLayers, outBuffer, useIdentityTransform);
+ return captureScreenCommon(renderArea, traverseLayers, outBuffer, useIdentityTransform,
+ outCapturedSecureLayers);
}
status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder,
@@ -4794,34 +4989,40 @@
const bool mChildrenOnly;
};
- auto layerHandle = reinterpret_cast<Layer::Handle*>(layerHandleBinder.get());
- auto parent = layerHandle->owner.promote();
-
- if (parent == nullptr || parent->isPendingRemoval()) {
- ALOGE("captureLayers called with a removed parent");
- return NAME_NOT_FOUND;
- }
-
- const int uid = IPCThreadState::self()->getCallingUid();
- const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
- if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) {
- ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
- return PERMISSION_DENIED;
- }
-
+ int reqWidth = 0;
+ int reqHeight = 0;
+ sp<Layer> parent;
Rect crop(sourceCrop);
- if (sourceCrop.width() <= 0) {
- crop.left = 0;
- crop.right = parent->getCurrentState().active.w;
- }
- if (sourceCrop.height() <= 0) {
- crop.top = 0;
- crop.bottom = parent->getCurrentState().active.h;
- }
+ {
+ Mutex::Autolock _l(mStateLock);
- int32_t reqWidth = crop.width() * frameScale;
- int32_t reqHeight = crop.height() * frameScale;
+ parent = fromHandle(layerHandleBinder);
+ if (parent == nullptr || parent->isPendingRemoval()) {
+ ALOGE("captureLayers called with an invalid or removed parent");
+ return NAME_NOT_FOUND;
+ }
+
+ const int uid = IPCThreadState::self()->getCallingUid();
+ const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
+ if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) {
+ ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
+ return PERMISSION_DENIED;
+ }
+
+ if (sourceCrop.width() <= 0) {
+ crop.left = 0;
+ crop.right = parent->getCurrentState().active.w;
+ }
+
+ if (sourceCrop.height() <= 0) {
+ crop.top = 0;
+ crop.bottom = parent->getCurrentState().active.h;
+ }
+
+ reqWidth = crop.width() * frameScale;
+ reqHeight = crop.height() * frameScale;
+ } // mStateLock
LayerRenderArea renderArea(this, parent, crop, reqWidth, reqHeight, childrenOnly);
@@ -4835,13 +5036,16 @@
visitor(layer);
});
};
- return captureScreenCommon(renderArea, traverseLayers, outBuffer, false);
+ bool outCapturedSecureLayers = false;
+ return captureScreenCommon(renderArea, traverseLayers, outBuffer, false,
+ outCapturedSecureLayers);
}
status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
sp<GraphicBuffer>* outBuffer,
- bool useIdentityTransform) {
+ bool useIdentityTransform,
+ bool& outCapturedSecureLayers) {
ATRACE_CALL();
renderArea.updateDimensions(mPrimaryDisplayOrientation);
@@ -4879,7 +5083,8 @@
Mutex::Autolock _l(mStateLock);
renderArea.render([&]() {
result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(),
- useIdentityTransform, forSystem, &fd);
+ useIdentityTransform, forSystem, &fd,
+ outCapturedSecureLayers);
});
}
@@ -5030,21 +5235,19 @@
status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
ANativeWindowBuffer* buffer,
- bool useIdentityTransform,
- bool forSystem,
- int* outSyncFd) {
+ bool useIdentityTransform, bool forSystem,
+ int* outSyncFd, bool& outCapturedSecureLayers) {
ATRACE_CALL();
- bool secureLayerIsVisible = false;
-
traverseLayers([&](Layer* layer) {
- secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && layer->isSecure());
+ outCapturedSecureLayers =
+ outCapturedSecureLayers || (layer->isVisible() && layer->isSecure());
});
// We allow the system server to take screenshots of secure layers for
// use in situations like the Screen-rotation animation and place
// the impetus on WindowManager to not persist them.
- if (secureLayerIsVisible && !forSystem) {
+ if (outCapturedSecureLayers && !forSystem) {
ALOGW("FB is protected: PERMISSION_DENIED");
return PERMISSION_DENIED;
}
@@ -5144,8 +5347,20 @@
}
}
-}; // namespace android
+sp<Layer> SurfaceFlinger::fromHandle(const sp<IBinder>& handle) {
+ BBinder *b = handle->localBinder();
+ if (b == nullptr) {
+ return nullptr;
+ }
+ auto it = mLayersByLocalBinderToken.find(b);
+ if (it != mLayersByLocalBinderToken.end()) {
+ auto ret = it->second.promote();
+ return ret;
+ }
+ return nullptr;
+}
+} // namespace android
#if defined(__gl_h_)
#error "don't include gl/gl.h in this file"
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8566b03..1f8c205 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -320,6 +320,10 @@
return getDefaultDisplayDeviceLocked();
}
+ // Obtains a name from the texture pool, or, if the pool is empty, posts a
+ // synchronous message to the main thread to obtain one on the fly
+ uint32_t getNewTexture();
+
// utility function to delete a texture on the main thread
void deleteTextureAsync(uint32_t texture);
@@ -343,6 +347,12 @@
int getPrimaryDisplayOrientation() const { return mPrimaryDisplayOrientation; }
+ status_t clearLayerFrameStats(const sp<const Client>& client, const sp<IBinder>& handle);
+
+ status_t getLayerFrameStats(const sp<const Client>& client, const sp<IBinder>& handle, FrameStats* outStats);
+
+ sp<Layer> fromHandle(const sp<IBinder>& handle) REQUIRES(mStateLock);
+
private:
friend class Client;
friend class DisplayEventConnection;
@@ -418,13 +428,15 @@
virtual sp<IDisplayEventConnection> createDisplayEventConnection(
ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp);
virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
+ bool& outCapturedSecureLayers,
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
- ISurfaceComposer::Rotation rotation);
+ ISurfaceComposer::Rotation rotation, bool captureSecureLayers);
virtual status_t captureLayers(const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
const Rect& sourceCrop, float frameScale, bool childrenOnly);
virtual status_t getDisplayStats(const sp<IBinder>& display,
DisplayStatInfo* stats);
+ virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport);
virtual status_t getDisplayConfigs(const sp<IBinder>& display,
Vector<DisplayInfo>* configs);
virtual int getActiveConfig(const sp<IBinder>& display);
@@ -515,17 +527,17 @@
uint32_t setTransactionFlags(uint32_t flags, VSyncModulator::TransactionStart transactionStart);
void commitTransaction();
bool containsAnyInvalidClientState(const Vector<ComposerState>& states);
- uint32_t setClientStateLocked(const ComposerState& composerState);
+ uint32_t setClientStateLocked(const ComposerState& composerState) REQUIRES(mStateLock);
uint32_t setDisplayStateLocked(const DisplayState& s);
- void setDestroyStateLocked(const ComposerState& composerState);
+ void setDestroyStateLocked(const ComposerState& composerState) REQUIRES(mStateLock);
/* ------------------------------------------------------------------------
* Layer management
*/
- status_t createLayer(const String8& name, const sp<Client>& client,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
- int32_t windowType, int32_t ownerUid, sp<IBinder>* handle,
- sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent);
+ status_t createLayer(const String8& name, const sp<Client>& client, uint32_t w, uint32_t h,
+ PixelFormat format, uint32_t flags, int32_t windowType, int32_t ownerUid,
+ sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp,
+ const sp<IBinder>& parentHandle, const sp<Layer>& parentLayer = nullptr);
status_t createBufferLayer(const sp<Client>& client, const String8& name,
uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
@@ -551,12 +563,13 @@
status_t removeLayer(const sp<Layer>& layer, bool topLevelOnly = false);
status_t removeLayerLocked(const Mutex&, const sp<Layer>& layer, bool topLevelOnly = false);
+ // remove layer from mapping
+ status_t removeLayerFromMap(const wp<Layer>& layer);
+
// add a layer to SurfaceFlinger
- status_t addClientLayer(const sp<Client>& client,
- const sp<IBinder>& handle,
- const sp<IGraphicBufferProducer>& gbc,
- const sp<Layer>& lbc,
- const sp<Layer>& parent);
+ status_t addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
+ const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc,
+ const sp<IBinder>& parentHandle, const sp<Layer>& parentLayer);
/* ------------------------------------------------------------------------
* Boot animation, on/off animations and screen capture
@@ -568,11 +581,11 @@
bool yswap, bool useIdentityTransform);
status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers,
sp<GraphicBuffer>* outBuffer,
- bool useIdentityTransform);
+ bool useIdentityTransform, bool& outCapturedSecureLayers);
status_t captureScreenImplLocked(const RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
ANativeWindowBuffer* buffer, bool useIdentityTransform,
- bool forSystem, int* outSyncFd);
+ bool forSystem, int* outSyncFd, bool& outCapturedSecureLayers);
void traverseLayersInDisplay(const sp<const DisplayDevice>& display, int32_t minLayerZ,
int32_t maxLayerZ, const LayerVector::Visitor& visitor);
@@ -808,6 +821,13 @@
sp<Fence> mPreviousPresentFence = Fence::NO_FENCE;
bool mHadClientComposition = false;
+ enum class BootStage {
+ BOOTLOADER,
+ BOOTANIMATION,
+ FINISHED,
+ };
+ BootStage mBootStage;
+
struct HotplugEvent {
hwc2_display_t display;
HWC2::Connection connection = HWC2::Connection::Invalid;
@@ -819,6 +839,9 @@
// it may be read from other threads with mStateLock held
DefaultKeyedVector< wp<IBinder>, sp<DisplayDevice> > mDisplays;
+ // protected by mStateLock
+ std::unordered_map<BBinder*, wp<Layer>> mLayersByLocalBinderToken;
+
// don't use a lock for these, we don't care
int mDebugRegion;
int mDebugDDMS;
@@ -828,7 +851,6 @@
nsecs_t mLastSwapBufferTime;
volatile nsecs_t mDebugInTransaction;
nsecs_t mLastTransactionTime;
- bool mBootFinished;
bool mForceFullDamage;
bool mPropagateBackpressure = true;
std::unique_ptr<SurfaceInterceptor> mInterceptor =
@@ -858,6 +880,13 @@
std::atomic<bool> mRefreshPending{false};
+ // We maintain a pool of pre-generated texture names to hand out to avoid
+ // layer creation needing to run on the main thread (which it would
+ // otherwise need to do to access RenderEngine).
+ std::mutex mTexturePoolMutex;
+ uint32_t mTexturePoolSize = 0;
+ std::vector<uint32_t> mTexturePool;
+
/* ------------------------------------------------------------------------
* Feature prototyping
*/
@@ -878,9 +907,9 @@
static bool useVrFlinger;
std::thread::id mMainThreadId;
- DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::MANAGED;
- // Applied on sRGB layers when the render intent is non-colorimetric.
- mat4 mLegacySrgbSaturationMatrix;
+ DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::ENHANCED;
+ // Applied on Display P3 layers when the render intent is non-colorimetric.
+ mat4 mEnhancedSaturationMatrix;
using CreateBufferQueueFunction =
std::function<void(sp<IGraphicBufferProducer>* /* outProducer */,
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
index f8c466e..67dcd06 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -27,52 +27,67 @@
namespace android {
void SurfaceTracing::enable() {
+ ATRACE_CALL();
+ std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+
if (mEnabled) {
return;
}
- ATRACE_CALL();
mEnabled = true;
- std::lock_guard<std::mutex> protoGuard(mTraceMutex);
- mTrace.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
- LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
+ mTrace = std::make_unique<LayersTraceFileProto>();
+ mTrace->set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
+ LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
}
status_t SurfaceTracing::disable() {
+ ATRACE_CALL();
+ std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+
if (!mEnabled) {
return NO_ERROR;
}
- ATRACE_CALL();
- std::lock_guard<std::mutex> protoGuard(mTraceMutex);
mEnabled = false;
status_t err(writeProtoFileLocked());
ALOGE_IF(err == PERMISSION_DENIED, "Could not save the proto file! Permission denied");
ALOGE_IF(err == NOT_ENOUGH_DATA, "Could not save the proto file! There are missing fields");
- mTrace.Clear();
+ mTrace.reset();
return err;
}
-bool SurfaceTracing::isEnabled() {
+bool SurfaceTracing::isEnabled() const {
+ std::lock_guard<std::mutex> protoGuard(mTraceMutex);
return mEnabled;
}
void SurfaceTracing::traceLayers(const char* where, LayersProto layers) {
std::lock_guard<std::mutex> protoGuard(mTraceMutex);
-
- LayersTraceProto* entry = mTrace.add_entry();
+ if (!mEnabled) {
+ return;
+ }
+ LayersTraceProto* entry = mTrace->add_entry();
entry->set_elapsed_realtime_nanos(elapsedRealtimeNano());
entry->set_where(where);
entry->mutable_layers()->Swap(&layers);
+
+ constexpr int maxBufferedEntryCount = 3600;
+ if (mTrace->entry_size() >= maxBufferedEntryCount) {
+ // TODO: flush buffered entries without disabling tracing
+ ALOGE("too many buffered frames; force disable tracing");
+ mEnabled = false;
+ writeProtoFileLocked();
+ mTrace.reset();
+ }
}
status_t SurfaceTracing::writeProtoFileLocked() {
ATRACE_CALL();
- if (!mTrace.IsInitialized()) {
+ if (!mTrace->IsInitialized()) {
return NOT_ENOUGH_DATA;
}
std::string output;
- if (!mTrace.SerializeToString(&output)) {
+ if (!mTrace->SerializeToString(&output)) {
return PERMISSION_DENIED;
}
if (!android::base::WriteStringToFile(output, mOutputFileName, true)) {
@@ -82,4 +97,11 @@
return NO_ERROR;
}
+void SurfaceTracing::dump(String8& result) const {
+ std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+
+ result.appendFormat("Tracing state: %s\n", mEnabled ? "enabled" : "disabled");
+ result.appendFormat(" number of entries: %d\n", mTrace ? mTrace->entry_size() : 0);
+}
+
} // namespace android
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
index 590ab96..fd8cb82 100644
--- a/services/surfaceflinger/SurfaceTracing.h
+++ b/services/surfaceflinger/SurfaceTracing.h
@@ -18,7 +18,9 @@
#include <layerproto/LayerProtoHeader.h>
#include <utils/Errors.h>
+#include <utils/String8.h>
+#include <memory>
#include <mutex>
using namespace android::surfaceflinger;
@@ -32,9 +34,10 @@
public:
void enable();
status_t disable();
- bool isEnabled();
+ bool isEnabled() const;
void traceLayers(const char* where, LayersProto);
+ void dump(String8& result) const;
private:
static constexpr auto DEFAULT_FILENAME = "/data/misc/wmtrace/layers_trace.pb";
@@ -43,8 +46,8 @@
bool mEnabled = false;
std::string mOutputFileName = DEFAULT_FILENAME;
- std::mutex mTraceMutex;
- LayersTraceFileProto mTrace;
+ mutable std::mutex mTraceMutex;
+ std::unique_ptr<LayersTraceFileProto> mTrace;
};
} // namespace android
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index d4f1e29..9c34aa7 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -277,6 +277,9 @@
std::lock_guard<std::mutex> lock(mMutex);
if (!timeStatsTracker.count(layerName)) return;
LayerRecord& layerRecord = timeStatsTracker[layerName];
+ if (layerRecord.waitData < 0 ||
+ layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
+ return;
TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
if (timeRecord.frameNumber == frameNumber) {
timeRecord.latchTime = latchTime;
@@ -294,6 +297,9 @@
std::lock_guard<std::mutex> lock(mMutex);
if (!timeStatsTracker.count(layerName)) return;
LayerRecord& layerRecord = timeStatsTracker[layerName];
+ if (layerRecord.waitData < 0 ||
+ layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
+ return;
TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
if (timeRecord.frameNumber == frameNumber) {
timeRecord.desiredTime = desiredTime;
@@ -311,6 +317,9 @@
std::lock_guard<std::mutex> lock(mMutex);
if (!timeStatsTracker.count(layerName)) return;
LayerRecord& layerRecord = timeStatsTracker[layerName];
+ if (layerRecord.waitData < 0 ||
+ layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
+ return;
TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
if (timeRecord.frameNumber == frameNumber) {
timeRecord.acquireTime = acquireTime;
@@ -328,6 +337,9 @@
std::lock_guard<std::mutex> lock(mMutex);
if (!timeStatsTracker.count(layerName)) return;
LayerRecord& layerRecord = timeStatsTracker[layerName];
+ if (layerRecord.waitData < 0 ||
+ layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
+ return;
TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
if (timeRecord.frameNumber == frameNumber) {
timeRecord.acquireFence = acquireFence;
@@ -345,6 +357,9 @@
std::lock_guard<std::mutex> lock(mMutex);
if (!timeStatsTracker.count(layerName)) return;
LayerRecord& layerRecord = timeStatsTracker[layerName];
+ if (layerRecord.waitData < 0 ||
+ layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
+ return;
TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
if (timeRecord.frameNumber == frameNumber) {
timeRecord.presentTime = presentTime;
@@ -366,6 +381,9 @@
std::lock_guard<std::mutex> lock(mMutex);
if (!timeStatsTracker.count(layerName)) return;
LayerRecord& layerRecord = timeStatsTracker[layerName];
+ if (layerRecord.waitData < 0 ||
+ layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
+ return;
TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
if (timeRecord.frameNumber == frameNumber) {
timeRecord.presentFence = presentFence;
diff --git a/services/surfaceflinger/VSyncModulator.h b/services/surfaceflinger/VSyncModulator.h
index d526313..e071a59 100644
--- a/services/surfaceflinger/VSyncModulator.h
+++ b/services/surfaceflinger/VSyncModulator.h
@@ -36,6 +36,11 @@
public:
+ struct Offsets {
+ nsecs_t sf;
+ nsecs_t app;
+ };
+
enum TransactionStart {
EARLY,
NORMAL
@@ -43,21 +48,32 @@
// Sets the phase offsets
//
- // early: the phase offset when waking up early. May be the same as late, in which case we don't
- // shift offsets.
- // late: the regular sf phase offset.
- void setPhaseOffsets(nsecs_t early, nsecs_t late) {
- mEarlyPhaseOffset = early;
- mLatePhaseOffset = late;
- mPhaseOffset = late;
+ // sfEarly: The phase offset when waking up SF early, which happens when marking a transaction
+ // as early. May be the same as late, in which case we don't shift offsets.
+ // sfEarlyGl: Like sfEarly, but only if we used GL composition. If we use both GL composition
+ // and the transaction was marked as early, we'll use sfEarly.
+ // sfLate: The regular SF vsync phase offset.
+ // appEarly: Like sfEarly, but for the app-vsync
+ // appEarlyGl: Like sfEarlyGl, but for the app-vsync.
+ // appLate: The regular app vsync phase offset.
+ void setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late) {
+ mEarlyOffsets = early;
+ mEarlyGlOffsets = earlyGl;
+ mLateOffsets = late;
+ mOffsets = late;
}
- nsecs_t getEarlyPhaseOffset() const {
- return mEarlyPhaseOffset;
+ Offsets getEarlyOffsets() const {
+ return mEarlyOffsets;
}
- void setEventThread(EventThread* eventThread) {
- mEventThread = eventThread;
+ Offsets getEarlyGlOffsets() const {
+ return mEarlyGlOffsets;
+ }
+
+ void setEventThreads(EventThread* sfEventThread, EventThread* appEventThread) {
+ mSfEventThread = sfEventThread;
+ mAppEventThread = appEventThread;
}
void setTransactionStart(TransactionStart transactionStart) {
@@ -71,63 +87,70 @@
return;
}
mTransactionStart = transactionStart;
- updatePhaseOffsets();
+ updateOffsets();
}
void onTransactionHandled() {
if (mTransactionStart == TransactionStart::NORMAL) return;
mTransactionStart = TransactionStart::NORMAL;
- updatePhaseOffsets();
+ updateOffsets();
}
void onRefreshed(bool usedRenderEngine) {
- bool updatePhaseOffsetsNeeded = false;
+ bool updateOffsetsNeeded = false;
if (mRemainingEarlyFrameCount > 0) {
mRemainingEarlyFrameCount--;
- updatePhaseOffsetsNeeded = true;
+ updateOffsetsNeeded = true;
}
if (usedRenderEngine != mLastFrameUsedRenderEngine) {
mLastFrameUsedRenderEngine = usedRenderEngine;
- updatePhaseOffsetsNeeded = true;
+ updateOffsetsNeeded = true;
}
- if (updatePhaseOffsetsNeeded) {
- updatePhaseOffsets();
+ if (updateOffsetsNeeded) {
+ updateOffsets();
}
}
private:
- void updatePhaseOffsets() {
+ void updateOffsets() {
+ const Offsets desired = getOffsets();
+ const Offsets current = mOffsets;
- // Do not change phase offsets if disabled.
- if (mEarlyPhaseOffset == mLatePhaseOffset) return;
+ bool changed = false;
+ if (desired.sf != current.sf) {
+ mSfEventThread->setPhaseOffset(desired.sf);
+ changed = true;
+ }
+ if (desired.app != current.app) {
+ mAppEventThread->setPhaseOffset(desired.app);
+ changed = true;
+ }
- if (shouldUseEarlyOffset()) {
- if (mPhaseOffset != mEarlyPhaseOffset) {
- if (mEventThread) {
- mEventThread->setPhaseOffset(mEarlyPhaseOffset);
- }
- mPhaseOffset = mEarlyPhaseOffset;
- }
- } else {
- if (mPhaseOffset != mLatePhaseOffset) {
- if (mEventThread) {
- mEventThread->setPhaseOffset(mLatePhaseOffset);
- }
- mPhaseOffset = mLatePhaseOffset;
- }
+ if (changed) {
+ mOffsets = desired;
}
}
- bool shouldUseEarlyOffset() {
- return mTransactionStart == TransactionStart::EARLY || mLastFrameUsedRenderEngine
- || mRemainingEarlyFrameCount > 0;
+ Offsets getOffsets() {
+ if (mTransactionStart == TransactionStart::EARLY || mRemainingEarlyFrameCount > 0) {
+ return mEarlyOffsets;
+ } else if (mLastFrameUsedRenderEngine) {
+ return mEarlyGlOffsets;
+ } else {
+ return mLateOffsets;
+ }
}
- nsecs_t mLatePhaseOffset = 0;
- nsecs_t mEarlyPhaseOffset = 0;
- EventThread* mEventThread = nullptr;
- std::atomic<nsecs_t> mPhaseOffset = 0;
+ Offsets mLateOffsets;
+ Offsets mEarlyOffsets;
+ Offsets mEarlyGlOffsets;
+
+ EventThread* mSfEventThread = nullptr;
+ EventThread* mAppEventThread = nullptr;
+
+ std::atomic<Offsets> mOffsets;
+
std::atomic<TransactionStart> mTransactionStart = TransactionStart::NORMAL;
std::atomic<bool> mLastFrameUsedRenderEngine = false;
std::atomic<int> mRemainingEarlyFrameCount = 0;
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index 77c6675..edf56ab 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -80,6 +80,10 @@
optional int32 hwc_composition_type = 35;
// If it's a buffer layer, indicate if the content is protected
optional bool is_protected = 36;
+ // Current frame number being rendered.
+ optional uint64 curr_frame = 37;
+ // A list of barriers that the layer is waiting to update state.
+ repeated BarrierLayerProto barrier_layer = 38;
}
message PositionProto {
@@ -131,3 +135,10 @@
optional float b = 3;
optional float a = 4;
}
+
+message BarrierLayerProto {
+ // layer id the barrier is waiting on.
+ optional int32 id = 1;
+ // frame number the barrier is waiting on.
+ optional uint64 frame_number = 2;
+}
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index 8255b41..b1ff522 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -102,7 +102,7 @@
// publish surface flinger
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
- IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
+ IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);
// publish GpuService
sp<GpuService> gpuservice = new GpuService();
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 322e8a0..2331dfd 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -18,7 +18,8 @@
tags: ["test"],
test_suites: ["device-tests"],
srcs: [
- "Stress_test.cpp",
+ "InvalidHandles_test.cpp",
+ "Stress_test.cpp",
"SurfaceInterceptor_test.cpp",
"Transaction_test.cpp",
],
diff --git a/services/surfaceflinger/tests/InvalidHandles_test.cpp b/services/surfaceflinger/tests/InvalidHandles_test.cpp
new file mode 100644
index 0000000..42d1f5a
--- /dev/null
+++ b/services/surfaceflinger/tests/InvalidHandles_test.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 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 <binder/Binder.h>
+
+#include <gtest/gtest.h>
+
+#include <gui/ISurfaceComposer.h>
+#include <gui/SurfaceComposerClient.h>
+#include <private/gui/ComposerService.h>
+#include <ui/Rect.h>
+
+namespace android {
+namespace {
+
+class NotALayer : public BBinder {};
+
+/**
+ * For all of these tests we make a SurfaceControl with an invalid layer handle
+ * and verify we aren't able to trick SurfaceFlinger.
+ */
+class InvalidHandleTest : public ::testing::Test {
+protected:
+ sp<SurfaceComposerClient> mScc;
+ sp<SurfaceControl> mNotSc;
+ void SetUp() override {
+ mScc = new SurfaceComposerClient;
+ ASSERT_EQ(NO_ERROR, mScc->initCheck());
+ mNotSc = makeNotSurfaceControl();
+ }
+
+ sp<SurfaceControl> makeNotSurfaceControl() {
+ return new SurfaceControl(mScc, new NotALayer(), nullptr, true);
+ }
+};
+
+TEST_F(InvalidHandleTest, createSurfaceInvalidHandle) {
+ auto notSc = makeNotSurfaceControl();
+ ASSERT_EQ(nullptr,
+ mScc->createSurface(String8("lolcats"), 19, 47, PIXEL_FORMAT_RGBA_8888, 0,
+ notSc.get())
+ .get());
+}
+
+TEST_F(InvalidHandleTest, captureLayersInvalidHandle) {
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ sp<GraphicBuffer> outBuffer;
+
+ ASSERT_EQ(NAME_NOT_FOUND,
+ sf->captureLayers(mNotSc->getHandle(), &outBuffer, Rect::EMPTY_RECT, 1.0f));
+}
+
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
index 36424b9..cca84e5 100644
--- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter
+++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
@@ -1,5 +1,5 @@
{
"presubmit": {
- "filter": "LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*"
+ "filter": "LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*:-CropLatchingTest.FinalCropLatchingBufferOldSize"
}
}
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 5108279..6ce2075 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -29,6 +29,7 @@
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
+#include <private/android_filesystem_config.h>
#include <ui/DisplayInfo.h>
#include <ui/Rect.h>
@@ -36,6 +37,8 @@
#include <math.h>
#include <math/vec3.h>
+#include <sys/types.h>
+#include <unistd.h>
namespace android {
@@ -68,6 +71,30 @@
}
// Fill a region with the specified color.
+void fillANativeWindowBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect,
+ const Color& color) {
+ Rect r(0, 0, buffer.width, buffer.height);
+ if (!r.intersect(rect, &r)) {
+ return;
+ }
+
+ int32_t width = r.right - r.left;
+ int32_t height = r.bottom - r.top;
+
+ for (int32_t row = 0; row < height; row++) {
+ uint8_t* dst =
+ static_cast<uint8_t*>(buffer.bits) + (buffer.stride * (r.top + row) + r.left) * 4;
+ for (int32_t column = 0; column < width; column++) {
+ dst[0] = color.r;
+ dst[1] = color.g;
+ dst[2] = color.b;
+ dst[3] = color.a;
+ dst += 4;
+ }
+ }
+}
+
+// Fill a region with the specified color.
void fillBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, const Color& color) {
int32_t x = rect.left;
int32_t y = rect.top;
@@ -319,6 +346,16 @@
return layer;
}
+ ANativeWindow_Buffer getBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) {
+ // wait for previous transactions (such as setSize) to complete
+ Transaction().apply(true);
+
+ ANativeWindow_Buffer buffer = {};
+ EXPECT_EQ(NO_ERROR, layer->getSurface()->lock(&buffer, nullptr));
+
+ return buffer;
+ }
+
ANativeWindow_Buffer getLayerBuffer(const sp<SurfaceControl>& layer) {
// wait for previous transactions (such as setSize) to complete
Transaction().apply(true);
@@ -336,6 +373,21 @@
waitForLayerBuffers();
}
+ void postBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) {
+ ASSERT_EQ(NO_ERROR, layer->getSurface()->unlockAndPost());
+
+ // wait for the newly posted buffer to be latched
+ waitForLayerBuffers();
+ }
+
+ virtual void fillBufferQueueLayerColor(const sp<SurfaceControl>& layer, const Color& color,
+ int32_t bufferWidth, int32_t bufferHeight) {
+ ANativeWindow_Buffer buffer;
+ ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer));
+ fillANativeWindowBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight), color);
+ postBufferQueueLayerBuffer(layer);
+ }
+
void fillLayerColor(const sp<SurfaceControl>& layer, const Color& color) {
ANativeWindow_Buffer buffer;
ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer));
@@ -847,6 +899,57 @@
false));
}
+/** RAII Wrapper around get/seteuid */
+class UIDFaker {
+ uid_t oldId;
+public:
+ UIDFaker(uid_t uid) {
+ oldId = geteuid();
+ seteuid(uid);
+ }
+ ~UIDFaker() {
+ seteuid(oldId);
+ }
+};
+
+TEST_F(LayerTransactionTest, SetFlagsSecureEUidSystem) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+
+ sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+ sp<GraphicBuffer> outBuffer;
+ Transaction()
+ .setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure)
+ .apply(true);
+
+ ASSERT_EQ(PERMISSION_DENIED,
+ composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, 0, INT_MAX, false));
+
+ UIDFaker f(AID_SYSTEM);
+
+ // By default the system can capture screenshots with secure layers but they
+ // will be blacked out
+ ASSERT_EQ(NO_ERROR,
+ composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, 0, INT_MAX, false));
+
+ {
+ SCOPED_TRACE("as system");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+
+ // Here we pass captureSecureLayers = true and since we are AID_SYSTEM we should be able
+ // to receive them...we are expected to take care with the results.
+ bool outCapturedSecureLayers = false;
+ ASSERT_EQ(NO_ERROR,
+ composer->captureScreen(mDisplay, &outBuffer, outCapturedSecureLayers,
+ Rect(), 0, 0, 0, INT_MAX, false, ISurfaceComposer::eRotateNone, true));
+ ASSERT_EQ(true, outCapturedSecureLayers);
+ ScreenCapture sc(outBuffer);
+ sc.expectColor(Rect(0, 0, 32, 32), Color::RED);
+}
+
TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic) {
const Rect top(0, 0, 32, 16);
const Rect bottom(0, 16, 32, 32);
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index 520df2d..5fa8a09 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -12,6 +12,7 @@
shared_libs: [
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.power@1.3",
"libbase",
"libbinder",
"libcutils",
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 39761dd..4a92780 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -24,6 +24,7 @@
"EventThreadTest.cpp",
"mock/DisplayHardware/MockComposer.cpp",
"mock/DisplayHardware/MockDisplaySurface.cpp",
+ "mock/DisplayHardware/MockPowerAdvisor.cpp",
"mock/gui/MockGraphicBufferConsumer.cpp",
"mock/gui/MockGraphicBufferProducer.cpp",
"mock/MockEventControlThread.cpp",
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index f1556d8..acd16fe 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -149,12 +149,18 @@
* Wrapper classes for Read-write access to private data to set up
* preconditions and assert post-conditions.
*/
+ class FakePowerAdvisor : public Hwc2::PowerAdvisor {
+ public:
+ FakePowerAdvisor() = default;
+ ~FakePowerAdvisor() override = default;
+ void setExpensiveRenderingExpected(hwc2_display_t, bool) override { }
+ };
struct HWC2Display : public HWC2::Display {
- HWC2Display(Hwc2::Composer& composer,
+ HWC2Display(Hwc2::Composer& composer, Hwc2::PowerAdvisor& advisor,
const std::unordered_set<HWC2::Capability>& capabilities, hwc2_display_t id,
HWC2::DisplayType type)
- : HWC2::Display(composer, capabilities, id, type) {}
+ : HWC2::Display(composer, advisor, capabilities, id, type) {}
~HWC2Display() {
// Prevents a call to disable vsyncs.
mType = HWC2::DisplayType::Invalid;
@@ -217,8 +223,8 @@
}
void inject(TestableSurfaceFlinger* flinger, Hwc2::Composer* composer) {
- auto display = std::make_unique<HWC2Display>(*composer, mCapabilities, mHwcDisplayId,
- mHwcDisplayType);
+ auto display = std::make_unique<HWC2Display>(*composer, mPowerAdvisor, mCapabilities,
+ mHwcDisplayId, mHwcDisplayType);
auto config = HWC2::Display::Config::Builder(*display, mActiveConfig);
config.setWidth(mWidth);
@@ -248,6 +254,7 @@
int32_t mDpiY = DEFAULT_DPI;
int32_t mActiveConfig = DEFAULT_ACTIVE_CONFIG;
std::unordered_set<HWC2::Capability> mCapabilities;
+ FakePowerAdvisor mPowerAdvisor;
};
class FakeDisplayDeviceInjector {
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.cpp b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.cpp
new file mode 100644
index 0000000..8be7077
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 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 "MockPowerAdvisor.h"
+
+namespace android {
+namespace Hwc2 {
+namespace mock {
+
+// Explicit default instantiation is recommended.
+PowerAdvisor::PowerAdvisor() = default;
+PowerAdvisor::~PowerAdvisor() = default;
+
+} // namespace mock
+} // namespace Hwc2
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
new file mode 100644
index 0000000..dc6d83b
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include "DisplayHardware/PowerAdvisor.h"
+
+namespace android {
+namespace Hwc2 {
+namespace mock {
+
+class PowerAdvisor : public android::Hwc2::PowerAdvisor {
+public:
+ PowerAdvisor();
+ ~PowerAdvisor() override;
+
+ MOCK_METHOD2(setExpensiveRenderingExpected, void(hwc2_display_t displayId, bool expected));
+};
+
+} // namespace mock
+} // namespace Hwc2
+} // namespace android
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 56bc35e..19d0146 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -945,7 +945,9 @@
memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
- prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
+ // b/130182551 VK_KHR_SWAPCHAIN_SPEC_VERSION > 68 has structs the
+ // loader doesn't handle properly. So drop the spec version to 68.
+ prop.specVersion = 68;
}
}