Merge "Switch to returnCode for IPackageDeleteObserver"
diff --git a/include/binder/IBinder.h b/include/binder/IBinder.h
index 749a977..81b56c2 100644
--- a/include/binder/IBinder.h
+++ b/include/binder/IBinder.h
@@ -98,7 +98,7 @@
      * Register the @a recipient for a notification if this binder
      * goes away.  If this binder object unexpectedly goes away
      * (typically because its hosting process has been killed),
-     * then DeathRecipient::binderDied() will be called with a referene
+     * then DeathRecipient::binderDied() will be called with a reference
      * to this.
      *
      * The @a cookie is optional -- if non-NULL, it should be a
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 31615d0..9bf38f7 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -37,7 +37,8 @@
 
 class SurfaceTexture : public BnSurfaceTexture {
 public:
-    enum { MIN_BUFFER_SLOTS = 3 };
+    enum { MIN_UNDEQUEUED_BUFFERS = 2 };
+    enum { MIN_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS + 1 };
     enum { NUM_BUFFER_SLOTS = 32 };
 
     struct FrameAvailableListener : public virtual RefBase {
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index ff2251d..4cdece9 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -40,40 +40,41 @@
     SurfaceTextureClient(const SurfaceTextureClient& rhs);
 
     // ANativeWindow hooks
-    static int setSwapInterval(ANativeWindow* window, int interval);
-    static int dequeueBuffer(ANativeWindow* window, android_native_buffer_t** buffer);
     static int cancelBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
+    static int dequeueBuffer(ANativeWindow* window, android_native_buffer_t** buffer);
     static int lockBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
-    static int queueBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
-    static int query(ANativeWindow* window, int what, int* value);
     static int perform(ANativeWindow* window, int operation, ...);
+    static int query(ANativeWindow* window, int what, int* value);
+    static int queueBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
+    static int setSwapInterval(ANativeWindow* window, int interval);
 
-    int setSwapInterval(int interval);
+    int cancelBuffer(android_native_buffer_t* buffer);
     int dequeueBuffer(android_native_buffer_t** buffer);
     int lockBuffer(android_native_buffer_t* buffer);
-    int queueBuffer(android_native_buffer_t* buffer);
-    int cancelBuffer(android_native_buffer_t* buffer);
-    int query(int what, int* value);
     int perform(int operation, va_list args);
+    int query(int what, int* value);
+    int queueBuffer(android_native_buffer_t* buffer);
+    int setSwapInterval(int interval);
 
-    int dispatchSetUsage(va_list args);
     int dispatchConnect(va_list args);
     int dispatchDisconnect(va_list args);
-    int dispatchSetCrop(va_list args);
     int dispatchSetBufferCount(va_list args);
     int dispatchSetBuffersGeometry(va_list args);
     int dispatchSetBuffersTransform(va_list args);
+    int dispatchSetCrop(va_list args);
+    int dispatchSetUsage(va_list args);
 
     int connect(int api);
     int disconnect(int api);
-    int setUsage(uint32_t reqUsage);
-    int setCrop(Rect const* rect);
     int setBufferCount(int bufferCount);
     int setBuffersGeometry(int w, int h, int format);
     int setBuffersTransform(int transform);
+    int setCrop(Rect const* rect);
+    int setUsage(uint32_t reqUsage);
 
     void freeAllBuffers();
 
+    enum { MIN_UNDEQUEUED_BUFFERS = SurfaceTexture::MIN_UNDEQUEUED_BUFFERS };
     enum { MIN_BUFFER_SLOTS = SurfaceTexture::MIN_BUFFER_SLOTS };
     enum { NUM_BUFFER_SLOTS = SurfaceTexture::NUM_BUFFER_SLOTS };
     enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h
index eb599b5..717f837 100644
--- a/include/private/surfaceflinger/SharedBufferStack.h
+++ b/include/private/surfaceflinger/SharedBufferStack.h
@@ -65,7 +65,7 @@
     // When changing these values, the COMPILE_TIME_ASSERT at the end of this
     // file need to be updated.
     static const unsigned int NUM_LAYERS_MAX  = 31;
-    static const unsigned int NUM_BUFFER_MAX  = 16;
+    static const unsigned int NUM_BUFFER_MAX  = 32;
     static const unsigned int NUM_BUFFER_MIN  = 2;
     static const unsigned int NUM_DISPLAY_MAX = 4;
 
@@ -123,7 +123,7 @@
 
 // ----------------------------------------------------------------------------
 
-// 32 KB max
+// 64 KB max
 class SharedClient
 {
 public:
@@ -394,7 +394,7 @@
 
 // ---------------------------------------------------------------------------
 
-COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 32768)
+COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 65536)
 COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096)
 
 // ---------------------------------------------------------------------------
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index d783caf..9e0b5bb 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -242,6 +242,10 @@
     status_t validate(bool inCancelBuffer = false) const;
     sp<ISurface> getISurface() const;
 
