Merge "Change "more" button to call InputMethodConfigure in Settings"
diff --git a/include/binder/IPCThreadState.h b/include/binder/IPCThreadState.h
index b54718f..3378d97 100644
--- a/include/binder/IPCThreadState.h
+++ b/include/binder/IPCThreadState.h
@@ -33,6 +33,7 @@
{
public:
static IPCThreadState* self();
+ static IPCThreadState* selfOrNull(); // self(), but won't instantiate
sp<ProcessState> process();
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index cef439c..2df8ca3 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -249,7 +249,7 @@
uint32_t *pWidth, uint32_t *pHeight,
uint32_t *pFormat, uint32_t *pUsage) const;
- static void cleanCachedSurfaces();
+ static void cleanCachedSurfacesLocked();
class BufferInfo {
uint32_t mWidth;
diff --git a/include/utils/CallStack.h b/include/utils/CallStack.h
index c2c8ce5..8817120 100644
--- a/include/utils/CallStack.h
+++ b/include/utils/CallStack.h
@@ -50,7 +50,7 @@
void clear();
- void update(int32_t ignoreDepth=0, int32_t maxDepth=MAX_DEPTH);
+ void update(int32_t ignoreDepth=1, int32_t maxDepth=MAX_DEPTH);
// Dump a stack trace to the log
void dump(const char* prefix = 0) const;
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 13c58f0..95cfddf 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -318,6 +318,16 @@
goto restart;
}
+IPCThreadState* IPCThreadState::selfOrNull()
+{
+ if (gHaveTLS) {
+ const pthread_key_t k = gTLS;
+ IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
+ return st;
+ }
+ return NULL;
+}
+
void IPCThreadState::shutdown()
{
gShutdown = true;
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index 9467a4c..aa0c2e8 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -384,7 +384,7 @@
Mutex Surface::sCachedSurfacesLock;
-DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces(wp<Surface>(0));
+DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces;
sp<Surface> Surface::readFromParcel(const Parcel& data) {
Mutex::Autolock _l(sCachedSurfacesLock);
@@ -397,13 +397,13 @@
if (surface->mSurface == 0) {
surface = 0;
}
- cleanCachedSurfaces();
+ cleanCachedSurfacesLocked();
return surface;
}
// Remove the stale entries from the surface cache. This should only be called
// with sCachedSurfacesLock held.
-void Surface::cleanCachedSurfaces() {
+void Surface::cleanCachedSurfacesLocked() {
for (int i = sCachedSurfaces.size()-1; i >= 0; --i) {
wp<Surface> s(sCachedSurfaces.valueAt(i));
if (s == 0 || s.promote() == 0) {
@@ -489,6 +489,9 @@
LOGE("[Surface] using an invalid surface, "
"identity=%u should be %d",
mIdentity, identity);
+ CallStack stack;
+ stack.update();
+ stack.dump("Surface");
return NO_INIT;
}
@@ -497,6 +500,9 @@
if (err != NO_ERROR) {
LOGE("surface (identity=%u) is invalid, err=%d (%s)",
mIdentity, err, strerror(-err));
+ CallStack stack;
+ stack.update();
+ stack.dump("Surface");
return err;
}
diff --git a/opengl/tests/hwc/hwc_stress.cpp b/opengl/tests/hwc/hwc_stress.cpp
index 35e53ab..580eb83 100644
--- a/opengl/tests/hwc/hwc_stress.cpp
+++ b/opengl/tests/hwc/hwc_stress.cpp
@@ -202,18 +202,19 @@
};
// File scope constants
-static const struct {
+static const struct graphicFormat {
unsigned int format;
const char *desc;
+ unsigned int wMod, hMod; // Width/height mod this value must equal zero
} graphicFormat[] = {
- {HAL_PIXEL_FORMAT_RGBA_8888, "RGBA8888"},
- {HAL_PIXEL_FORMAT_RGBX_8888, "RGBX8888"},
- {HAL_PIXEL_FORMAT_RGB_888, "RGB888"},
- {HAL_PIXEL_FORMAT_RGB_565, "RGB565"},
- {HAL_PIXEL_FORMAT_BGRA_8888, "BGRA8888"},
- {HAL_PIXEL_FORMAT_RGBA_5551, "RGBA5551"},
- {HAL_PIXEL_FORMAT_RGBA_4444, "RGBA4444"},
- {HAL_PIXEL_FORMAT_YV12, "YV12"},
+ {HAL_PIXEL_FORMAT_RGBA_8888, "RGBA8888", 1, 1},
+ {HAL_PIXEL_FORMAT_RGBX_8888, "RGBX8888", 1, 1},
+ {HAL_PIXEL_FORMAT_RGB_888, "RGB888", 1, 1},
+ {HAL_PIXEL_FORMAT_RGB_565, "RGB565", 1, 1},
+ {HAL_PIXEL_FORMAT_BGRA_8888, "BGRA8888", 1, 1},
+ {HAL_PIXEL_FORMAT_RGBA_5551, "RGBA5551", 1, 1},
+ {HAL_PIXEL_FORMAT_RGBA_4444, "RGBA4444", 1, 1},
+ {HAL_PIXEL_FORMAT_YV12, "YV12", 2, 2},
};
const unsigned int blendingOps[] = {
HWC_BLENDING_NONE,
@@ -478,7 +479,7 @@
exit(20);
}
- // Prandomly select a subset of frames to be used by this pass.
+ // Prandomly select a subset of frames to be used by this pass.
vector <vector <sp<GraphicBuffer> > > selectedFrames;
selectedFrames = vectorRandSelect(frames, list->numHwLayers);
@@ -749,7 +750,6 @@
{
unsigned char* buf = NULL;
status_t err;
- unsigned int numPixels = gBuf->getWidth() * gBuf->getHeight();
uint32_t pixel;
// RGB 2 YUV conversion ratios
@@ -835,9 +835,16 @@
exit(51);
}
- for (unsigned int n1 = 0; n1 < numPixels; n1++) {
- memmove(buf, &pixel, attrib->bytes);
- buf += attrib->bytes;
+ for (unsigned int row = 0; row < gBuf->getHeight(); row++) {
+ for (unsigned int col = 0; col < gBuf->getWidth(); col++) {
+ memmove(buf, &pixel, attrib->bytes);
+ buf += attrib->bytes;
+ }
+ for (unsigned int pad = 0;
+ pad < (gBuf->getStride() - gBuf->getWidth()) * attrib->bytes;
+ pad++) {
+ *buf++ = testRandMod(256);
+ }
}
err = gBuf->unlock();
@@ -856,14 +863,13 @@
const struct yuvAttrib {
int format;
- size_t padWidth;
bool planar;
unsigned int uSubSampX;
unsigned int uSubSampY;
unsigned int vSubSampX;
unsigned int vSubSampY;
} yuvAttributes[] = {
- { HAL_PIXEL_FORMAT_YV12, 16, true, 2, 2, 2, 2},
+ { HAL_PIXEL_FORMAT_YV12, true, 2, 2, 2, 2},
};
const struct yuvAttrib *attrib;
@@ -879,12 +885,6 @@
assert(attrib->planar == true); // So far, only know how to handle planar
- // If needed round width up to pad size
- if (width % attrib->padWidth) {
- width += attrib->padWidth - (width % attrib->padWidth);
- }
- assert((width % attrib->padWidth) == 0);
-
err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
if (err != 0) {
testPrintE("fillColor lock failed: %d", err);
@@ -892,23 +892,35 @@
}
// Fill in Y component
- for (unsigned int x = 0; x < width; x++) {
- for (unsigned int y = 0; y < height; y++) {
- *buf++ = (x < gBuf->getWidth()) ? (255 * color.y()) : 0;
+ for (unsigned int row = 0; row < height; row++) {
+ for (unsigned int col = 0; col < width; col++) {
+ *buf++ = 255 * color.y();
+ }
+ for (unsigned int pad = 0; pad < gBuf->getStride() - gBuf->getWidth();
+ pad++) {
+ *buf++ = testRandMod(256);
}
}
// Fill in U component
- for (unsigned int x = 0; x < width; x += attrib->uSubSampX) {
- for (unsigned int y = 0; y < height; y += attrib->uSubSampY) {
- *buf++ = (x < gBuf->getWidth()) ? (255 * color.u()) : 0;
+ for (unsigned int row = 0; row < height; row += attrib->uSubSampY) {
+ for (unsigned int col = 0; col < width; col += attrib->uSubSampX) {
+ *buf++ = 255 * color.u();
+ }
+ for (unsigned int pad = 0; pad < gBuf->getStride() - gBuf->getWidth();
+ pad += attrib->uSubSampX) {
+ *buf++ = testRandMod(256);
}
}
// Fill in V component
- for (unsigned int x = 0; x < width; x += attrib->vSubSampX) {
- for (unsigned int y = 0; y < height; y += attrib->vSubSampY) {
- *buf++ = (x < gBuf->getWidth()) ? (255 * color.v()) : 0;
+ for (unsigned int row = 0; row < height; row += attrib->vSubSampY) {
+ for (unsigned int col = 0; col < width; col += attrib->vSubSampX) {
+ *buf++ = 255 * color.v();
+ }
+ for (unsigned int pad = 0; pad < gBuf->getStride() - gBuf->getWidth();
+ pad += attrib->vSubSampX) {
+ *buf++ = testRandMod(256);
}
}
@@ -989,7 +1001,7 @@
eglQuerySurface(dpy, surface, EGL_HEIGHT, &height);
checkEglError("eglQuerySurface");
- fprintf(stderr, "Window dimensions: %d x %d", width, height);
+ testPrintI("Window dimensions: %d x %d", width, height);
printGLString("Version", GL_VERSION);
printGLString("Vendor", GL_VENDOR);
@@ -1017,7 +1029,7 @@
*
* Creates an array of graphic buffers, within the global variable
* named frames. The graphic buffers are contained within a vector of
- * verctors. All the graphic buffers in a particular row are of the same
+ * vectors. All the graphic buffers in a particular row are of the same
* format and dimension. Each graphic buffer is uniformly filled with a
* prandomly selected color. It is likely that each buffer, even
* in the same row, will be filled with a unique color.
@@ -1039,11 +1051,22 @@
for (unsigned int row = 0; row < rows; row++) {
// All frames within a row have to have the same format and
// dimensions. Width and height need to be >= 1.
- int format = graphicFormat[testRandMod(NUMA(graphicFormat))].format;
+ unsigned int formatIdx = testRandMod(NUMA(graphicFormat));
+ const struct graphicFormat *formatPtr = &graphicFormat[formatIdx];
+ int format = formatPtr->format;
+
+ // Pick width and height, which must be >= 1 and the size
+ // mod the wMod/hMod value must be equal to 0.
size_t w = (width * maxSizeRatio) * testRandFract();
size_t h = (height * maxSizeRatio) * testRandFract();
w = max(1u, w);
h = max(1u, h);
+ if ((w % formatPtr->wMod) != 0) {
+ w += formatPtr->wMod - (w % formatPtr->wMod);
+ }
+ if ((h % formatPtr->hMod) != 0) {
+ h += formatPtr->hMod - (h % formatPtr->hMod);
+ }
if (verbose) {
testPrintI(" frame %u width: %u height: %u format: %u %s",
row, w, h, format, graphicFormat2str(format));
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 74d1ac9..8a00a2e 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -35,7 +35,6 @@
LOCAL_SHARED_LIBRARIES := \
libcutils \
- libpixelflinger \
libhardware \
libutils \
libEGL \
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 80aef5f..fde68f6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -83,8 +83,28 @@
sharedClient, token, mBufferManager.getDefaultBufferCount(),
getIdentity());
- status_t err = mUserClientRef.setToken(userClient, lcblk, token);
+ sp<UserClient> ourClient(mUserClientRef.getClient());
+
+ /*
+ * Here it is guaranteed that userClient != ourClient
+ * (see UserClient::getTokenForSurface()).
+ *
+ * We release the token used by this surface in ourClient below.
+ * This should be safe to do so now, since this layer won't be attached
+ * to this client, it should be okay to reuse that id.
+ *
+ * If this causes problems, an other solution would be to keep a list
+ * of all the {UserClient, token} ever used and release them when the
+ * Layer is destroyed.
+ *
+ */
+
+ if (ourClient != 0) {
+ ourClient->detachLayer(this);
+ }
+
+ status_t err = mUserClientRef.setToken(userClient, lcblk, token);
LOGE_IF(err != NO_ERROR,
"ClientRef::setToken(%p, %p, %u) failed",
userClient.get(), lcblk.get(), token);
@@ -226,9 +246,10 @@
void Layer::setPerFrameData(hwc_layer_t* hwcl) {
sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
if (buffer == NULL) {
- // this situation can happen if we ran out of memory for instance.
- // not much we can do. continue to use whatever texture was bound
- // to this context.
+ // this can happen if the client never drew into this layer yet,
+ // or if we ran out of memory. In that case, don't let
+ // HWC handle it.
+ hwcl->flags |= HWC_SKIP_LAYER;
hwcl->handle = NULL;
return;
}
@@ -561,12 +582,20 @@
}
// we retired a buffer, which becomes the new front buffer
+
+ const bool noActiveBuffer = !mBufferManager.hasActiveBuffer();
if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) {
LOGE("retireAndLock() buffer index (%d) out of range", int(buf));
mPostedDirtyRegion.clear();
return;
}
+ if (noActiveBuffer) {
+ // we didn't have an active buffer, we need to recompute
+ // our visible region
+ recomputeVisibleRegions = true;
+ }
+
sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
if (newFrontBuffer != NULL) {
// get the dirty region
@@ -775,7 +804,7 @@
Layer::BufferManager::BufferManager(TextureManager& tm)
: mNumBuffers(NUM_BUFFERS), mTextureManager(tm),
- mActiveBuffer(-1), mFailover(false)
+ mActiveBufferIndex(-1), mFailover(false)
{
}
@@ -790,10 +819,10 @@
if (size < mNumBuffers) {
// Move the active texture into slot 0
- BufferData activeBufferData = mBufferData[mActiveBuffer];
- mBufferData[mActiveBuffer] = mBufferData[0];
+ BufferData activeBufferData = mBufferData[mActiveBufferIndex];
+ mBufferData[mActiveBufferIndex] = mBufferData[0];
mBufferData[0] = activeBufferData;
- mActiveBuffer = 0;
+ mActiveBufferIndex = 0;
// Free the buffers that are no longer needed.
for (size_t i = size; i < mNumBuffers; i++) {
@@ -839,33 +868,33 @@
}
status_t Layer::BufferManager::setActiveBufferIndex(size_t index) {
- mActiveBuffer = index;
+ BufferData const * const buffers = mBufferData;
+ Mutex::Autolock _l(mLock);
+ mActiveBuffer = buffers[index].buffer;
+ mActiveBufferIndex = index;
return NO_ERROR;
}
size_t Layer::BufferManager::getActiveBufferIndex() const {
- return mActiveBuffer;
+ return mActiveBufferIndex;
}
Texture Layer::BufferManager::getActiveTexture() const {
Texture res;
- if (mFailover || mActiveBuffer<0) {
+ if (mFailover || mActiveBufferIndex<0) {
res = mFailoverTexture;
} else {
- static_cast<Image&>(res) = mBufferData[mActiveBuffer].texture;
+ static_cast<Image&>(res) = mBufferData[mActiveBufferIndex].texture;
}
return res;
}
sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const {
- sp<GraphicBuffer> result;
- const ssize_t activeBuffer = mActiveBuffer;
- if (activeBuffer >= 0) {
- BufferData const * const buffers = mBufferData;
- Mutex::Autolock _l(mLock);
- result = buffers[activeBuffer].buffer;
- }
- return result;
+ return mActiveBuffer;
+}
+
+bool Layer::BufferManager::hasActiveBuffer() const {
+ return mActiveBufferIndex >= 0;
}
sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index)
@@ -910,7 +939,7 @@
const sp<GraphicBuffer>& buffer)
{
status_t err = NO_INIT;
- ssize_t index = mActiveBuffer;
+ ssize_t index = mActiveBufferIndex;
if (index >= 0) {
if (!mFailover) {
Image& texture(mBufferData[index].texture);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 30021d3..5444d2f 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -164,7 +164,8 @@
size_t mNumBuffers;
Texture mFailoverTexture;
TextureManager& mTextureManager;
- ssize_t mActiveBuffer;
+ ssize_t mActiveBufferIndex;
+ sp<GraphicBuffer> mActiveBuffer;
bool mFailover;
static status_t destroyTexture(Image* tex, EGLDisplay dpy);
@@ -188,6 +189,8 @@
size_t getActiveBufferIndex() const;
// return the active buffer
sp<GraphicBuffer> getActiveBuffer() const;
+ // return wether we have an active buffer
+ bool hasActiveBuffer() const;
// return the active texture (or fail-over)
Texture getActiveTexture() const;
// frees resources associated with all buffers
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 61d08aa..825d90b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -395,6 +395,7 @@
logger.log(GraphicLog::SF_REPAINT_DONE, index);
} else {
// pretend we did the post
+ hw.compositionComplete();
unlockClients();
usleep(16667); // 60 fps period
}
@@ -1023,6 +1024,8 @@
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
}
}
@@ -2120,6 +2123,7 @@
// invert everything, b/c glReadPixel() below will invert the FB
glViewport(0, 0, sw, sh);
+ glScissor(0, 0, sw, sh);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
@@ -2129,6 +2133,7 @@
// redraw the screen entirely...
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
+
const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
const size_t count = layers.size();
for (size_t i=0 ; i<count ; ++i) {
@@ -2166,7 +2171,6 @@
result = NO_MEMORY;
}
}
-
glEnable(GL_SCISSOR_TEST);
glViewport(0, 0, hw_w, hw_h);
glMatrixMode(GL_PROJECTION);
@@ -2182,6 +2186,9 @@
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
glDeleteRenderbuffersOES(1, &tname);
glDeleteFramebuffersOES(1, &name);
+
+ hw.compositionComplete();
+
return result;
}