Merge "EGL: rename CallStack::dump into CallStack::log" into klp-dev
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 7a782f5..c95f297 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -101,6 +101,7 @@
status_t writeString16(const char16_t* str, size_t len);
status_t writeStrongBinder(const sp<IBinder>& val);
status_t writeWeakBinder(const wp<IBinder>& val);
+ status_t writeInt32Array(size_t len, const int32_t *val);
template<typename T>
status_t write(const Flattenable<T>& val);
diff --git a/include/powermanager/IPowerManager.h b/include/powermanager/IPowerManager.h
index 2f4c3c4..d85003f 100644
--- a/include/powermanager/IPowerManager.h
+++ b/include/powermanager/IPowerManager.h
@@ -35,6 +35,7 @@
virtual status_t acquireWakeLockWithUid(int flags, const sp<IBinder>& lock, const String16& tag,
const String16& packageName, int uid) = 0;
virtual status_t releaseWakeLock(const sp<IBinder>& lock, int flags) = 0;
+ virtual status_t updateWakeLockUids(const sp<IBinder>& lock, int len, const int *uids) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 7a5919f..38e019c 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -617,6 +617,16 @@
{
return writeAligned(val);
}
+status_t Parcel::writeInt32Array(size_t len, const int32_t *val) {
+ if (!val) {
+ return writeAligned(-1);
+ }
+ status_t ret = writeAligned(len);
+ if (ret == NO_ERROR) {
+ ret = write(val, len * sizeof(*val));
+ }
+ return ret;
+}
status_t Parcel::writeInt64(int64_t val)
{
diff --git a/services/powermanager/IPowerManager.cpp b/services/powermanager/IPowerManager.cpp
index 9f60e75..5ecd299 100644
--- a/services/powermanager/IPowerManager.cpp
+++ b/services/powermanager/IPowerManager.cpp
@@ -32,6 +32,7 @@
ACQUIRE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION,
ACQUIRE_WAKE_LOCK_UID = IBinder::FIRST_CALL_TRANSACTION + 1,
RELEASE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION + 2,
+ UPDATE_WAKE_LOCK_UIDS = IBinder::FIRST_CALL_TRANSACTION + 3,
};
class BpPowerManager : public BpInterface<IPowerManager>
@@ -78,6 +79,16 @@
data.writeInt32(flags);
return remote()->transact(RELEASE_WAKE_LOCK, data, &reply);
}
+
+ virtual status_t updateWakeLockUids(const sp<IBinder>& lock, int len, const int *uids) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
+ data.writeStrongBinder(lock);
+ data.writeInt32Array(len, uids);
+ // We don't really care too much if this succeeds (there's nothing we can do if it doesn't)
+ // but it should return ASAP
+ return remote()->transact(UPDATE_WAKE_LOCK_UIDS, data, &reply, IBinder::FLAG_ONEWAY);
+ }
};
IMPLEMENT_META_INTERFACE(PowerManager, "android.os.IPowerManager");
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 555d843..a2f4332 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -480,6 +480,11 @@
return result;
}
+bool SensorService::isVirtualSensor(int handle) const {
+ SensorInterface* sensor = mSensorMap.valueFor(handle);
+ return sensor->isVirtual();
+}
+
Vector<Sensor> SensorService::getSensorList()
{
char value[PROPERTY_VALUE_MAX];
@@ -858,6 +863,11 @@
}
}
+ // Early return if there are no events for this connection.
+ if (count == 0) {
+ return status_t(NO_ERROR);
+ }
+
// NOTE: ASensorEvent and sensors_event_t are the same type
ssize_t size = SensorEventQueue::write(mChannel,
reinterpret_cast<ASensorEvent const*>(scratch), count);
@@ -922,7 +932,7 @@
// Loop through all sensors for this connection and call flush on each of them.
for (size_t i = 0; i < mSensorInfo.size(); ++i) {
const int handle = mSensorInfo.keyAt(i);
- if (halVersion < SENSORS_DEVICE_API_VERSION_1_1) {
+ if (halVersion < SENSORS_DEVICE_API_VERSION_1_1 || mService->isVirtualSensor(handle)) {
// For older devices just increment pending flush count which will send a trivial
// flush complete event.
FlushInfo& flushInfo = mSensorInfo.editValueFor(handle);
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 6c1691a..c968319 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -130,6 +130,7 @@
DefaultKeyedVector<int, SensorInterface*> getActiveVirtualSensors() const;
String8 getSensorName(int handle) const;
+ bool isVirtualSensor(int handle) const;
void recordLastValue(sensors_event_t const * buffer, size_t count);
static void sortEventBuffer(sensors_event_t* buffer, size_t count);
Sensor registerSensor(SensorInterface* sensor);
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index c3daa64..b2bc550 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -51,6 +51,10 @@
LOCAL_CFLAGS += -DTARGET_DISABLE_TRIPLE_BUFFERING
endif
+ifeq ($(TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS),true)
+ LOCAL_CFLAGS += -DFORCE_HWC_COPY_FOR_VIRTUAL_DISPLAYS
+endif
+
ifneq ($(NUM_FRAMEBUFFER_SURFACE_BUFFERS),)
LOCAL_CFLAGS += -DNUM_FRAMEBUFFER_SURFACE_BUFFERS=$(NUM_FRAMEBUFFER_SURFACE_BUFFERS)
endif
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index c5a14b0..bbe8d68 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -22,6 +22,12 @@
namespace android {
// ---------------------------------------------------------------------------
+#if defined(FORCE_HWC_COPY_FOR_VIRTUAL_DISPLAYS)
+static const bool sForceHwcCopy = true;
+#else
+static const bool sForceHwcCopy = false;
+#endif
+
#define VDS_LOGE(msg, ...) ALOGE("[%s] "msg, \
mDisplayName.string(), ##__VA_ARGS__)
#define VDS_LOGW_IF(cond, msg, ...) ALOGW_IF(cond, "[%s] "msg, \
@@ -47,7 +53,8 @@
mHwc(hwc),
mDisplayId(dispId),
mDisplayName(name),
- mProducerUsage(GRALLOC_USAGE_HW_COMPOSER),
+ mOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
+ mOutputUsage(GRALLOC_USAGE_HW_COMPOSER),
mProducerSlotSource(0),
mDbgState(DBG_STATE_IDLE),
mDbgLastCompositionType(COMPOSITION_UNKNOWN)
@@ -95,6 +102,17 @@
mDbgState = DBG_STATE_PREPARED;
mCompositionType = compositionType;
+ if (sForceHwcCopy && mCompositionType == COMPOSITION_GLES) {
+ // Some hardware can do RGB->YUV conversion more efficiently in hardware
+ // controlled by HWC than in hardware controlled by the video encoder.
+ // Forcing GLES-composed frames to go through an extra copy by the HWC
+ // allows the format conversion to happen there, rather than passing RGB
+ // directly to the consumer.
+ //
+ // On the other hand, when the consumer prefers RGB or can consume RGB
+ // inexpensively, this forces an unnecessary copy.
+ mCompositionType = COMPOSITION_MIXED;
+ }
if (mCompositionType != mDbgLastCompositionType) {
VDS_LOGV("prepareFrame: composition type changed to %s",
@@ -102,6 +120,24 @@
mDbgLastCompositionType = mCompositionType;
}
+ if (mCompositionType != COMPOSITION_GLES &&
+ (mOutputFormat != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED ||
+ mOutputUsage != GRALLOC_USAGE_HW_COMPOSER)) {
+ // We must have just switched from GLES-only to MIXED or HWC
+ // composition. Stop using the format and usage requested by the GLES
+ // driver; they may be suboptimal when HWC is writing to the output
+ // buffer. For example, if the output is going to a video encoder, and
+ // HWC can write directly to YUV, some hardware can skip a
+ // memory-to-memory RGB-to-YUV conversion step.
+ //
+ // If we just switched *to* GLES-only mode, we'll change the
+ // format/usage and get a new buffer when the GLES driver calls
+ // dequeueBuffer().
+ mOutputFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+ mOutputUsage = GRALLOC_USAGE_HW_COMPOSER;
+ refreshOutputBuffer();
+ }
+
return NO_ERROR;
}
@@ -212,12 +248,12 @@
}
status_t VirtualDisplaySurface::dequeueBuffer(Source source,
- uint32_t format, int* sslot, sp<Fence>* fence) {
+ uint32_t format, uint32_t usage, int* sslot, sp<Fence>* fence) {
// Don't let a slow consumer block us
bool async = (source == SOURCE_SINK);
status_t result = mSource[source]->dequeueBuffer(sslot, fence, async,
- mSinkBufferWidth, mSinkBufferHeight, format, mProducerUsage);
+ mSinkBufferWidth, mSinkBufferHeight, format, usage);
if (result < 0)
return result;
int pslot = mapSource2ProducerSlot(source, *sslot);
@@ -258,7 +294,6 @@
VDS_LOGV("dequeueBuffer %dx%d fmt=%d usage=%#x", w, h, format, usage);
status_t result = NO_ERROR;
- mProducerUsage = usage | GRALLOC_USAGE_HW_COMPOSER;
Source source = fbSourceForCompositionType(mCompositionType);
if (source == SOURCE_SINK) {
@@ -279,13 +314,20 @@
// prepare and set, but since we're in GLES-only mode already it
// shouldn't matter.
+ usage |= GRALLOC_USAGE_HW_COMPOSER;
const sp<GraphicBuffer>& buf = mProducerBuffers[mOutputProducerSlot];
- if ((mProducerUsage & ~buf->getUsage()) != 0 ||
+ if ((usage & ~buf->getUsage()) != 0 ||
(format != 0 && format != (uint32_t)buf->getPixelFormat()) ||
(w != 0 && w != mSinkBufferWidth) ||
(h != 0 && h != mSinkBufferHeight)) {
- VDS_LOGV("dequeueBuffer: output buffer doesn't satisfy GLES "
- "request, getting a new buffer");
+ VDS_LOGV("dequeueBuffer: dequeueing new output buffer: "
+ "want %dx%d fmt=%d use=%#x, "
+ "have %dx%d fmt=%d use=%#x",
+ w, h, format, usage,
+ mSinkBufferWidth, mSinkBufferHeight,
+ buf->getPixelFormat(), buf->getUsage());
+ mOutputFormat = format;
+ mOutputUsage = usage;
result = refreshOutputBuffer();
if (result < 0)
return result;
@@ -297,7 +339,7 @@
*fence = mOutputFence;
} else {
int sslot;
- result = dequeueBuffer(source, format, &sslot, fence);
+ result = dequeueBuffer(source, format, usage, &sslot, fence);
if (result >= 0) {
*pslot = mapSource2ProducerSlot(source, sslot);
}
@@ -414,7 +456,8 @@
}
int sslot;
- status_t result = dequeueBuffer(SOURCE_SINK, 0, &sslot, &mOutputFence);
+ status_t result = dequeueBuffer(SOURCE_SINK, mOutputFormat, mOutputUsage,
+ &sslot, &mOutputFence);
if (result < 0)
return result;
mOutputProducerSlot = mapSource2ProducerSlot(SOURCE_SINK, sslot);
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 18fb5a7..57b5554 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -110,7 +110,7 @@
// Utility methods
//
static Source fbSourceForCompositionType(CompositionType type);
- status_t dequeueBuffer(Source source, uint32_t format,
+ status_t dequeueBuffer(Source source, uint32_t format, uint32_t usage,
int* sslot, sp<Fence>* fence);
void updateQueueBufferOutput(const QueueBufferOutput& qbo);
void resetPerFrameState();
@@ -137,10 +137,12 @@
// Inter-frame state
//
- // To avoid buffer reallocations, we track the buffer usage requested by
- // the GLES driver in dequeueBuffer so we can use the same flags on
- // HWC-only frames.
- uint32_t mProducerUsage;
+ // To avoid buffer reallocations, we track the buffer usage and format
+ // we used on the previous frame and use it again on the new frame. If
+ // the composition type changes or the GLES driver starts requesting
+ // different usage/format, we'll get a new buffer.
+ uint32_t mOutputFormat;
+ uint32_t mOutputUsage;
// Since we present a single producer interface to the GLES driver, but
// are internally muxing between the sink and scratch producers, we have