+    // When the buffer pool is a fixed size we want to make sure SurfaceFlinger
+    // won't stall clients, so we require an extra buffer.
+    enum { MIN_UNDEQUEUED_BUFFERS = 2 };
+
     inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
     inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
 
diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h
index fdc8105..fd83f46 100644
--- a/include/ui/egl/android_natives.h
+++ b/include/ui/egl/android_natives.h
@@ -75,6 +75,26 @@
     NATIVE_WINDOW_WIDTH     = 0,
     NATIVE_WINDOW_HEIGHT,
     NATIVE_WINDOW_FORMAT,
+
+    /* The minimum number of buffers that must remain un-dequeued after a buffer
+     * has been queued.  This value applies only if set_buffer_count was used to
+     * override the number of buffers and if a buffer has since been queued.
+     * Users of the set_buffer_count ANativeWindow method should query this
+     * value before calling set_buffer_count.  If it is necessary to have N
+     * buffers simultaneously dequeued as part of the steady-state operation,
+     * and this query returns M then N+M buffers should be requested via
+     * native_window_set_buffer_count.
+     *
+     * Note that this value does NOT apply until a single buffer has been
+     * queued.  In particular this means that it is possible to:
+     *
+     * 1. Query M = min undequeued buffers
+     * 2. Set the buffer count to N + M
+     * 3. Dequeue all N + M buffers
+     * 4. Cancel M buffers
+     * 5. Queue, dequeue, queue, dequeue, ad infinitum
+     */
+    NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
 };
 
 /* valid operations for the (*perform)() hook */
diff --git a/include/utils/StrongPointer.h b/include/utils/StrongPointer.h
index a8c9897..49fa3a8 100644
--- a/include/utils/StrongPointer.h
+++ b/include/utils/StrongPointer.h
@@ -133,7 +133,7 @@
 template<typename T> template<typename U>
 sp<T>::sp(U* other) : m_ptr(other)
 {
-    if (other) other->incStrong(this);
+    if (other) ((T*)other)->incStrong(this);
 }
 
 template<typename T> template<typename U>
