Merge "Stop using netmask in the framework."
diff --git a/include/gui/ISurfaceTexture.h b/include/gui/ISurfaceTexture.h
index 77d37f1..168310c 100644
--- a/include/gui/ISurfaceTexture.h
+++ b/include/gui/ISurfaceTexture.h
@@ -72,6 +72,12 @@
virtual status_t setCrop(const Rect& reg) = 0;
virtual status_t setTransform(uint32_t transform) = 0;
+
+ // getAllocator retrieves the binder object that must be referenced as long
+ // as the GraphicBuffers dequeued from this ISurfaceTexture are referenced.
+ // Holding this binder reference prevents SurfaceFlinger from freeing the
+ // buffers before the client is done with them.
+ virtual sp<IBinder> getAllocator() = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 79c33f5..31615d0 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -101,6 +101,12 @@
// when a new frame becomes available.
void setFrameAvailableListener(const sp<FrameAvailableListener>& l);
+ // getAllocator retrieves the binder object that must be referenced as long
+ // as the GraphicBuffers dequeued from this SurfaceTexture are referenced.
+ // Holding this binder reference prevents SurfaceFlinger from freeing the
+ // buffers before the client is done with them.
+ sp<IBinder> getAllocator();
+
private:
// freeAllBuffers frees the resources (both GraphicBuffer and EGLImage) for
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index dd1d490..ff2251d 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -83,6 +83,10 @@
// interactions with the server using this interface.
sp<ISurfaceTexture> mSurfaceTexture;
+ // mAllocator is the binder object that is referenced to prevent the
+ // dequeued buffers from being freed prematurely.
+ sp<IBinder> mAllocator;
+
// mSlots stores the buffers that have been allocated for each buffer slot.
// It is initialized to null pointers, and gets filled in with the result of
// ISurfaceTexture::requestBuffer when the client dequeues a buffer from a
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index 56ed3a4..361e7dc 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -44,6 +44,8 @@
eSecure = 0x00000080,
eNonPremultiplied = 0x00000100,
eOpaque = 0x00000400,
+ eProtectedByApp = 0x00000800,
+ eProtectedByDRM = 0x00001000,
eFXSurfaceNormal = 0x00000000,
eFXSurfaceBlur = 0x00010000,
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index 8b256f4..02d6f8f 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -54,9 +54,11 @@
USAGE_SW_WRITE_RARELY = GRALLOC_USAGE_SW_WRITE_RARELY,
USAGE_SW_WRITE_OFTEN = GRALLOC_USAGE_SW_WRITE_OFTEN,
USAGE_SW_WRITE_MASK = GRALLOC_USAGE_SW_WRITE_MASK,
-
+
USAGE_SOFTWARE_MASK = USAGE_SW_READ_MASK|USAGE_SW_WRITE_MASK,
-
+
+ USAGE_PROTECTED = GRALLOC_USAGE_PROTECTED,
+
USAGE_HW_TEXTURE = GRALLOC_USAGE_HW_TEXTURE,
USAGE_HW_RENDER = GRALLOC_USAGE_HW_RENDER,
USAGE_HW_2D = GRALLOC_USAGE_HW_2D,
diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h
index 654d0f3..fdc8105 100644
--- a/include/ui/egl/android_natives.h
+++ b/include/ui/egl/android_natives.h
@@ -315,6 +315,8 @@
* If all parameters are 0, the normal behavior is restored. That is,
* dequeued buffers following this call will be sized to the window's size.
*
+ * Calling this function will reset the window crop to a NULL value, which
+ * disables cropping of the buffers.
*/
static inline int native_window_set_buffers_geometry(
ANativeWindow* window,
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index ed7f53d..6227f3e 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -1985,6 +1985,7 @@
#ifndef HAVE_ANDROID_OS
void print(bool inclValues) const;
+ static String8 normalizeForOutput(const char* input);
#endif
private:
diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp
index 90bca3c..d661fd5 100644
--- a/libs/gui/ISurfaceTexture.cpp
+++ b/libs/gui/ISurfaceTexture.cpp
@@ -38,6 +38,7 @@
CANCEL_BUFFER,
SET_CROP,
SET_TRANSFORM,
+ GET_ALLOCATOR,
};
@@ -123,6 +124,13 @@
status_t result = reply.readInt32();
return result;
}
+
+ virtual sp<IBinder> getAllocator() {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+ remote()->transact(GET_ALLOCATOR, data, &reply);
+ return reply.readStrongBinder();
+ }
};
IMPLEMENT_META_INTERFACE(SurfaceTexture, "android.gui.SurfaceTexture");
@@ -195,6 +203,12 @@
reply->writeInt32(result);
return NO_ERROR;
} break;
+ case GET_ALLOCATOR: {
+ CHECK_INTERFACE(ISurfaceTexture, data, reply);
+ sp<IBinder> result = getAllocator();
+ reply->writeStrongBinder(result);
+ return NO_ERROR;
+ } break;
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 1dadd53..6466f2b 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -219,11 +219,19 @@
mSlots[mLastQueued].mEglImage = image;
mSlots[mLastQueued].mEglDisplay = dpy;
}
+
+ GLint error;
+ while ((error = glGetError()) != GL_NO_ERROR) {
+ LOGE("GL error cleared before updating SurfaceTexture: %#04x", error);
+ }
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image);
- GLint error = glGetError();
- if (error != GL_NO_ERROR) {
+ bool failed = false;
+ while ((error = glGetError()) != GL_NO_ERROR) {
LOGE("error binding external texture image %p (slot %d): %#04x",
image, mLastQueued, error);
+ failed = true;
+ }
+ if (failed) {
return -EINVAL;
}
@@ -304,6 +312,11 @@
mFrameAvailableListener = l;
}
+sp<IBinder> SurfaceTexture::getAllocator() {
+ LOGV("SurfaceTexture::getAllocator");
+ return mGraphicBufferAlloc->asBinder();
+}
+
void SurfaceTexture::freeAllBuffers() {
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
mSlots[i].mGraphicBuffer = 0;
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 0ed8be5..ee14ac9 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -25,8 +25,8 @@
SurfaceTextureClient::SurfaceTextureClient(
const sp<ISurfaceTexture>& surfaceTexture):
- mSurfaceTexture(surfaceTexture), mReqWidth(1), mReqHeight(1),
- mReqFormat(DEFAULT_FORMAT), mReqUsage(0), mMutex() {
+ mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(1),
+ mReqHeight(1), mReqFormat(DEFAULT_FORMAT), mReqUsage(0), mMutex() {
// Initialize the ANativeWindow function pointers.
ANativeWindow::setSwapInterval = setSwapInterval;
ANativeWindow::dequeueBuffer = dequeueBuffer;
@@ -35,6 +35,9 @@
ANativeWindow::queueBuffer = queueBuffer;
ANativeWindow::query = query;
ANativeWindow::perform = perform;
+
+ // Get a reference to the allocator.
+ mAllocator = mSurfaceTexture->getAllocator();
}
int SurfaceTextureClient::setSwapInterval(ANativeWindow* window, int interval) {
@@ -88,7 +91,7 @@
int buf = -1;
status_t err = mSurfaceTexture->dequeueBuffer(&buf);
if (err < 0) {
- LOGE("dequeueBuffer: ISurfaceTexture::dequeueBuffer failed: %d", err);
+ LOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer failed: %d", err);
return err;
}
sp<GraphicBuffer>& gbuf(mSlots[buf]);
@@ -238,13 +241,15 @@
LOGV("SurfaceTextureClient::setCrop");
Mutex::Autolock lock(mMutex);
- // empty/invalid rects are not allowed
- if (rect->isEmpty())
- return BAD_VALUE;
+ Rect realRect;
+ if (rect == NULL || rect->isEmpty()) {
+ realRect = Rect(0, 0);
+ } else {
+ realRect = *rect;
+ }
status_t err = mSurfaceTexture->setCrop(*rect);
- LOGE_IF(err, "ISurfaceTexture::setCrop(...) returned %s",
- strerror(-err));
+ LOGE_IF(err, "ISurfaceTexture::setCrop(...) returned %s", strerror(-err));
return err;
}
@@ -280,7 +285,10 @@
mReqHeight = h;
mReqFormat = format;
- return NO_ERROR;
+ status_t err = mSurfaceTexture->setCrop(Rect(0, 0));
+ LOGE_IF(err, "ISurfaceTexture::setCrop(...) returned %s", strerror(-err));
+
+ return err;
}
int SurfaceTextureClient::setBuffersTransform(int transform)
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index e21bab7..1e9bd74 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -827,13 +827,15 @@
int Surface::crop(Rect const* rect)
{
- // empty/invalid rects are not allowed
- if (rect->isEmpty())
- return BAD_VALUE;
-
Mutex::Autolock _l(mSurfaceLock);
// TODO: validate rect size
- mNextBufferCrop = *rect;
+
+ if (rect == NULL || rect->isEmpty()) {
+ mNextBufferCrop = Rect(0,0);
+ } else {
+ mNextBufferCrop = *rect;
+ }
+
return NO_ERROR;
}
@@ -884,6 +886,9 @@
// EGLConfig validation.
mFormat = format;
}
+
+ mNextBufferCrop = Rect(0,0);
+
return NO_ERROR;
}
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index 73ff230..7197ad7 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -4141,6 +4141,38 @@
}
}
+// Normalize a string for output
+String8 ResTable::normalizeForOutput( const char *input )
+{
+ String8 ret;
+ char buff[2];
+ buff[1] = '\0';
+
+ while (*input != '\0') {
+ switch (*input) {
+ // All interesting characters are in the ASCII zone, so we are making our own lives
+ // easier by scanning the string one byte at a time.
+ case '\\':
+ ret += "\\\\";
+ break;
+ case '\n':
+ ret += "\\n";
+ break;
+ case '"':
+ ret += "\\\"";
+ break;
+ default:
+ buff[0] = *input;
+ ret += buff;
+ break;
+ }
+
+ input++;
+ }
+
+ return ret;
+}
+
void ResTable::print_value(const Package* pkg, const Res_value& value) const
{
if (value.dataType == Res_value::TYPE_NULL) {
@@ -4154,13 +4186,13 @@
const char* str8 = pkg->header->values.string8At(
value.data, &len);
if (str8 != NULL) {
- printf("(string8) \"%s\"\n", str8);
+ printf("(string8) \"%s\"\n", normalizeForOutput(str8).string());
} else {
const char16_t* str16 = pkg->header->values.stringAt(
value.data, &len);
if (str16 != NULL) {
printf("(string16) \"%s\"\n",
- String8(str16, len).string());
+ normalizeForOutput(String8(str16, len).string()).string());
} else {
printf("(string) null\n");
}
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index ad9a94f..b1bd828 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -778,6 +778,7 @@
// called by a new thread using the same thread ID as this one.
self->mThread = thread_id_t(-1);
self->mThreadExitedCondition.broadcast();
+ self->mThread = thread_id_t(-1); // thread id could be reused
self->mLock.unlock();
break;
}
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 7ac6f92..a1cb23a 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -82,6 +82,11 @@
if (ggl_unlikely(gEGLErrorKey == -1))
return EGL_SUCCESS;
GLint error = (GLint)pthread_getspecific(gEGLErrorKey);
+ if (error == 0) {
+ // The TLS key has been created by another thread, but the value for
+ // this thread has not been initialized.
+ return EGL_SUCCESS;
+ }
pthread_setspecific(gEGLErrorKey, (void*)EGL_SUCCESS);
return error;
}
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 8977fbf..3dc8c03 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -389,10 +389,9 @@
}
static inline void clearError() {
- if (gEGLThreadLocalStorageKey != -1) {
- tls_t* tls = getTLS();
- tls->error = EGL_SUCCESS;
- }
+ // This must clear the error from all the underlying EGL implementations as
+ // well as the EGL wrapper layer.
+ eglGetError();
}
template<typename T>
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 3730739..fde8e67 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -56,6 +56,8 @@
mNeedsBlending(true),
mNeedsDithering(false),
mSecure(false),
+ mProtectedByApp(false),
+ mProtectedByDRM(false),
mTextureManager(),
mBufferManager(mTextureManager),
mWidth(0), mHeight(0), mNeedsScaling(false), mFixedSize(false)
@@ -150,8 +152,7 @@
// the layer is not on screen anymore. free as much resources as possible
mFreezeLock.clear();
- EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
- mBufferManager.destroy(dpy);
+ // Free our own reference to ISurface
mSurface.clear();
Mutex::Autolock _l(mLock);
@@ -191,6 +192,8 @@
mReqHeight = h;
mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
+ mProtectedByApp = (flags & ISurfaceComposer::eProtectedByApp) ? true : false;
+ mProtectedByDRM = (flags & ISurfaceComposer::eProtectedByDRM) ? true : false;
mNeedsBlending = (info.h_alpha - info.l_alpha) > 0 &&
(flags & ISurfaceComposer::eOpaque) == 0;
@@ -476,6 +479,10 @@
// request EGLImage for all buffers
usage |= GraphicBuffer::USAGE_HW_TEXTURE;
}
+ if (mProtectedByApp || mProtectedByDRM) {
+ // need a hardware-protected path to external video sink
+ usage |= GraphicBuffer::USAGE_PROTECTED;
+ }
return usage;
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 2908119..d9a8be3 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -79,6 +79,8 @@
virtual bool needsDithering() const { return mNeedsDithering; }
virtual bool needsFiltering() const;
virtual bool isSecure() const { return mSecure; }
+ virtual bool isProtectedByApp() const { return mProtectedByApp; }
+ virtual bool isProtectedByDRM() const { return mProtectedByDRM; }
virtual sp<Surface> createSurface() const;
virtual status_t ditch();
virtual void onRemoved();
@@ -218,7 +220,9 @@
bool mNeedsDithering;
// page-flip thread (currently main thread)
- bool mSecure;
+ bool mSecure; // no screenshots
+ bool mProtectedByApp; // application requires protected path to external sink
+ bool mProtectedByDRM; // DRM agent requires protected path to external sink
Region mPostedDirtyRegion;
// page-flip thread and transaction thread (currently main thread)
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 8d83f0b..86057f8 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -498,11 +498,9 @@
}
void LayerBase::setBufferCrop(const Rect& crop) {
- if (!crop.isEmpty()) {
- if (mBufferCrop != crop) {
- mBufferCrop = crop;
- mFlinger->invalidateHwcGeometry();
- }
+ if (mBufferCrop != crop) {
+ mBufferCrop = crop;
+ mFlinger->invalidateHwcGeometry();
}
}
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 8ed4749..184edd7 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -196,6 +196,18 @@
*/
virtual bool isSecure() const { return false; }
+ /**
+ * isProtectedByApp - true if application says this surface is protected, that
+ * is if it requires a hardware-protected data path to an external sink.
+ */
+ virtual bool isProtectedByApp() const { return false; }
+
+ /**
+ * isProtectedByDRM - true if DRM agent says this surface is protected, that
+ * is if it requires a hardware-protected data path to an external sink.
+ */
+ virtual bool isProtectedByDRM() const { return false; }
+
/** Called from the main thread, when the surface is removed from the
* draw list */
virtual status_t ditch() { return NO_ERROR; }
diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp
index 11f8feb..f79166d 100644
--- a/services/surfaceflinger/LayerDim.cpp
+++ b/services/surfaceflinger/LayerDim.cpp
@@ -30,29 +30,12 @@
namespace android {
// ---------------------------------------------------------------------------
-bool LayerDim::sUseTexture;
-GLuint LayerDim::sTexId;
-EGLImageKHR LayerDim::sImage;
-int32_t LayerDim::sWidth;
-int32_t LayerDim::sHeight;
-
-// ---------------------------------------------------------------------------
-
LayerDim::LayerDim(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client)
: LayerBaseClient(flinger, display, client)
{
}
-void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h)
-{
- sTexId = -1;
- sImage = EGL_NO_IMAGE_KHR;
- sWidth = w;
- sHeight = h;
- sUseTexture = false;
-}
-
LayerDim::~LayerDim()
{
}
@@ -84,15 +67,7 @@
#endif
glDisable(GL_TEXTURE_2D);
- GLshort w = sWidth;
- GLshort h = sHeight;
- const GLshort vertices[4][2] = {
- { 0, 0 },
- { 0, h },
- { w, h },
- { w, 0 }
- };
- glVertexPointer(2, GL_SHORT, 0, vertices);
+ glVertexPointer(2, GL_FLOAT, 0, mVertices);
while (it != end) {
const Rect& r = *it++;
diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h
index f032314..75f9a89 100644
--- a/services/surfaceflinger/LayerDim.h
+++ b/services/surfaceflinger/LayerDim.h
@@ -31,22 +31,17 @@
class LayerDim : public LayerBaseClient
{
- static bool sUseTexture;
- static GLuint sTexId;
- static EGLImageKHR sImage;
- static int32_t sWidth;
- static int32_t sHeight;
public:
LayerDim(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client);
virtual ~LayerDim();
virtual void onDraw(const Region& clip) const;
- virtual bool needsBlending() const { return true; }
- virtual bool isSecure() const { return false; }
+ virtual bool needsBlending() const { return true; }
+ virtual bool isSecure() const { return false; }
+ virtual bool isProtectedByApp() const { return false; }
+ virtual bool isProtectedByDRM() const { return false; }
virtual const char* getTypeId() const { return "LayerDim"; }
-
- static void initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h);
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 87b66ea..fd3f0c2 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -259,8 +259,6 @@
glLoadIdentity();
glOrthof(0, w, h, 0, 0, 1);
- LayerDim::initDimmer(this, w, h);
-
mReadyToRunBarrier.open();
/*