Merge "Fix 5023708,4689527: Add popups and overlays to recents. Misc bug fixes."
diff --git a/include/gui/ISurfaceTexture.h b/include/gui/ISurfaceTexture.h
index e705c6f..5b5b731 100644
--- a/include/gui/ISurfaceTexture.h
+++ b/include/gui/ISurfaceTexture.h
@@ -104,6 +104,24 @@
     // queued buffers will be retired in order.
     // The default mode is asynchronous.
     virtual status_t setSynchronousMode(bool enabled) = 0;
+
+    // connect attempts to connect a client API to the SurfaceTexture.  This
+    // must be called before any other ISurfaceTexture methods are called except
+    // for getAllocator.
+    //
+    // This method will fail if the connect was previously called on the
+    // SurfaceTexture and no corresponding disconnect call was made.
+    virtual status_t connect(int api) = 0;
+
+    // disconnect attempts to disconnect a client API from the SurfaceTexture.
+    // Calling this method will cause any subsequent calls to other
+    // ISurfaceTexture methods to fail except for getAllocator and connect.
+    // Successfully calling connect after this will allow the other methods to
+    // succeed again.
+    //
+    // This method will fail if the the SurfaceTexture is not currently
+    // connected to the specified client API.
+    virtual status_t disconnect(int api) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index e36360c..4080f27 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -44,6 +44,7 @@
         MIN_SYNC_BUFFER_SLOTS  = MIN_UNDEQUEUED_BUFFERS
     };
     enum { NUM_BUFFER_SLOTS = 32 };
+    enum { NO_CONNECTED_API = 0 };
 
     struct FrameAvailableListener : public virtual RefBase {
         // onFrameAvailable() is called from queueBuffer() each time an
@@ -97,6 +98,24 @@
     // The default mode is asynchronous.
     virtual status_t setSynchronousMode(bool enabled);
 
+    // connect attempts to connect a client API to the SurfaceTexture.  This
+    // must be called before any other ISurfaceTexture methods are called except
+    // for getAllocator.
+    //
+    // This method will fail if the connect was previously called on the
+    // SurfaceTexture and no corresponding disconnect call was made.
+    virtual status_t connect(int api);
+
+    // disconnect attempts to disconnect a client API from the SurfaceTexture.
+    // Calling this method will cause any subsequent calls to other
+    // ISurfaceTexture methods to fail except for getAllocator and connect.
+    // Successfully calling connect after this will allow the other methods to
+    // succeed again.
+    //
+    // This method will fail if the the SurfaceTexture is not currently
+    // connected to the specified client API.
+    virtual status_t disconnect(int api);
+
     // updateTexImage sets the image contents of the target texture to that of
     // the most recently queued buffer.
     //
@@ -362,6 +381,11 @@
     // mAllowSynchronousMode whether we allow synchronous mode or not
     const bool mAllowSynchronousMode;
 
+    // mConnectedApi indicates the API that is currently connected to this
+    // SurfaceTexture.  It defaults to NO_CONNECTED_API (= 0), and gets updated
+    // by the connect and disconnect methods.
+    int mConnectedApi;
+
     // mDequeueCondition condition used for dequeueBuffer in synchronous mode
     mutable Condition mDequeueCondition;
 
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index 9db7364..5ec469e 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -129,9 +129,6 @@
     // a timestamp is auto-generated when queueBuffer is called.
     int64_t mTimestamp;
 
-    // mConnectedApi holds the currently connected API to this surface
-    int mConnectedApi;
-
     // mQueryWidth is the width returned by query(). It is set to width
     // of the last dequeued buffer or to mReqWidth if no buffer was dequeued.
     uint32_t mQueryWidth;
diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp
index 16e3780..41434a4 100644
--- a/libs/gui/ISurfaceTexture.cpp
+++ b/libs/gui/ISurfaceTexture.cpp
@@ -41,6 +41,8 @@
     GET_ALLOCATOR,
     QUERY,
     SET_SYNCHRONOUS_MODE,
+    CONNECT,
+    DISCONNECT,
 };
 
 
@@ -154,7 +156,23 @@
         return result;
     }
 
+    virtual status_t connect(int api) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeInt32(api);
+        remote()->transact(CONNECT, data, &reply);
+        status_t result = reply.readInt32();
+        return result;
+    }
 
+    virtual status_t disconnect(int api) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeInt32(api);
+        remote()->transact(DISCONNECT, data, &reply);
+        status_t result = reply.readInt32();
+        return result;
+    }
 };
 
 IMPLEMENT_META_INTERFACE(SurfaceTexture, "android.gui.SurfaceTexture");
