Merge change 24337 into eclair
* changes:
Fix issue 2107584: media server crash when AudioFlinger fails to allocate memory for track control block.
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index e66b00f..f425f6b 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -552,17 +552,6 @@
CameraParameters params(mHardware->getParameters());
params.getPreviewSize(&w, &h);
- const char *format = params.getPreviewFormat();
- int fmt;
- if (!strcmp(format, "yuv422i-yuyv"))
- fmt = OVERLAY_FORMAT_YCbYCr_422_I;
- else if (!strcmp(format, "rgb565"))
- fmt = OVERLAY_FORMAT_RGB_565;
- else {
- LOGE("Invalid preview format for overlays");
- return -EINVAL;
- }
-
if ( w != mOverlayW || h != mOverlayH )
{
// Force the destruction of any previous overlay
@@ -574,7 +563,7 @@
status_t ret = NO_ERROR;
if (mSurface != 0) {
if (mOverlayRef.get() == NULL) {
- mOverlayRef = mSurface->createOverlay(w, h, fmt);
+ mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT);
if ( mOverlayRef.get() == NULL )
{
LOGE("Overlay Creation Failed!");
@@ -1112,8 +1101,7 @@
}
CameraParameters p(params);
- mHardware->setParameters(p);
- return NO_ERROR;
+ return mHardware->setParameters(p);
}
// get preview/capture parameters - key/value pairs
diff --git a/cmds/keystore/Android.mk b/cmds/keystore/Android.mk
index 3daf44e..8804636 100644
--- a/cmds/keystore/Android.mk
+++ b/cmds/keystore/Android.mk
@@ -4,7 +4,7 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- netkeystore.c keymgmt.c
+ netkeystore.c netkeystore_main.c keymgmt.c
LOCAL_C_INCLUDES := \
$(call include-path-for, system-core)/cutils \
diff --git a/cmds/keystore/keymgmt.c b/cmds/keystore/keymgmt.c
index 69e0380..b5ace86 100644
--- a/cmds/keystore/keymgmt.c
+++ b/cmds/keystore/keymgmt.c
@@ -385,7 +385,10 @@
return -1;
}
while ((de = readdir(d))) {
- if (unlink(de->d_name) != 0) ret = -1;
+ char *dirname = de->d_name;
+ if (strcmp(".", dirname) == 0) continue;
+ if (strcmp("..", dirname) == 0) continue;
+ if (unlink(dirname) != 0) ret = -1;
}
closedir(d);
state = UNINITIALIZED;
diff --git a/cmds/keystore/netkeystore.c b/cmds/keystore/netkeystore.c
index 82a92c3..83c7871 100644
--- a/cmds/keystore/netkeystore.c
+++ b/cmds/keystore/netkeystore.c
@@ -14,8 +14,6 @@
** limitations under the License.
*/
-#define LOG_TAG "keystore"
-
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
@@ -247,7 +245,7 @@
reply->retcode = reset_keystore();
}
-static void execute(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
+void execute(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
{
uint32_t cmd_max = sizeof(cmds)/sizeof(struct cmdinfo);
@@ -309,7 +307,7 @@
return 0;
}
-static int parse_cmd(int argc, const char **argv, LPC_MARSHAL *cmd)
+int parse_cmd(int argc, const char **argv, LPC_MARSHAL *cmd)
{
uint32_t i, len = 0;
uint32_t cmd_max = sizeof(cmds)/sizeof(cmds[0]);
@@ -335,30 +333,30 @@
}
}
-static int shell_command(const int argc, const char **argv)
+int shell_command(const int argc, const char **argv)
{
int fd, i;
LPC_MARSHAL cmd;
- if (parse_cmd(argc, argv , &cmd)) {
+ if (parse_cmd(argc, argv, &cmd)) {
fprintf(stderr, "Incorrect command or command line is too long.\n");
- exit(1);
+ return -1;
}
fd = socket_local_client(SOCKET_PATH,
ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_STREAM);
if (fd == -1) {
fprintf(stderr, "Keystore service is not up and running.\n");
- exit(1);
+ return -1;
}
if (write_marshal(fd, &cmd)) {
fprintf(stderr, "Incorrect command or command line is too long.\n");
- exit(1);
+ return -1;
}
if (read_marshal(fd, &cmd)) {
fprintf(stderr, "Failed to read the result.\n");
- exit(1);
+ return -1;
}
cmd.data[cmd.len] = 0;
fprintf(stdout, "%s\n", (cmd.retcode == 0) ? "Succeeded!" : "Failed!");
@@ -367,30 +365,26 @@
return 0;
}
-int main(const int argc, const char *argv[])
+int server_main(const int argc, const char *argv[])
{
struct sockaddr addr;
socklen_t alen;
int lsocket, s;
LPC_MARSHAL cmd, reply;
- if (argc > 1) {
- return shell_command(argc - 1, argv + 1);
- }
-
if (init_keystore(KEYSTORE_DIR)) {
LOGE("Can not initialize the keystore, the directory exist?\n");
- exit(1);
+ return -1;
}
lsocket = android_get_control_socket(SOCKET_PATH);
if (lsocket < 0) {
LOGE("Failed to get socket from environment: %s\n", strerror(errno));
- exit(1);
+ return -1;
}
if (listen(lsocket, 5)) {
LOGE("Listen on socket failed: %s\n", strerror(errno));
- exit(1);
+ return -1;
}
fcntl(lsocket, F_SETFD, FD_CLOEXEC);
memset(&reply, 0, sizeof(LPC_MARSHAL));
diff --git a/cmds/keystore/netkeystore.h b/cmds/keystore/netkeystore.h
index d80ddae..e2ffd8b 100644
--- a/cmds/keystore/netkeystore.h
+++ b/cmds/keystore/netkeystore.h
@@ -25,6 +25,10 @@
#include "common.h"
+// for testing
+int parse_cmd(int argc, const char **argv, LPC_MARSHAL *cmd);
+void execute(LPC_MARSHAL *cmd, LPC_MARSHAL *reply);
+
static inline int readx(int s, void *_buf, int count)
{
char *buf = _buf;
diff --git a/cmds/keystore/netkeystore_main.c b/cmds/keystore/netkeystore_main.c
new file mode 100644
index 0000000..606e67a
--- /dev/null
+++ b/cmds/keystore/netkeystore_main.c
@@ -0,0 +1,29 @@
+/*
+** Copyright 2009, 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.
+*/
+
+#define LOG_TAG "keystore"
+
+int shell_command(const int argc, const char **argv);
+int server_main(const int argc, const char *argv[]);
+
+int main(const int argc, const char *argv[])
+{
+ if (argc > 1) {
+ return shell_command(argc - 1, argv + 1);
+ } else {
+ return server_main(argc, argv);
+ }
+}
diff --git a/cmds/keystore/tests/Android.mk b/cmds/keystore/tests/Android.mk
index 33541cc..e0a776a 100644
--- a/cmds/keystore/tests/Android.mk
+++ b/cmds/keystore/tests/Android.mk
@@ -16,7 +16,7 @@
ifdef KEYSTORE_TESTS
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= netkeystore_test.c ../keymgmt.c
+LOCAL_SRC_FILES:= netkeystore_test.c ../keymgmt.c ../netkeystore.c
LOCAL_SHARED_LIBRARIES := libcutils libssl
LOCAL_MODULE:= netkeystore_test
LOCAL_MODULE_TAGS := optional
diff --git a/cmds/keystore/tests/netkeystore_test.c b/cmds/keystore/tests/netkeystore_test.c
index 00390e0..ce79503 100644
--- a/cmds/keystore/tests/netkeystore_test.c
+++ b/cmds/keystore/tests/netkeystore_test.c
@@ -29,9 +29,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <cutils/log.h>
#include "common.h"
#include "keymgmt.h"
+#include "netkeystore.h"
+
+#define LOG_TAG "keystore_test"
typedef int FUNC_PTR();
typedef struct {
@@ -61,7 +65,9 @@
void teardown()
{
- reset_keystore();
+ if (reset_keystore() != 0) {
+ fprintf(stderr, "Can not reset the test directory %s\n", TEST_DIR);
+ }
rmdir(TEST_DIR);
}
@@ -74,7 +80,7 @@
FUNC_BODY(reset_keystore)
{
- chdir("/procx");
+ int ret = chdir("/proc");
if (reset_keystore() == 0) return -1;
chdir(TEST_DIR);
return EXIT_SUCCESS;
@@ -87,7 +93,8 @@
if (get_state() != UNLOCKED) return -1;
lock();
if (get_state() != LOCKED) return -1;
- reset_keystore();
+
+ if (reset_keystore() != 0) return -1;
if (get_state() != UNINITIALIZED) return -1;
return EXIT_SUCCESS;
}
@@ -218,6 +225,37 @@
return EXIT_SUCCESS;
}
+static int execute_cmd(int argc, const char *argv[], LPC_MARSHAL *cmd,
+ LPC_MARSHAL *reply)
+{
+ memset(cmd, 0, sizeof(LPC_MARSHAL));
+ memset(reply, 0, sizeof(LPC_MARSHAL));
+ if (parse_cmd(argc, argv, cmd)) return -1;
+ execute(cmd, reply);
+ return (reply->retcode ? -1 : 0);
+}
+
+FUNC_BODY(client_passwd)
+{
+ LPC_MARSHAL cmd, reply;
+ const char *set_passwd_cmds[2] = {"passwd", TEST_PASSWD};
+ const char *change_passwd_cmds[3] = {"passwd", TEST_PASSWD, TEST_NPASSWD};
+
+ if (execute_cmd(2, set_passwd_cmds, &cmd, &reply)) return -1;
+
+ lock();
+ if (unlock("55555555") == 0) return -1;
+ if (unlock(TEST_PASSWD) != 0) return -1;
+
+ if (execute_cmd(3, change_passwd_cmds, &cmd, &reply)) return -1;
+
+ lock();
+ if (unlock(TEST_PASSWD) == 0) return -1;
+ if (unlock(TEST_NPASSWD) != 0) return -1;
+
+ return EXIT_SUCCESS;
+}
+
TESTFUNC all_tests[] = {
FUNC_NAME(init_keystore),
FUNC_NAME(reset_keystore),
@@ -229,11 +267,13 @@
FUNC_NAME(get_key),
FUNC_NAME(remove_key),
FUNC_NAME(list_keys),
+ FUNC_NAME(client_passwd),
};
int main(int argc, char **argv) {
int i, ret;
for (i = 0 ; i < (int)(sizeof(all_tests)/sizeof(TESTFUNC)) ; ++i) {
+ LOGD("run %s...\n", all_tests[i].name);
setup();
if ((ret = all_tests[i].func()) != EXIT_SUCCESS) {
fprintf(stderr, "ERROR in function %s\n", all_tests[i].name);
diff --git a/include/private/ui/SharedBufferStack.h b/include/private/ui/SharedBufferStack.h
index 2bd5344..6181f55 100644
--- a/include/private/ui/SharedBufferStack.h
+++ b/include/private/ui/SharedBufferStack.h
@@ -85,6 +85,7 @@
public:
SharedBufferStack();
+ void init(int32_t identity);
status_t setDirtyRegion(int buffer, const Region& reg);
Region getDirtyRegion(int buffer) const;
@@ -93,12 +94,12 @@
volatile int32_t available; // number of dequeue-able buffers
volatile int32_t queued; // number of buffers waiting for post
volatile int32_t inUse; // buffer currently in use by SF
+ volatile status_t status; // surface's status code
// not part of the conditions
volatile int32_t reallocMask;
int32_t identity; // surface's identity (const)
- status_t status; // surface's status code
int32_t reserved32[13];
FlatRegion dirtyRegion[NUM_BUFFER_MAX]; // 12*4=48 bytes
};
@@ -114,7 +115,6 @@
status_t validate(size_t token) const;
uint32_t getIdentity(size_t token) const;
- status_t setIdentity(size_t token, uint32_t identity);
private:
friend class SharedBufferBase;
@@ -168,10 +168,11 @@
template <typename T>
status_t SharedBufferBase::waitForCondition(T condition)
{
+ const SharedBufferStack& stack( *mSharedStack );
SharedClient& client( *mSharedClient );
const nsecs_t TIMEOUT = s2ns(1);
Mutex::Autolock _l(client.lock);
- while (!condition()) {
+ while ((condition()==false) && (stack.status == NO_ERROR)) {
status_t err = client.cv.waitRelative(client.lock, TIMEOUT);
// handle errors and timeouts
@@ -195,7 +196,7 @@
}
}
}
- return NO_ERROR;
+ return stack.status;
}
@@ -261,13 +262,15 @@
class SharedBufferServer : public SharedBufferBase
{
public:
- SharedBufferServer(SharedClient* sharedClient, int surface, int num);
+ SharedBufferServer(SharedClient* sharedClient, int surface, int num,
+ int32_t identity);
ssize_t retireAndLock();
status_t unlock(int buffer);
+ void setStatus(status_t status);
status_t reallocate();
status_t assertReallocate(int buffer);
-
+
Region getDirtyRegion(int buffer) const;
private:
@@ -283,6 +286,12 @@
inline ssize_t operator()();
};
+ struct StatusUpdate : public UpdateBase {
+ const status_t status;
+ inline StatusUpdate(SharedBufferBase* sbb, status_t status);
+ inline ssize_t operator()();
+ };
+
struct ReallocateCondition : public ConditionBase {
int buf;
inline ReallocateCondition(SharedBufferBase* sbb, int buf);
diff --git a/include/utils/threads.h b/include/utils/threads.h
index e9b0788..f5304f7 100644
--- a/include/utils/threads.h
+++ b/include/utils/threads.h
@@ -90,6 +90,11 @@
ANDROID_TGROUP_MAX = ANDROID_TGROUP_FG_BOOST,
};
+typedef enum {
+ SP_BACKGROUND = 0,
+ SP_FOREGROUND = 1,
+} SchedPolicy;
+
// Create and run a new thread.
extern int androidCreateThread(android_thread_func_t, void *);
@@ -408,6 +413,9 @@
volatile bool mExitPending;
volatile bool mRunning;
sp<Thread> mHoldSelf;
+#if HAVE_ANDROID_OS
+ int mTid;
+#endif
};
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 651e7cf..d893f0a 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -103,10 +103,22 @@
}
// initialize EGL
- const EGLint attribs[] = {
+ EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_NONE, 0,
EGL_NONE
};
+
+ // debug: disable h/w rendering
+ char property[PROPERTY_VALUE_MAX];
+ if (property_get("debug.sf.hw", property, NULL) > 0) {
+ if (atoi(property) == 0) {
+ LOGW("H/W composition disabled");
+ attribs[2] = EGL_CONFIG_CAVEAT;
+ attribs[3] = EGL_SLOW_CONFIG;
+ }
+ }
+
EGLint w, h, dummy;
EGLint numConfigs=0;
EGLSurface surface;
@@ -193,7 +205,6 @@
mDpiY = mNativeWindow->ydpi;
mRefreshRate = fbDev->fps;
- char property[PROPERTY_VALUE_MAX];
/* Read density from build-specific ro.sf.lcd_density property
* except if it is overridden by qemu.sf.lcd_density.
*/
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index ecb6b32..6275910 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -49,13 +49,12 @@
Layer::Layer(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& c, int32_t i)
- : LayerBaseClient(flinger, display, c, i), lcblk(NULL),
+ : LayerBaseClient(flinger, display, c, i),
mSecure(false),
mNeedsBlending(true)
{
// no OpenGL operation is possible here, since we might not be
// in the OpenGL thread.
- lcblk = new SharedBufferServer(c->ctrlblk, i, NUM_BUFFERS);
mFrontBufferIndex = lcblk->getFrontBuffer();
}
@@ -63,8 +62,14 @@
{
destroy();
// the actual buffers will be destroyed here
- delete lcblk;
+}
+// called with SurfaceFlinger::mStateLock as soon as the layer is entered
+// in the purgatory list
+void Layer::onRemoved()
+{
+ // wake up the condition
+ lcblk->setStatus(NO_INIT);
}
void Layer::destroy()
@@ -79,7 +84,9 @@
eglDestroyImageKHR(dpy, mTextures[i].image);
mTextures[i].image = EGL_NO_IMAGE_KHR;
}
+ Mutex::Autolock _l(mLock);
mBuffers[i].clear();
+ mWidth = mHeight = 0;
}
mSurface.clear();
}
@@ -213,6 +220,16 @@
sp<SurfaceBuffer> Layer::requestBuffer(int index, int usage)
{
+ sp<Buffer> buffer;
+
+ // this ensures our client doesn't go away while we're accessing
+ // the shared area.
+ sp<Client> ourClient(client.promote());
+ if (ourClient == 0) {
+ // oops, the client is already gone
+ return buffer;
+ }
+
/*
* This is called from the client's Surface::dequeue(). This can happen
* at any time, especially while we're in the middle of using the
@@ -225,12 +242,21 @@
*/
status_t err = lcblk->assertReallocate(index);
LOGE_IF(err, "assertReallocate(%d) failed (%s)", index, strerror(-err));
+ if (err != NO_ERROR) {
+ // the surface may have died
+ return buffer;
+ }
- Mutex::Autolock _l(mLock);
- uint32_t w = mWidth;
- uint32_t h = mHeight;
-
- sp<Buffer>& buffer(mBuffers[index]);
+ uint32_t w, h;
+ { // scope for the lock
+ Mutex::Autolock _l(mLock);
+ w = mWidth;
+ h = mHeight;
+ buffer = mBuffers[index];
+ mBuffers[index].clear();
+ }
+
+
if (buffer->getStrongCount() == 1) {
err = buffer->reallocate(w, h, mFormat, usage, mBufferFlags);
} else {
@@ -253,8 +279,16 @@
}
if (err == NO_ERROR && buffer->handle != 0) {
- // texture is now dirty...
- mTextures[index].dirty = true;
+ Mutex::Autolock _l(mLock);
+ if (mWidth && mHeight) {
+ // and we have new buffer
+ mBuffers[index] = buffer;
+ // texture is now dirty...
+ mTextures[index].dirty = true;
+ } else {
+ // oops we got killed while we were allocating the buffer
+ buffer.clear();
+ }
}
return buffer;
}
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index 3b4489e..2e8173d 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -51,10 +51,6 @@
static const char* const typeID;
virtual char const* getTypeID() const { return typeID; }
virtual uint32_t getTypeInfo() const { return typeInfo; }
-
-
- SharedBufferServer* lcblk;
-
Layer(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i);
@@ -88,6 +84,8 @@
return mBuffers[mFrontBufferIndex];
}
+ virtual void onRemoved();
+
void reloadTexture(const Region& dirty);
sp<SurfaceBuffer> requestBuffer(int index, int usage);
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index 62e41b0..1f22488 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -642,9 +642,12 @@
LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i)
- : LayerBase(flinger, display), client(client),
+ : LayerBase(flinger, display), lcblk(NULL), client(client),
mIndex(i), mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
{
+ lcblk = new SharedBufferServer(
+ client->ctrlblk, i, NUM_BUFFERS,
+ mIdentity);
}
void LayerBaseClient::onFirstRef()
@@ -652,8 +655,6 @@
sp<Client> client(this->client.promote());
if (client != 0) {
client->bindLayer(this, mIndex);
- // Initialize this layer's identity
- client->ctrlblk->setIdentity(mIndex, mIdentity);
}
}
@@ -663,6 +664,7 @@
if (client != 0) {
client->free(mIndex);
}
+ delete lcblk;
}
int32_t LayerBaseClient::serverIndex() const
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index 78bb4bf..3a52240 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -292,13 +292,16 @@
virtual char const* getTypeID() const { return typeID; }
virtual uint32_t getTypeInfo() const { return typeInfo; }
+ // lcblk is (almost) only accessed from the main SF thread, in the places
+ // where it's not, a reference to Client must be held
+ SharedBufferServer* lcblk;
+
LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i);
virtual ~LayerBaseClient();
virtual void onFirstRef();
- wp<Client> client;
-// SharedBufferServer* lcblk;
+ const wp<Client> client;
inline uint32_t getIdentity() const { return mIdentity; }
inline int32_t clientIndex() const { return mIndex; }
@@ -308,6 +311,7 @@
sp<Surface> getSurface();
virtual sp<Surface> createSurface() const;
+ virtual void onRemoved() { }
class Surface : public BnSurface
{
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp
index 00abd5a..e14f35b 100644
--- a/libs/surfaceflinger/LayerBlur.cpp
+++ b/libs/surfaceflinger/LayerBlur.cpp
@@ -24,6 +24,7 @@
#include <GLES/gl.h>
#include <GLES/glext.h>
+#include "clz.h"
#include "BlurFilter.h"
#include "LayerBlur.h"
#include "SurfaceFlinger.h"
@@ -40,7 +41,8 @@
LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i)
: LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
- mRefreshCache(true), mCacheAge(0), mTextureName(-1U)
+ mRefreshCache(true), mCacheAge(0), mTextureName(-1U),
+ mWidthScale(1.0f), mHeightScale(1.0f)
{
}
@@ -164,11 +166,26 @@
bl.format = GGL_PIXEL_FORMAT_RGB_565;
bl.data = (GGLubyte*)pixels;
blurFilter(&bl, 8, 2);
-
- // NOTE: this works only because we have POT. we'd have to round the
- // texture size up, otherwise.
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
- GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+
+ if (mFlags & (DisplayHardware::NPOT_EXTENSION)) {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
+ GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+ mWidthScale = 1.0f / w;
+ mHeightScale =-1.0f / h;
+ mYOffset = 0;
+ } else {
+ GLuint tw = 1 << (31 - clz(w));
+ GLuint th = 1 << (31 - clz(h));
+ if (tw < w) tw <<= 1;
+ if (th < h) th <<= 1;
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0,
+ GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h,
+ GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+ mWidthScale = 1.0f / tw;
+ mHeightScale =-1.0f / th;
+ mYOffset = th-h;
+ }
free((void*)pixels);
}
@@ -184,7 +201,12 @@
glDisable(GL_BLEND);
}
- glDisable(GL_DITHER);
+ if (mFlags & DisplayHardware::SLOW_CONFIG) {
+ glDisable(GL_DITHER);
+ } else {
+ glEnable(GL_DITHER);
+ }
+
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -194,8 +216,8 @@
// This is a very rare scenario.
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
- glScalef(1.0f/w, -1.0f/h, 1);
- glTranslatef(-x, -y, 0);
+ glScalef(mWidthScale, mHeightScale, 1);
+ glTranslatef(-x, mYOffset - y, 0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FIXED, 0, mVertices);
glTexCoordPointer(2, GL_FIXED, 0, mVertices);
@@ -205,6 +227,7 @@
glScissor(r.left, sy, r.width(), r.height());
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
} else {
// NOTE: this is marginally faster with the software gl, because
// glReadPixels() reads the fb bottom-to-top, however we'll
@@ -221,8 +244,6 @@
}
}
}
-
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBlur.h b/libs/surfaceflinger/LayerBlur.h
index 0c3e6eb..bf36ae4 100644
--- a/libs/surfaceflinger/LayerBlur.h
+++ b/libs/surfaceflinger/LayerBlur.h
@@ -56,6 +56,9 @@
mutable bool mAutoRefreshPending;
nsecs_t mCacheAge;
mutable GLuint mTextureName;
+ mutable GLfloat mWidthScale;
+ mutable GLfloat mHeightScale;
+ mutable GLfloat mYOffset;
};
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 433b48e..bbfc54b 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -133,6 +133,14 @@
return false;
}
+void LayerBuffer::serverDestroy()
+{
+ sp<Source> source(clearSource());
+ if (source != 0) {
+ source->destroy();
+ }
+}
+
/**
* This creates a "buffer" source for this surface
*/
@@ -354,7 +362,7 @@
{
ISurface::BufferHeap buffers;
{ // scope for the lock
- Mutex::Autolock _l(mLock);
+ Mutex::Autolock _l(mBufferSourceLock);
buffers = mBufferHeap;
if (buffers.heap != 0) {
const size_t memorySize = buffers.heap->getSize();
@@ -379,7 +387,7 @@
void LayerBuffer::BufferSource::unregisterBuffers()
{
- Mutex::Autolock _l(mLock);
+ Mutex::Autolock _l(mBufferSourceLock);
mBufferHeap.heap.clear();
mBuffer.clear();
mLayer.invalidate();
@@ -387,13 +395,13 @@
sp<LayerBuffer::Buffer> LayerBuffer::BufferSource::getBuffer() const
{
- Mutex::Autolock _l(mLock);
+ Mutex::Autolock _l(mBufferSourceLock);
return mBuffer;
}
void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer)
{
- Mutex::Autolock _l(mLock);
+ Mutex::Autolock _l(mBufferSourceLock);
mBuffer = buffer;
}
@@ -413,7 +421,7 @@
status_t err = NO_ERROR;
NativeBuffer src(ourBuffer->getBuffer());
- const Rect& transformedBounds = mLayer.getTransformedBounds();
+ const Rect transformedBounds(mLayer.getTransformedBounds());
copybit_device_t* copybit = mBlitEngine;
if (copybit) {
@@ -493,7 +501,7 @@
}
}
- const Rect& transformedBounds = mLayer.getTransformedBounds();
+ const Rect transformedBounds(mLayer.getTransformedBounds());
const copybit_rect_t& drect =
reinterpret_cast<const copybit_rect_t&>(transformedBounds);
const State& s(mLayer.drawingState());
@@ -583,9 +591,7 @@
mOverlayHandle = overlay->getHandleRef(overlay);
- // NOTE: here it's okay to acquire a reference to "this"m as long as
- // the reference is not released before we leave the ctor.
- sp<OverlayChannel> channel = new OverlayChannel(this);
+ sp<OverlayChannel> channel = new OverlayChannel( &layer );
*overlayRef = new OverlayRef(mOverlayHandle, channel,
mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
@@ -601,7 +607,6 @@
void LayerBuffer::OverlaySource::onDraw(const Region& clip) const
{
- GLclampx color = 0x000018; //dark blue
GLclampx red = 0;
GLclampx green = 0;
GLclampx blue = 0x1818;
@@ -626,14 +631,14 @@
if (mVisibilityChanged || !mInitialized) {
mVisibilityChanged = false;
mInitialized = true;
- const Rect& bounds = mLayer.getTransformedBounds();
+ const Rect bounds(mLayer.getTransformedBounds());
int x = bounds.left;
int y = bounds.top;
int w = bounds.width();
int h = bounds.height();
// we need a lock here to protect "destroy"
- Mutex::Autolock _l(mLock);
+ Mutex::Autolock _l(mOverlaySourceLock);
if (mOverlay) {
overlay_control_device_t* overlay_dev = mOverlayDevice;
overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h);
@@ -645,17 +650,11 @@
}
}
-void LayerBuffer::OverlaySource::serverDestroy()
-{
- mLayer.clearSource();
- destroyOverlay();
-}
-
-void LayerBuffer::OverlaySource::destroyOverlay()
+void LayerBuffer::OverlaySource::destroy()
{
// we need a lock here to protect "onVisibilityResolved"
- Mutex::Autolock _l(mLock);
- if (mOverlay) {
+ Mutex::Autolock _l(mOverlaySourceLock);
+ if (mOverlay && mOverlayDevice) {
overlay_control_device_t* overlay_dev = mOverlayDevice;
overlay_dev->destroyOverlay(overlay_dev, mOverlay);
mOverlay = 0;
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index e539f68..0452818 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -49,6 +49,7 @@
virtual void postBuffer(ssize_t offset);
virtual void unregisterBuffers();
virtual bool transformed() const;
+ virtual void destroy() { }
protected:
LayerBuffer& mLayer;
};
@@ -81,10 +82,12 @@
sp<Source> getSource() const;
sp<Source> clearSource();
void setNeedsBlending(bool blending);
- const Rect& getTransformedBounds() const {
+ Rect getTransformedBounds() const {
return mTransformedBounds;
}
+ void serverDestroy();
+
private:
struct NativeBuffer {
copybit_image_t img;
@@ -123,8 +126,9 @@
virtual void postBuffer(ssize_t offset);
virtual void unregisterBuffers();
virtual bool transformed() const;
+ virtual void destroy() { }
private:
- mutable Mutex mLock;
+ mutable Mutex mBufferSourceLock;
sp<Buffer> mBuffer;
status_t mStatus;
ISurface::BufferHeap mBufferHeap;
@@ -143,28 +147,23 @@
virtual void onDraw(const Region& clip) const;
virtual void onTransaction(uint32_t flags);
virtual void onVisibilityResolved(const Transform& planeTransform);
+ virtual void destroy();
private:
- void serverDestroy();
- void destroyOverlay();
+
class OverlayChannel : public BnOverlay {
- mutable Mutex mLock;
- sp<OverlaySource> mSource;
+ wp<LayerBuffer> mLayer;
virtual void destroy() {
- sp<OverlaySource> source;
- { // scope for the lock;
- Mutex::Autolock _l(mLock);
- source = mSource;
- mSource.clear();
- }
- if (source != 0) {
- source->serverDestroy();
+ sp<LayerBuffer> layer(mLayer.promote());
+ if (layer != 0) {
+ layer->serverDestroy();
}
}
public:
- OverlayChannel(const sp<OverlaySource>& source)
- : mSource(source) {
+ OverlayChannel(const sp<LayerBuffer>& layer)
+ : mLayer(layer) {
}
};
+
friend class OverlayChannel;
bool mVisibilityChanged;
@@ -176,7 +175,7 @@
int32_t mFormat;
int32_t mWidthStride;
int32_t mHeightStride;
- mutable Mutex mLock;
+ mutable Mutex mOverlaySourceLock;
bool mInitialized;
};
@@ -199,7 +198,7 @@
return static_cast<LayerBuffer*>(Surface::getOwner().get());
}
};
-
+
mutable Mutex mLock;
sp<Source> mSource;
sp<Surface> mSurface;
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index b368db6..8685f99 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -654,6 +654,7 @@
// some layers might have been removed, so
// we need to update the regions they're exposing.
if (mLayersRemoved) {
+ mLayersRemoved = false;
mVisibleRegionsDirty = true;
const LayerVector& previousLayers(mDrawingState.layersSortedByZ);
const size_t count = previousLayers.size();
@@ -1093,9 +1094,6 @@
void SurfaceFlinger::free_resources_l()
{
- // Destroy layers that were removed
- mLayersRemoved = false;
-
// free resources associated with disconnected clients
Vector< sp<Client> >& disconnectedClients(mDisconnectedClients);
const size_t count = disconnectedClients.size();
@@ -1321,11 +1319,15 @@
* to wait for all client's references to go away first).
*/
+ status_t err = NAME_NOT_FOUND;
Mutex::Autolock _l(mStateLock);
sp<LayerBaseClient> layer = getLayerUser_l(index);
- status_t err = purgatorizeLayer_l(layer);
- if (err == NO_ERROR) {
- setTransactionFlags(eTransactionNeeded);
+ if (layer != 0) {
+ err = purgatorizeLayer_l(layer);
+ if (err == NO_ERROR) {
+ layer->onRemoved();
+ setTransactionFlags(eTransactionNeeded);
+ }
}
return err;
}
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index 348dd68..9577044 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -40,4 +40,8 @@
LOCAL_MODULE:= libui
+ifeq ($(TARGET_SIMULATOR),true)
+ LOCAL_LDLIBS += -lpthread
+endif
+
include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/ui/SharedBufferStack.cpp b/libs/ui/SharedBufferStack.cpp
index 5995af5..436d793 100644
--- a/libs/ui/SharedBufferStack.cpp
+++ b/libs/ui/SharedBufferStack.cpp
@@ -53,21 +53,20 @@
return uint32_t(surfaces[token].identity);
}
-status_t SharedClient::setIdentity(size_t token, uint32_t identity) {
- if (token >= NUM_LAYERS_MAX)
- return BAD_INDEX;
- surfaces[token].identity = identity;
- return NO_ERROR;
-}
-
// ----------------------------------------------------------------------------
SharedBufferStack::SharedBufferStack()
- : inUse(-1), identity(-1), status(NO_ERROR)
{
}
+void SharedBufferStack::init(int32_t i)
+{
+ inUse = -1;
+ status = NO_ERROR;
+ identity = i;
+}
+
status_t SharedBufferStack::setDirtyRegion(int buffer, const Region& dirty)
{
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
@@ -231,16 +230,46 @@
return head;
}
+SharedBufferServer::StatusUpdate::StatusUpdate(
+ SharedBufferBase* sbb, status_t status)
+ : UpdateBase(sbb), status(status) {
+}
+
+ssize_t SharedBufferServer::StatusUpdate::operator()() {
+ android_atomic_write(status, &stack.status);
+ return NO_ERROR;
+}
+
// ============================================================================
SharedBufferClient::SharedBufferClient(SharedClient* sharedClient,
int surface, int num)
: SharedBufferBase(sharedClient, surface, num), tail(0)
{
+ SharedBufferStack& stack( *mSharedStack );
+ int32_t avail;
+ int32_t head;
+ // we need to make sure we read available and head coherently,
+ // w.r.t RetireUpdate.
+ do {
+ avail = stack.available;
+ head = stack.head;
+ } while (stack.available != avail);
+ tail = head - avail + 1;
+ if (tail < 0) {
+ tail += num;
+ }
}
ssize_t SharedBufferClient::dequeue()
{
+ SharedBufferStack& stack( *mSharedStack );
+
+ if (stack.head == tail && stack.available == 2) {
+ LOGW("dequeue: tail=%d, head=%d, avail=%d, queued=%d",
+ tail, stack.head, stack.available, stack.queued);
+ }
+
//LOGD("[%d] about to dequeue a buffer",
// mSharedStack->identity);
DequeueCondition condition(this);
@@ -248,8 +277,6 @@
if (err != NO_ERROR)
return ssize_t(err);
-
- SharedBufferStack& stack( *mSharedStack );
// NOTE: 'stack.available' is part of the conditions, however
// decrementing it, never changes any conditions, so we don't need
// to do this as part of an update.
@@ -261,6 +288,7 @@
tail = ((tail+1 >= mNumBuffers) ? 0 : tail+1);
LOGD_IF(DEBUG_ATOMICS, "dequeued=%d, tail=%d, %s",
dequeued, tail, dump("").string());
+
return dequeued;
}
@@ -302,9 +330,10 @@
// ----------------------------------------------------------------------------
SharedBufferServer::SharedBufferServer(SharedClient* sharedClient,
- int surface, int num)
+ int surface, int num, int32_t identity)
: SharedBufferBase(sharedClient, surface, num)
{
+ mSharedStack->init(identity);
mSharedStack->head = num-1;
mSharedStack->available = num;
mSharedStack->queued = 0;
@@ -316,7 +345,7 @@
{
RetireUpdate update(this, mNumBuffers);
ssize_t buf = updateCondition( update );
- LOGD_IF(DEBUG_ATOMICS, "retire=%d, %s", int(buf), dump("").string());
+ LOGD_IF(DEBUG_ATOMICS && buf>=0, "retire=%d, %s", int(buf), dump("").string());
return buf;
}
@@ -327,6 +356,12 @@
return err;
}
+void SharedBufferServer::setStatus(status_t status)
+{
+ StatusUpdate update(this, status);
+ updateCondition( update );
+}
+
status_t SharedBufferServer::reallocate()
{
SharedBufferStack& stack( *mSharedStack );
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index 6be372c..ec3db09 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -655,6 +655,11 @@
wp<Thread> weak(strong);
self->mHoldSelf.clear();
+#if HAVE_ANDROID_OS
+ // this is very useful for debugging with gdb
+ self->mTid = gettid();
+#endif
+
bool first = true;
do {
@@ -685,7 +690,7 @@
self->mExitPending = true;
self->mLock.lock();
self->mRunning = false;
- self->mThreadExitedCondition.signal();
+ self->mThreadExitedCondition.broadcast();
self->mLock.unlock();
break;
}
@@ -693,7 +698,7 @@
// Release our strong reference, to let a chance to the thread
// to die a peaceful death.
strong.clear();
- // And immediately, reacquire a strong reference for the next loop
+ // And immediately, re-acquire a strong reference for the next loop
strong = weak.promote();
} while(strong != 0);
diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp
index 4d3c2f4..90e6d29 100644
--- a/opengl/libagl/texture.cpp
+++ b/opengl/libagl/texture.cpp
@@ -118,10 +118,10 @@
/*
* If the active textures are EGLImage, they need to be locked before
- * they can be used.
- *
+ * they can be used.
+ *
* FIXME: code below is far from being optimal
- *
+ *
*/
void ogles_lock_textures(ogles_context_t* c)
@@ -409,6 +409,49 @@
return 0;
}
+static size_t dataSizePalette4(int numLevels, int width, int height, int format)
+{
+ int indexBits = 8;
+ int entrySize = 0;
+ switch (format) {
+ case GL_PALETTE4_RGB8_OES:
+ indexBits = 4;
+ /* FALLTHROUGH */
+ case GL_PALETTE8_RGB8_OES:
+ entrySize = 3;
+ break;
+
+ case GL_PALETTE4_RGBA8_OES:
+ indexBits = 4;
+ /* FALLTHROUGH */
+ case GL_PALETTE8_RGBA8_OES:
+ entrySize = 4;
+ break;
+
+ case GL_PALETTE4_R5_G6_B5_OES:
+ case GL_PALETTE4_RGBA4_OES:
+ case GL_PALETTE4_RGB5_A1_OES:
+ indexBits = 4;
+ /* FALLTHROUGH */
+ case GL_PALETTE8_R5_G6_B5_OES:
+ case GL_PALETTE8_RGBA4_OES:
+ case GL_PALETTE8_RGB5_A1_OES:
+ entrySize = 2;
+ break;
+ }
+
+ size_t size = (1 << indexBits) * entrySize; // palette size
+
+ for (int i=0 ; i< numLevels ; i++) {
+ int w = (width >> i) ? : 1;
+ int h = (height >> i) ? : 1;
+ int levelSize = h * ((w * indexBits) / 8) ? : 1;
+ size += levelSize;
+ }
+
+ return size;
+}
+
static void decodePalette4(const GLvoid *data, int level, int width, int height,
void *surface, int stride, int format)
@@ -443,6 +486,7 @@
}
const int paletteSize = (1 << indexBits) * entrySize;
+
uint8_t const* pixels = (uint8_t *)data + paletteSize;
for (int i=0 ; i<level ; i++) {
int w = (width >> i) ? : 1;
@@ -652,7 +696,7 @@
ogles_context_t* c)
{
ogles_lock_textures(c);
-
+
const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
y = gglIntToFixed(cbSurface.height) - (y + h);
w >>= FIXED_BITS;
@@ -799,7 +843,7 @@
c->rasterizer.procs.disable(c, GGL_AA);
c->rasterizer.procs.shadeModel(c, GL_FLAT);
c->rasterizer.procs.recti(c, x, y, x+w, y+h);
-
+
ogles_unlock_textures(c);
return;
@@ -1091,6 +1135,12 @@
GGLSurface* surface;
// all mipmap levels are specified at once.
const int numLevels = level<0 ? -level : 1;
+
+ if (dataSizePalette4(numLevels, width, height, format) > imageSize) {
+ ogles_error(c, GL_INVALID_VALUE);
+ return;
+ }
+
for (int i=0 ; i<numLevels ; i++) {
int lod_w = (width >> i) ? : 1;
int lod_h = (height >> i) ? : 1;