DO NOT MERGE ANYWHERE: BufferQueue consumers: Add discardFreeBuffer method am: 8211047138 -s ours
am: 7b265d8ab5 -s ours
Change-Id: I555ef520067d4300450ef3b0e91f127d06e55b66
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index facf300..5885738 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -102,6 +102,7 @@
{ "pm", "Package Manager", ATRACE_TAG_PACKAGE_MANAGER, { } },
{ "ss", "System Server", ATRACE_TAG_SYSTEM_SERVER, { } },
{ "database", "Database", ATRACE_TAG_DATABASE, { } },
+ { "network", "Network", ATRACE_TAG_NETWORK, { } },
{ k_coreServiceCategory, "Core services", 0, { } },
{ "sched", "CPU Scheduling", 0, {
{ REQ, "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index e9f9e57..23629b3 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -689,6 +689,8 @@
run_command("IP6TABLES", 10, "ip6tables", "-L", "-nvx", NULL);
run_command("IPTABLE NAT", 10, "iptables", "-t", "nat", "-L", "-nvx", NULL);
/* no ip6 nat */
+ run_command("IPTABLE MANGLE", 10, "iptables", "-t", "mangle", "-L", "-nvx", NULL);
+ run_command("IP6TABLE MANGLE", 10, "ip6tables", "-t", "mangle", "-L", "-nvx", NULL);
run_command("IPTABLE RAW", 10, "iptables", "-t", "raw", "-L", "-nvx", NULL);
run_command("IP6TABLE RAW", 10, "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
}
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 2014e99..31f9d7e 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -2186,6 +2186,9 @@
bool art_success = true;
if (!a_image_path.empty()) {
art_success = move_ab_path(b_image_path, a_image_path);
+ if (!art_success) {
+ unlink(a_image_path.c_str());
+ }
}
success = art_success || kIgnoreAppImageFailure;
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index b8ee331..c4f88b6 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -166,8 +166,8 @@
static status_t getHdrCapabilities(const sp<IBinder>& display,
HdrCapabilities* outCapabilities);
- static void setDisplaySurface(const sp<IBinder>& token,
- const sp<IGraphicBufferProducer>& bufferProducer);
+ static status_t setDisplaySurface(const sp<IBinder>& token,
+ sp<IGraphicBufferProducer> bufferProducer);
static void setDisplayLayerStack(const sp<IBinder>& token,
uint32_t layerStack);
static void setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height);
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index dbf8114..ab223ff 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -1364,12 +1364,18 @@
status_t res = OK;
- if (!nameAlreadyWritten) res = parcel->writeString16(name);
+ if (!nameAlreadyWritten) {
+ res = parcel->writeString16(name);
+ if (res != OK) return res;
- if (res == OK) {
- res = parcel->writeStrongBinder(
- IGraphicBufferProducer::asBinder(graphicBufferProducer));
+ /* isSingleBuffered defaults to no */
+ res = parcel->writeInt32(0);
+ if (res != OK) return res;
}
+
+ res = parcel->writeStrongBinder(
+ IGraphicBufferProducer::asBinder(graphicBufferProducer));
+
return res;
}
@@ -1380,13 +1386,20 @@
status_t Surface::readFromParcel(const Parcel* parcel, bool nameAlreadyRead) {
if (parcel == nullptr) return BAD_VALUE;
+ status_t res = OK;
if (!nameAlreadyRead) {
name = readMaybeEmptyString16(parcel);
+ // Discard this for now
+ int isSingleBuffered;
+ res = parcel->readInt32(&isSingleBuffered);
+ if (res != OK) {
+ return res;
+ }
}
sp<IBinder> binder;
- status_t res = parcel->readStrongBinder(&binder);
+ res = parcel->readStrongBinder(&binder);
if (res != OK) return res;
graphicBufferProducer = interface_cast<IGraphicBufferProducer>(binder);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 3df5f74..b78de2e 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -170,8 +170,8 @@
status_t setGeometryAppliesWithResize(const sp<SurfaceComposerClient>& client,
const sp<IBinder>& id);
- void setDisplaySurface(const sp<IBinder>& token,
- const sp<IGraphicBufferProducer>& bufferProducer);
+ status_t setDisplaySurface(const sp<IBinder>& token,
+ sp<IGraphicBufferProducer> bufferProducer);
void setDisplayLayerStack(const sp<IBinder>& token, uint32_t layerStack);
void setDisplayProjection(const sp<IBinder>& token,
uint32_t orientation,
@@ -473,12 +473,24 @@
return mDisplayStates.editItemAt(static_cast<size_t>(index));
}
-void Composer::setDisplaySurface(const sp<IBinder>& token,
- const sp<IGraphicBufferProducer>& bufferProducer) {
+status_t Composer::setDisplaySurface(const sp<IBinder>& token,
+ sp<IGraphicBufferProducer> bufferProducer) {
+ if (bufferProducer.get() != nullptr) {
+ // Make sure that composition can never be stalled by a virtual display
+ // consumer that isn't processing buffers fast enough.
+ status_t err = bufferProducer->setAsyncMode(true);
+ if (err != NO_ERROR) {
+ ALOGE("Composer::setDisplaySurface Failed to enable async mode on the "
+ "BufferQueue. This BufferQueue cannot be used for virtual "
+ "display. (%d)", err);
+ return err;
+ }
+ }
Mutex::Autolock _l(mLock);
DisplayState& s(getDisplayStateLocked(token));
s.surface = bufferProducer;
s.what |= DisplayState::eSurfaceChanged;
+ return NO_ERROR;
}
void Composer::setDisplayLayerStack(const sp<IBinder>& token,
@@ -716,9 +728,9 @@
// ----------------------------------------------------------------------------
-void SurfaceComposerClient::setDisplaySurface(const sp<IBinder>& token,
- const sp<IGraphicBufferProducer>& bufferProducer) {
- Composer::getInstance().setDisplaySurface(token, bufferProducer);
+status_t SurfaceComposerClient::setDisplaySurface(const sp<IBinder>& token,
+ sp<IGraphicBufferProducer> bufferProducer) {
+ return Composer::getInstance().setDisplaySurface(token, bufferProducer);
}
void SurfaceComposerClient::setDisplayLayerStack(const sp<IBinder>& token,
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index eb86860..24e4c19 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -31,7 +31,7 @@
EGL/Loader.cpp \
#
-LOCAL_SHARED_LIBRARIES += libcutils libutils liblog libui
+LOCAL_SHARED_LIBRARIES += libbinder libcutils libutils liblog libui
LOCAL_MODULE:= libEGL
LOCAL_LDFLAGS += -Wl,--exclude-libs=ALL
LOCAL_SHARED_LIBRARIES += libdl
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 03abc49..f41e6e2 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -33,6 +33,8 @@
#include <cutils/properties.h>
#include <cutils/memory.h>
+#include <gui/ISurfaceComposer.h>
+
#include <ui/GraphicBuffer.h>
#include <utils/KeyedVector.h>
@@ -40,6 +42,10 @@
#include <utils/String8.h>
#include <utils/Trace.h>
+#include "binder/Binder.h"
+#include "binder/Parcel.h"
+#include "binder/IServiceManager.h"
+
#include "../egl_impl.h"
#include "../hooks.h"
@@ -1872,20 +1878,77 @@
return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
}
- GraphicBuffer* gBuffer = new GraphicBuffer(width, height, format, usage,
+#define CHECK_ERROR_CONDITION(message) \
+ if (err != NO_ERROR) { \
+ ALOGE(message); \
+ goto error_condition; \
+ }
+
+ // The holder is used to destroy the buffer if an error occurs.
+ GraphicBuffer* gBuffer = new GraphicBuffer();
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> surfaceFlinger = sm->getService(String16("SurfaceFlinger"));
+ sp<IBinder> allocator;
+ Parcel sc_data, sc_reply, data, reply;
+ status_t err = NO_ERROR;
+ if (sm == NULL) {
+ ALOGE("Unable to connect to ServiceManager");
+ goto error_condition;
+ }
+
+ // Obtain an allocator.
+ if (surfaceFlinger == NULL) {
+ ALOGE("Unable to connect to SurfaceFlinger");
+ goto error_condition;
+ }
+ sc_data.writeInterfaceToken(String16("android.ui.ISurfaceComposer"));
+ err = surfaceFlinger->transact(
+ BnSurfaceComposer::CREATE_GRAPHIC_BUFFER_ALLOC, sc_data, &sc_reply);
+ CHECK_ERROR_CONDITION("Unable to obtain allocator from SurfaceFlinger");
+ allocator = sc_reply.readStrongBinder();
+
+ if (allocator == NULL) {
+ ALOGE("Unable to obtain an ISurfaceComposer");
+ goto error_condition;
+ }
+ data.writeInterfaceToken(String16("android.ui.IGraphicBufferAlloc"));
+ err = data.writeUint32(width);
+ CHECK_ERROR_CONDITION("Unable to write width");
+ err = data.writeUint32(height);
+ CHECK_ERROR_CONDITION("Unable to write height");
+ err = data.writeInt32(static_cast<int32_t>(format));
+ CHECK_ERROR_CONDITION("Unable to write format");
+ err = data.writeUint32(usage);
+ CHECK_ERROR_CONDITION("Unable to write usage");
+ err = data.writeUtf8AsUtf16(
std::string("[eglCreateNativeClientBufferANDROID pid ") +
std::to_string(getpid()) + ']');
- const status_t err = gBuffer->initCheck();
+ CHECK_ERROR_CONDITION("Unable to write requestor name");
+ err = allocator->transact(IBinder::FIRST_CALL_TRANSACTION, data,
+ &reply);
+ CHECK_ERROR_CONDITION(
+ "Unable to request buffer allocation from surface composer");
+ err = reply.readInt32();
+ CHECK_ERROR_CONDITION("Unable to obtain buffer from surface composer");
+ err = reply.read(*gBuffer);
+ CHECK_ERROR_CONDITION("Unable to read buffer from surface composer");
+
+ err = gBuffer->initCheck();
if (err != NO_ERROR) {
ALOGE("Unable to create native buffer { w=%d, h=%d, f=%d, u=%#x }: %#x",
width, height, format, usage, err);
- // Destroy the buffer.
- sp<GraphicBuffer> holder(gBuffer);
- return setError(EGL_BAD_ALLOC, (EGLClientBuffer)0);
+ goto error_condition;
}
ALOGD("Created new native buffer %p { w=%d, h=%d, f=%d, u=%#x }",
gBuffer, width, height, format, usage);
return static_cast<EGLClientBuffer>(gBuffer->getNativeBuffer());
+
+#undef CHECK_ERROR_CONDITION
+
+error_condition:
+ // Delete the buffer.
+ sp<GraphicBuffer> holder(gBuffer);
+ return setError(EGL_BAD_ALLOC, (EGLClientBuffer)0);
}
// ----------------------------------------------------------------------------
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index c1e1bad..f2f1444 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -206,7 +206,7 @@
status_t SensorService::SensorEventConnection::sendEvents(
sensors_event_t const* buffer, size_t numEvents,
sensors_event_t* scratch,
- SensorEventConnection const * const * mapFlushEventsToConnections) {
+ wp<const SensorEventConnection> const * mapFlushEventsToConnections) {
// filter out events not for this connection
int count = 0;
Mutex::Autolock _l(mConnectionLock);
@@ -234,7 +234,7 @@
FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
// Check if there is a pending flush_complete event for this sensor on this connection.
if (buffer[i].type == SENSOR_TYPE_META_DATA && flushInfo.mFirstFlushPending == true &&
- this == mapFlushEventsToConnections[i]) {
+ mapFlushEventsToConnections[i] == this) {
flushInfo.mFirstFlushPending = false;
ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ",
buffer[i].meta_data.sensor);
@@ -255,7 +255,7 @@
// from the same sensor_handle AND the current connection is mapped to the
// corresponding flush_complete_event.
if (buffer[i].type == SENSOR_TYPE_META_DATA) {
- if (this == mapFlushEventsToConnections[i]) {
+ if (mapFlushEventsToConnections[i] == this) {
scratch[count++] = buffer[i];
}
++i;
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index b796cc0..883c16e 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -52,7 +52,7 @@
bool isDataInjectionMode, const String16& opPackageName);
status_t sendEvents(sensors_event_t const* buffer, size_t count, sensors_event_t* scratch,
- SensorEventConnection const * const * mapFlushEventsToConnections = NULL);
+ wp<const SensorEventConnection> const * mapFlushEventsToConnections = NULL);
bool hasSensor(int32_t handle) const;
bool hasAnySensor() const;
bool hasOneShotSensors() const;
diff --git a/services/sensorservice/SensorRecord.cpp b/services/sensorservice/SensorRecord.cpp
index 644cfb0..53fb9de 100644
--- a/services/sensorservice/SensorRecord.cpp
+++ b/services/sensorservice/SensorRecord.cpp
@@ -21,13 +21,13 @@
namespace android {
SensorService::SensorRecord::SensorRecord(
- const sp<SensorEventConnection>& connection)
+ const sp<const SensorEventConnection>& connection)
{
mConnections.add(connection);
}
bool SensorService::SensorRecord::addConnection(
- const sp<SensorEventConnection>& connection)
+ const sp<const SensorEventConnection>& connection)
{
if (mConnections.indexOf(connection) < 0) {
mConnections.add(connection);
@@ -37,16 +37,16 @@
}
bool SensorService::SensorRecord::removeConnection(
- const wp<SensorEventConnection>& connection)
+ const wp<const SensorEventConnection>& connection)
{
ssize_t index = mConnections.indexOf(connection);
if (index >= 0) {
mConnections.removeItemsAt(index, 1);
}
// Remove this connections from the queue of flush() calls made on this sensor.
- for (Vector< wp<SensorEventConnection> >::iterator it = mPendingFlushConnections.begin();
+ for (Vector< wp<const SensorEventConnection> >::iterator it = mPendingFlushConnections.begin();
it != mPendingFlushConnections.end(); ) {
- if (it->unsafe_get() == connection.unsafe_get()) {
+ if (*it == connection) {
it = mPendingFlushConnections.erase(it);
} else {
++it;
@@ -56,7 +56,7 @@
}
void SensorService::SensorRecord::addPendingFlushConnection(
- const sp<SensorEventConnection>& connection) {
+ const sp<const SensorEventConnection>& connection) {
mPendingFlushConnections.add(connection);
}
@@ -66,10 +66,10 @@
}
}
-SensorService::SensorEventConnection *
+wp<const SensorService::SensorEventConnection>
SensorService::SensorRecord::getFirstPendingFlushConnection() {
if (mPendingFlushConnections.size() > 0) {
- return mPendingFlushConnections[0].unsafe_get();
+ return mPendingFlushConnections[0];
}
return NULL;
}
diff --git a/services/sensorservice/SensorRecord.h b/services/sensorservice/SensorRecord.h
index 29b970d..5a35410 100644
--- a/services/sensorservice/SensorRecord.h
+++ b/services/sensorservice/SensorRecord.h
@@ -25,20 +25,20 @@
class SensorService::SensorRecord {
public:
- SensorRecord(const sp<SensorEventConnection>& connection);
- bool addConnection(const sp<SensorEventConnection>& connection);
- bool removeConnection(const wp<SensorEventConnection>& connection);
+ SensorRecord(const sp<const SensorEventConnection>& connection);
+ bool addConnection(const sp<const SensorEventConnection>& connection);
+ bool removeConnection(const wp<const SensorEventConnection>& connection);
size_t getNumConnections() const { return mConnections.size(); }
- void addPendingFlushConnection(const sp<SensorEventConnection>& connection);
+ void addPendingFlushConnection(const sp<const SensorEventConnection>& connection);
void removeFirstPendingFlushConnection();
- SensorEventConnection * getFirstPendingFlushConnection();
+ wp<const SensorEventConnection> getFirstPendingFlushConnection();
void clearAllPendingFlushConnections();
private:
- SortedVector< wp<SensorEventConnection> > mConnections;
+ SortedVector< wp<const SensorEventConnection> > mConnections;
// A queue of all flush() calls made on this sensor. Flush complete events
// will be sent in this order.
- Vector< wp<SensorEventConnection> > mPendingFlushConnections;
+ Vector< wp<const SensorEventConnection> > mPendingFlushConnections;
};
}
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index a24740b..dbd0624 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -260,7 +260,7 @@
const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
mSensorEventBuffer = new sensors_event_t[minBufferSize];
mSensorEventScratch = new sensors_event_t[minBufferSize];
- mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];
+ mMapFlushEventsToConnections = new wp<const SensorEventConnection> [minBufferSize];
mCurrentOperatingMode = NORMAL;
mNextSensorRegIndex = 0;
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 1e1ea5a..4a63ef0 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -237,7 +237,7 @@
SortedVector< wp<SensorEventConnection> > mActiveConnections;
bool mWakeLockAcquired;
sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
- SensorEventConnection const **mMapFlushEventsToConnections;
+ wp<const SensorEventConnection> * mMapFlushEventsToConnections;
std::unordered_map<int, RecentEventLogger*> mRecentEvent;
Mode mCurrentOperatingMode;
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index dc5e97b..ffda035 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -79,18 +79,36 @@
LOCAL_CFLAGS += -DRUNNING_WITHOUT_SYNC_FRAMEWORK
endif
-# See build/target/board/generic/BoardConfig.mk for a description of this setting.
+# The following two BoardConfig variables define (respectively):
+#
+# - The phase offset between hardware vsync and when apps are woken up by the
+# Choreographer callback
+# - The phase offset between hardware vsync and when SurfaceFlinger wakes up
+# to consume input
+#
+# Their values can be tuned to trade off between display pipeline latency (both
+# overall latency and the lengths of the app --> SF and SF --> display phases)
+# and frame delivery jitter (which typically manifests as "jank" or "jerkiness"
+# while interacting with the device). The default values should produce a
+# relatively low amount of jitter at the expense of roughly two frames of
+# app --> display latency, and unless significant testing is performed to avoid
+# increased display jitter (both manual investigation using systrace [1] and
+# automated testing using dumpsys gfxinfo [2] are recommended), they should not
+# be modified.
+#
+# [1] https://developer.android.com/studio/profile/systrace.html
+# [2] https://developer.android.com/training/testing/performance.html
+
ifneq ($(VSYNC_EVENT_PHASE_OFFSET_NS),)
LOCAL_CFLAGS += -DVSYNC_EVENT_PHASE_OFFSET_NS=$(VSYNC_EVENT_PHASE_OFFSET_NS)
else
- LOCAL_CFLAGS += -DVSYNC_EVENT_PHASE_OFFSET_NS=0
+ LOCAL_CFLAGS += -DVSYNC_EVENT_PHASE_OFFSET_NS=1000000
endif
-# See build/target/board/generic/BoardConfig.mk for a description of this setting.
ifneq ($(SF_VSYNC_EVENT_PHASE_OFFSET_NS),)
LOCAL_CFLAGS += -DSF_VSYNC_EVENT_PHASE_OFFSET_NS=$(SF_VSYNC_EVENT_PHASE_OFFSET_NS)
else
- LOCAL_CFLAGS += -DSF_VSYNC_EVENT_PHASE_OFFSET_NS=0
+ LOCAL_CFLAGS += -DSF_VSYNC_EVENT_PHASE_OFFSET_NS=1000000
endif
ifneq ($(PRESENT_TIME_OFFSET_FROM_VSYNC_NS),)
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index c67feb3..1a9820d 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -385,7 +385,7 @@
mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
// set DispSync to SCHED_FIFO to minimize jitter
struct sched_param param = {0};
- param.sched_priority = 1;
+ param.sched_priority = 2;
if (sched_setscheduler(mThread->getTid(), SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO for DispSyncThread");
}
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 785df1a..dfece93 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -591,19 +591,25 @@
const Transform& tr(displayDevice->getTransform());
Rect transformedFrame = tr.transform(frame);
auto error = hwcLayer->setDisplayFrame(transformedFrame);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set display frame "
- "[%d, %d, %d, %d]: %s (%d)", mName.string(), transformedFrame.left,
- transformedFrame.top, transformedFrame.right,
- transformedFrame.bottom, to_string(error).c_str(),
- static_cast<int32_t>(error));
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)",
+ mName.string(), transformedFrame.left, transformedFrame.top,
+ transformedFrame.right, transformedFrame.bottom,
+ to_string(error).c_str(), static_cast<int32_t>(error));
+ } else {
+ hwcInfo.displayFrame = transformedFrame;
+ }
FloatRect sourceCrop = computeCrop(displayDevice);
error = hwcLayer->setSourceCrop(sourceCrop);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set source crop "
- "[%.3f, %.3f, %.3f, %.3f]: %s (%d)", mName.string(),
- sourceCrop.left, sourceCrop.top, sourceCrop.right,
- sourceCrop.bottom, to_string(error).c_str(),
- static_cast<int32_t>(error));
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
+ "%s (%d)", mName.string(), sourceCrop.left, sourceCrop.top,
+ sourceCrop.right, sourceCrop.bottom, to_string(error).c_str(),
+ static_cast<int32_t>(error));
+ } else {
+ hwcInfo.sourceCrop = sourceCrop;
+ }
error = hwcLayer->setPlaneAlpha(s.alpha);
ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set plane alpha %.3f: "
@@ -2235,6 +2241,54 @@
}
}
+#ifdef USE_HWC2
+void Layer::miniDumpHeader(String8& result) {
+ result.append("----------------------------------------");
+ result.append("---------------------------------------\n");
+ result.append(" Layer name\n");
+ result.append(" Z | ");
+ result.append(" Comp Type | ");
+ result.append(" Disp Frame (LTRB) | ");
+ result.append(" Source Crop (LTRB)\n");
+ result.append("----------------------------------------");
+ result.append("---------------------------------------\n");
+}
+
+void Layer::miniDump(String8& result, int32_t hwcId) const {
+ if (mHwcLayers.count(hwcId) == 0) {
+ return;
+ }
+
+ String8 name;
+ if (mName.length() > 77) {
+ std::string shortened;
+ shortened.append(mName.string(), 36);
+ shortened.append("[...]");
+ shortened.append(mName.string() + (mName.length() - 36), 36);
+ name = shortened.c_str();
+ } else {
+ name = mName;
+ }
+
+ result.appendFormat(" %s\n", name.string());
+
+ const Layer::State& layerState(getDrawingState());
+ const HWCInfo& hwcInfo = mHwcLayers.at(hwcId);
+ result.appendFormat(" %10u | ", layerState.z);
+ result.appendFormat("%10s | ",
+ to_string(getCompositionType(hwcId)).c_str());
+ const Rect& frame = hwcInfo.displayFrame;
+ result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top,
+ frame.right, frame.bottom);
+ const FloatRect& crop = hwcInfo.sourceCrop;
+ result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top,
+ crop.right, crop.bottom);
+
+ result.append("- - - - - - - - - - - - - - - - - - - - ");
+ result.append("- - - - - - - - - - - - - - - - - - - -\n");
+}
+#endif
+
void Layer::dumpFrameStats(String8& result) const {
mFrameTracker.dumpStats(result);
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 6533953..2ce1340 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -402,6 +402,10 @@
/* always call base class first */
void dump(String8& result, Colorizer& colorizer) const;
+#ifdef USE_HWC2
+ static void miniDumpHeader(String8& result);
+ void miniDump(String8& result, int32_t hwcId) const;
+#endif
void dumpFrameStats(String8& result) const;
void clearFrameStats();
void logFrameStats();
@@ -588,6 +592,8 @@
bool forceClientComposition;
HWC2::Composition compositionType;
bool clearClientTarget;
+ Rect displayFrame;
+ FloatRect sourceCrop;
};
std::unordered_map<int32_t, HWCInfo> mHwcLayers;
#else
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 2a67f4c..8db071e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -471,7 +471,7 @@
// set SFEventThread to SCHED_FIFO to minimize jitter
struct sched_param param = {0};
- param.sched_priority = 1;
+ param.sched_priority = 2;
if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
}
@@ -3057,6 +3057,26 @@
* VSYNC state
*/
mEventThread->dump(result);
+ result.append("\n");
+
+ /*
+ * HWC layer minidump
+ */
+ for (size_t d = 0; d < mDisplays.size(); d++) {
+ const sp<const DisplayDevice>& displayDevice(mDisplays[d]);
+ int32_t hwcId = displayDevice->getHwcDisplayId();
+ if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) {
+ continue;
+ }
+
+ result.appendFormat("Display %d HWC layers:\n", hwcId);
+ Layer::miniDumpHeader(result);
+ for (size_t l = 0; l < count; l++) {
+ const sp<Layer>& layer(currentLayers[l]);
+ layer->miniDump(result, hwcId);
+ }
+ result.append("\n");
+ }
/*
* Dump HWComposer state
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 650d6b4..b0f418c 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -467,7 +467,7 @@
// set SFEventThread to SCHED_FIFO to minimize jitter
struct sched_param param = {0};
- param.sched_priority = 1;
+ param.sched_priority = 2;
if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
}