@@ -248,6 +266,20 @@
             reply->writeInt32(res);
             return NO_ERROR;
         } break;
+        case CONNECT: {
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            int api = data.readInt32();
+            status_t res = connect(api);
+            reply->writeInt32(res);
+            return NO_ERROR;
+        } break;
+        case DISCONNECT: {
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            int api = data.readInt32();
+            status_t res = disconnect(api);
+            reply->writeInt32(res);
+            return NO_ERROR;
+        } break;
     }
     return BBinder::onTransact(code, data, reply, flags);
 }
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 886a3fb..1410481 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -92,7 +92,8 @@
     mNextTransform(0),
     mTexName(tex),
     mSynchronousMode(false),
-    mAllowSynchronousMode(allowSynchronousMode) {
+    mAllowSynchronousMode(allowSynchronousMode),
+    mConnectedApi(NO_CONNECTED_API) {
     LOGV("SurfaceTexture::SurfaceTexture");
     sp<ISurfaceComposer> composer(ComposerService::getComposerService());
     mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
@@ -493,6 +494,50 @@
     return OK;
 }
 
+status_t SurfaceTexture::connect(int api) {
+    LOGV("SurfaceTexture::connect");
+    Mutex::Autolock lock(mMutex);
+    int err = NO_ERROR;
+    switch (api) {
+        case NATIVE_WINDOW_API_EGL:
+        case NATIVE_WINDOW_API_CPU:
+        case NATIVE_WINDOW_API_MEDIA:
+        case NATIVE_WINDOW_API_CAMERA:
+            if (mConnectedApi != NO_CONNECTED_API) {
+                err = -EINVAL;
+            } else {
+                mConnectedApi = api;
+            }
+            break;
+        default:
+            err = -EINVAL;
+            break;
+    }
+    return err;
+}
+
+status_t SurfaceTexture::disconnect(int api) {
+    LOGV("SurfaceTexture::disconnect");
+    Mutex::Autolock lock(mMutex);
+    int err = NO_ERROR;
+    switch (api) {
+        case NATIVE_WINDOW_API_EGL:
+        case NATIVE_WINDOW_API_CPU:
+        case NATIVE_WINDOW_API_MEDIA:
+        case NATIVE_WINDOW_API_CAMERA:
+            if (mConnectedApi == api) {
+                mConnectedApi = NO_CONNECTED_API;
+            } else {
+                err = -EINVAL;
+            }
+            break;
+        default:
+            err = -EINVAL;
+            break;
+    }
+    return err;
+}
+
 status_t SurfaceTexture::updateTexImage() {
     LOGV("SurfaceTexture::updateTexImage");
     Mutex::Autolock lock(mMutex);
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index e203035..f39cabf 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -27,7 +27,7 @@
         const sp<ISurfaceTexture>& surfaceTexture):
         mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(0),
         mReqHeight(0), mReqFormat(0), mReqUsage(0),
-        mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO), mConnectedApi(0),
+        mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO),
         mQueryWidth(0), mQueryHeight(0), mQueryFormat(0),
         mMutex() {
     // Initialize the ANativeWindow function pointers.
@@ -327,45 +327,22 @@
 int SurfaceTextureClient::connect(int api) {
     LOGV("SurfaceTextureClient::connect");
     Mutex::Autolock lock(mMutex);
-    int err = NO_ERROR;
-    switch (api) {
-        case NATIVE_WINDOW_API_EGL:
-            if (mConnectedApi) {
-                err = -EINVAL;
-            } else {
-                mConnectedApi = api;
-            }
-            break;
-        default:
-            err = -EINVAL;
-            break;
-    }
-    return err;
+    return mSurfaceTexture->connect(api);
 }
 
 int SurfaceTextureClient::disconnect(int api) {
     LOGV("SurfaceTextureClient::disconnect");
     Mutex::Autolock lock(mMutex);
-    int err = NO_ERROR;
-    switch (api) {
-        case NATIVE_WINDOW_API_EGL:
-            if (mConnectedApi == api) {
-                mConnectedApi = 0;
-            } else {
-                err = -EINVAL;
-            }
-            break;
-        default:
-            err = -EINVAL;
-            break;
-    }
-    return err;
+    return mSurfaceTexture->disconnect(api);
 }
 
 int SurfaceTextureClient::getConnectedApi() const
 {
+    // XXX: This method will be going away shortly, and is currently bogus.  It
+    // always returns "nothing is connected".  It will go away once Surface gets
+    // updated to actually connect as the 'CPU' API when locking a buffer.
     Mutex::Autolock lock(mMutex);
-    return mConnectedApi;
+    return 0;
 }
 
 
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 88433fb..9abe89d 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "SurfaceTexture_test"
 //#define LOG_NDEBUG 0
 
 #include <gtest/gtest.h>
@@ -379,6 +380,13 @@
         ASSERT_NE(-1, mTexMatrixHandle);
     }
 