@@ -170,7 +170,7 @@
 template<typename T> template<typename U>
 sp<T>& sp<T>::operator = (const sp<U>& other)
 {
-    U* otherPtr(other.m_ptr);
+    T* otherPtr(other.m_ptr);
     if (otherPtr) otherPtr->incStrong(this);
     if (m_ptr) m_ptr->decStrong(this);
     m_ptr = otherPtr;
@@ -180,7 +180,7 @@
 template<typename T> template<typename U>
 sp<T>& sp<T>::operator = (U* other)
 {
-    if (other) other->incStrong(this);
+    if (other) ((T*)other)->incStrong(this);
     if (m_ptr) m_ptr->decStrong(this);
     m_ptr = other;
     return *this;
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 223cf09..3bed959 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -96,6 +96,11 @@
 
 status_t SurfaceTexture::setBufferCount(int bufferCount) {
     LOGV("SurfaceTexture::setBufferCount");
+
+    if (bufferCount < MIN_BUFFER_SLOTS) {
+        return BAD_VALUE;
+    }
+
     Mutex::Autolock lock(mMutex);
     freeAllBuffers();
     mBufferCount = bufferCount;
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index ee14ac9..43b330c 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -143,8 +143,21 @@
 int SurfaceTextureClient::query(int what, int* value) {
     LOGV("SurfaceTextureClient::query");
     Mutex::Autolock lock(mMutex);
-    // XXX: Implement this!
-    return INVALID_OPERATION;
+    switch (what) {
+    case NATIVE_WINDOW_WIDTH:
+    case NATIVE_WINDOW_HEIGHT:
+        // XXX: How should SurfaceTexture behave if setBuffersGeometry didn't
+        // override the size?
+        *value = 0;
+        return NO_ERROR;
+    case NATIVE_WINDOW_FORMAT:
+        *value = DEFAULT_FORMAT;
+        return NO_ERROR;
+    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
+        *value = MIN_UNDEQUEUED_BUFFERS;
+        return NO_ERROR;
+    }
+    return BAD_VALUE;
 }
 
 int SurfaceTextureClient::perform(int operation, va_list args)
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index 1e9bd74..818114a 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -709,6 +709,9 @@
     case NATIVE_WINDOW_FORMAT:
         *value = int(mFormat);
         return NO_ERROR;
+    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
+        *value = MIN_UNDEQUEUED_BUFFERS;
+        return NO_ERROR;
     }
     return BAD_VALUE;
 }
@@ -1040,7 +1043,7 @@
         // e.g. if GraphicBuffer is used to wrap an android_native_buffer_t that
         // was dequeued from an ANativeWindow.
         for (size_t i = 0; i < mBuffers.size(); i++) {
-            if (buffer->handle == mBuffers[i]->handle) {
+            if (mBuffers[i] != 0 && buffer->handle == mBuffers[i]->handle) {
                 idx = mBuffers[i]->getIndex();
                 break;
             }
diff --git a/libs/utils/RefBase.cpp b/libs/utils/RefBase.cpp
index 0fd404d..bb6c125 100644
--- a/libs/utils/RefBase.cpp
+++ b/libs/utils/RefBase.cpp
@@ -99,20 +99,38 @@
 #if DEBUG_REFS_FATAL_SANITY_CHECKS
             LOG_ALWAYS_FATAL("Strong references remain!");
 #else
-            LOGE("Strong references remain!");
+            LOGE("Strong references remain:");
 #endif
+            ref_entry* refs = mStrongRefs;
+            while (refs) {
+                char inc = refs->ref >= 0 ? '+' : '-';
+                LOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
+#if DEBUG_REFS_CALLSTACK_ENABLED
+                refs->stack.dump();
+#endif;
+                refs = refs->next;
+            }
         }
 
         if (!mRetain && mWeakRefs != NULL) {
             dumpStack = true;
 #if DEBUG_REFS_FATAL_SANITY_CHECKS
-            LOG_ALWAYS_FATAL("Weak references remain!");
+            LOG_ALWAYS_FATAL("Weak references remain:");
 #else
             LOGE("Weak references remain!");
 #endif
+            ref_entry* refs = mWeakRefs;
+            while (refs) {
+                char inc = refs->ref >= 0 ? '+' : '-';
+                LOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
+#if DEBUG_REFS_CALLSTACK_ENABLED
+                refs->stack.dump();
+#endif;
+                refs = refs->next;
+            }
         }
-
         if (dumpStack) {
+            LOGE("above errors at:");
             CallStack stack;
             stack.update();
             stack.dump();
@@ -228,7 +246,8 @@
         if (mTrackEnabled) {
             AutoMutex _l(mMutex);
             
-            ref_entry* ref = *refs;
+            ref_entry* const head = *refs;
+            ref_entry* ref = head;
             while (ref != NULL) {
                 if (ref->id == id) {
                     *refs = ref->next;
@@ -249,6 +268,13 @@
                     "(weakref_type %p) that doesn't exist!",
                     id, mBase, this);
 
+            ref = head;
+            while (ref) {
+                char inc = ref->ref >= 0 ? '+' : '-';
+                LOGD("\t%c ID %p (ref %d):", inc, ref->id, ref->ref);
+                ref = ref->next;
+            }
+
             CallStack stack;
             stack.update();
             stack.dump();