+    virtual void TearDown() {
+        mANW.clear();
+        mSTC.clear();
+        mST.clear();
+        GLTest::TearDown();
+    }
+
     // drawTexture draws the SurfaceTexture over the entire GL viewport.
     void drawTexture() {
         const GLfloat triangleVertices[] = {
@@ -1089,13 +1097,21 @@
     // synchronously from SurfaceTexture::queueBuffer.
     class FrameCondition : public SurfaceTexture::FrameAvailableListener {
     public:
+        FrameCondition():
+                mFrameAvailable(false),
+                mFrameFinished(false) {
+        }
+
         // waitForFrame waits for the next frame to arrive.  This should be
         // called from the consumer thread once for every frame expected by the
         // test.
         void waitForFrame() {
-            LOGV("+waitForFrame");
             Mutex::Autolock lock(mMutex);
-            status_t result = mFrameAvailableCondition.wait(mMutex);
+            LOGV("+waitForFrame");
+            while (!mFrameAvailable) {
+                mFrameAvailableCondition.wait(mMutex);
+            }
+            mFrameAvailable = false;
             LOGV("-waitForFrame");
         }
 
@@ -1103,22 +1119,30 @@
         // on to produce the next frame.  This should be called by the consumer
         // thread once for every frame expected by the test.
         void finishFrame() {
-            LOGV("+finishFrame");
             Mutex::Autolock lock(mMutex);
+            LOGV("+finishFrame");
+            mFrameFinished = true;
             mFrameFinishCondition.signal();
             LOGV("-finishFrame");
         }
 
         // This should be called by SurfaceTexture on the producer thread.
         virtual void onFrameAvailable() {
-            LOGV("+onFrameAvailable");
             Mutex::Autolock lock(mMutex);
+            LOGV("+onFrameAvailable");
+            mFrameAvailable = true;
             mFrameAvailableCondition.signal();
-            mFrameFinishCondition.wait(mMutex);
+            while (!mFrameFinished) {
+                mFrameFinishCondition.wait(mMutex);
+            }
+            mFrameFinished = false;
             LOGV("-onFrameAvailable");
         }
 
     protected:
+        bool mFrameAvailable;
+        bool mFrameFinished;
+
         Mutex mMutex;
         Condition mFrameAvailableCondition;
         Condition mFrameFinishCondition;
@@ -1164,6 +1188,7 @@
         }
         mProducerThread.clear();
         mFC.clear();
+        SurfaceTextureGLTest::TearDown();
     }
 
     void runProducerThread(const sp<ProducerThread> producerThread) {
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index 50312e7..d18c0a2 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -161,6 +161,7 @@
     pthread_t thread;
     int result = pthread_create(&thread, &attr,
                     (android_pthread_entry)entryFunction, userData);
+    pthread_attr_destroy(&attr);
     if (result != 0) {
         LOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n"
              "(android threadPriority=%d)",
diff --git a/libs/utils/VectorImpl.cpp b/libs/utils/VectorImpl.cpp
index 87ae3d5..bfb37a6 100644
--- a/libs/utils/VectorImpl.cpp
+++ b/libs/utils/VectorImpl.cpp
@@ -252,13 +252,15 @@
         "[%p] replace: index=%d, size=%d", this, (int)index, (int)size());
 
     void* item = editItemLocation(index);
-    if (item == 0)
-        return NO_MEMORY;
-    _do_destroy(item, 1);
-    if (prototype == 0) {
-        _do_construct(item, 1);
-    } else {
-        _do_copy(item, prototype, 1);
+    if (item != prototype) {
+        if (item == 0)
+            return NO_MEMORY;
+        _do_destroy(item, 1);
+        if (prototype == 0) {
+            _do_construct(item, 1);
+        } else {
+            _do_copy(item, prototype, 1);
+        }
     }
     return ssize_t(index);
 }
@@ -347,9 +349,10 @@
 //    LOGV("_grow(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
 //        this, (int)where, (int)amount, (int)mCount, (int)capacity());
 
-    if (where > mCount)
-        where = mCount;
-      
+    LOG_ASSERT(where <= mCount,
+            "[%p] _grow: where=%d, amount=%d, count=%d",
+            this, (int)where, (int)amount, (int)mCount); // caller already checked
+
     const size_t new_size = mCount + amount;
     if (capacity() < new_size) {
         const size_t new_capacity = max(kMinVectorCapacity, ((new_size*3)+1)/2);
@@ -366,10 +369,10 @@
             SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
             if (sb) {
                 void* array = sb->data();
-                if (where>0) {
+                if (where != 0) {
                     _do_copy(array, mStorage, where);
                 }
-                if (mCount>where) {
+                if (where != mCount) {
                     const void* from = reinterpret_cast<const uint8_t *>(mStorage) + where*mItemSize;
                     void* dest = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
                     _do_copy(dest, from, mCount-where);
@@ -379,15 +382,14 @@
             }
         }
     } else {
-        ssize_t s = mCount-where;
-        if (s>0) {
-            void* array = editArrayImpl();    
-            void* to = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
+        if (where != mCount) {
+            void* array = editArrayImpl();
             const void* from = reinterpret_cast<const uint8_t *>(array) + where*mItemSize;
-            _do_move_forward(to, from, s);
+            void* to = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
+            _do_move_forward(to, from, mCount - where);
         }
     }
-    mCount += amount;
+    mCount = new_size;
     void* free_space = const_cast<void*>(itemLocation(where));
     return free_space;
 }
@@ -400,14 +402,15 @@
 //    LOGV("_shrink(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
 //        this, (int)where, (int)amount, (int)mCount, (int)capacity());
 
-    if (where >= mCount)
-        where = mCount - amount;
+    LOG_ASSERT(where + amount <= mCount,
+            "[%p] _shrink: where=%d, amount=%d, count=%d",
+            this, (int)where, (int)amount, (int)mCount); // caller already checked
 
     const size_t new_size = mCount - amount;
     if (new_size*3 < capacity()) {
         const size_t new_capacity = max(kMinVectorCapacity, new_size*2);
 //        LOGV("shrink vector %p, new_capacity=%d", this, (int)new_capacity);
-        if ((where == mCount-amount) &&
+        if ((where == new_size) &&
             (mFlags & HAS_TRIVIAL_COPY) &&
             (mFlags & HAS_TRIVIAL_DTOR))
         {
@@ -418,31 +421,28 @@
             SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
             if (sb) {
                 void* array = sb->data();
-                if (where>0) {
+                if (where != 0) {
                     _do_copy(array, mStorage, where);
                 }
-                if (mCount > where+amount) {
+                if (where != new_size) {
                     const void* from = reinterpret_cast<const uint8_t *>(mStorage) + (where+amount)*mItemSize;
                     void* dest = reinterpret_cast<uint8_t *>(array) + where*mItemSize;
-                    _do_copy(dest, from, mCount-(where+amount));
+                    _do_copy(dest, from, new_size - where);
                 }
                 release_storage();
                 mStorage = const_cast<void*>(array);
             }
         }
     } else {
-        void* array = editArrayImpl();    
+        void* array = editArrayImpl();
         void* to = reinterpret_cast<uint8_t *>(array) + where*mItemSize;
         _do_destroy(to, amount);
-        ssize_t s = mCount-(where+amount);
-        if (s>0) {
+        if (where != new_size) {
             const void* from = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
-            _do_move_backward(to, from, s);
+            _do_move_backward(to, from, new_size - where);
         }
     }
-
-    // adjust the number of items...
-    mCount -= amount;
+    mCount = new_size;
 }
 
 size_t VectorImpl::itemSize() const {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b0881a4..680814c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1551,8 +1551,18 @@
          * Dump SurfaceFlinger global state
          */
 
-        snprintf(buffer, SIZE, "SurfaceFlinger global state\n");
+        snprintf(buffer, SIZE, "SurfaceFlinger global state:\n");
         result.append(buffer);
+
+        const GLExtensions& extensions(GLExtensions::getInstance());
+        snprintf(buffer, SIZE, "GLES: %s, %s, %s\n",
+                extensions.getVendor(),
+                extensions.getRenderer(),
+                extensions.getVersion());
+        result.append(buffer);
+        snprintf(buffer, SIZE, "EXTS: %s\n", extensions.getExtension());
+        result.append(buffer);
+
         mWormholeRegion.dump(result, "WormholeRegion");
         const DisplayHardware& hw(graphicPlane(0).displayHardware());
         snprintf(buffer, SIZE,