Merge "Making sure that the list of windows updates automatically in hierarchy viewer (View Server side)" into gingerbread
diff --git a/include/ui/Rect.h b/include/ui/Rect.h
index a213c09..4e65a2d 100644
--- a/include/ui/Rect.h
+++ b/include/ui/Rect.h
@@ -20,31 +20,28 @@
 #include <utils/TypeHelpers.h>
 #include <ui/Point.h>
 
+#include <android/rect.h>
+
 namespace android {
 
-class Rect
+class Rect : public ARect
 {
 public:
-    int left;
-    int top;
-    int right;
-    int bottom;
-
-    typedef int value_type;
+    typedef int32_t value_type;
 
     // we don't provide copy-ctor and operator= on purpose
     // because we want the compiler generated versions
 
     inline Rect() {
     }
-    inline Rect(int w, int h)
-        : left(0), top(0), right(w), bottom(h) {
+    inline Rect(int32_t w, int32_t h) {
+        left = top = 0; right = w; bottom = h;
     }
-    inline Rect(int l, int t, int r, int b)
-        : left(l), top(t), right(r), bottom(b) {
+    inline Rect(int32_t l, int32_t t, int32_t r, int32_t b) {
+        left = l; top = t; right = r; bottom = b;
     }
-    inline Rect(const Point& lt, const Point& rb) 
-        : left(lt.x), top(lt.y), right(rb.x), bottom(rb.y) {
+    inline Rect(const Point& lt, const Point& rb) {
+        left = lt.x; top = lt.y; right = rb.x; bottom = rb.y;
     }
 
     void makeInvalid();
@@ -68,12 +65,12 @@
     }
 
     // rectangle's width
-    inline int width() const {
+    inline int32_t width() const {
         return right-left;
     }
     
     // rectangle's height
-    inline int height() const {
+    inline int32_t height() const {
         return bottom-top;
     }
 
@@ -136,12 +133,12 @@
     const Rect operator + (const Point& rhs) const;
     const Rect operator - (const Point& rhs) const;
 
-    void translate(int dx, int dy) { // legacy, don't use.
+    void translate(int32_t dx, int32_t dy) { // legacy, don't use.
         offsetBy(dx, dy);
     }
  
-    Rect&   offsetTo(int x, int y);
-    Rect&   offsetBy(int x, int y);
+    Rect&   offsetTo(int32_t x, int32_t y);
+    Rect&   offsetBy(int32_t x, int32_t y);
     bool    intersect(const Rect& with, Rect* result) const;
 };
 
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index e6f46ce..97eb6c0 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -17,8 +17,7 @@
 
 
 #define LOG_TAG "AudioFlinger"
-//
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 
 #include <math.h>
 #include <signal.h>
@@ -5085,15 +5084,53 @@
     }
 }
 
+void AudioFlinger::EffectModule::updateState() {
+    Mutex::Autolock _l(mLock);
+
+    switch (mState) {
+    case RESTART:
+        reset_l();
+        // FALL THROUGH
+
+    case STARTING:
+        // clear auxiliary effect input buffer for next accumulation
+        if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+            memset(mConfig.inputCfg.buffer.raw,
+                   0,
+                   mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
+        }
+        start_l();
+        mState = ACTIVE;
+        break;
+    case STOPPING:
+        stop_l();
+        mDisableWaitCnt = mMaxDisableWaitCnt;
+        mState = STOPPED;
+        break;
+    case STOPPED:
+        // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
+        // turn off sequence.
+        if (--mDisableWaitCnt == 0) {
+            reset_l();
+            mState = IDLE;
+        }
+        break;
+    default: //IDLE , ACTIVE
+        break;
+    }
+}
+
 void AudioFlinger::EffectModule::process()
 {
     Mutex::Autolock _l(mLock);
 
-    if (mEffectInterface == NULL || mConfig.inputCfg.buffer.raw == NULL || mConfig.outputCfg.buffer.raw == NULL) {
+    if (mEffectInterface == NULL ||
+            mConfig.inputCfg.buffer.raw == NULL ||
+            mConfig.outputCfg.buffer.raw == NULL) {
         return;
     }
 
-    if (mState != IDLE) {
+    if (mState == ACTIVE || mState == STOPPING || mState == STOPPED) {
         // do 32 bit to 16 bit conversion for auxiliary effect input buffer
         if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
             AudioMixer::ditherAndClamp(mConfig.inputCfg.buffer.s32,
@@ -5101,33 +5138,15 @@
                                         mConfig.inputCfg.buffer.frameCount);
         }
 
-        // TODO: handle effects with buffer provider
-        if (mState != ACTIVE) {
-            switch (mState) {
-            case RESET:
-                reset_l();
-                mState = STARTING;
-                // clear auxiliary effect input buffer for next accumulation
-                if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
-                    memset(mConfig.inputCfg.buffer.raw, 0, mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
-                }
-                return;
-            case STARTING:
-                start_l();
-                mState = ACTIVE;
-                break;
-            case STOPPING:
-                mState = STOPPED;
-                break;
-            case STOPPED:
-                stop_l();
-                mState = IDLE;
-                return;
-            }
-        }
-
         // do the actual processing in the effect engine
-        (*mEffectInterface)->process(mEffectInterface, &mConfig.inputCfg.buffer, &mConfig.outputCfg.buffer);
+        int ret = (*mEffectInterface)->process(mEffectInterface,
+                                               &mConfig.inputCfg.buffer,
+                                               &mConfig.outputCfg.buffer);
+
+        // force transition to IDLE state when engine is ready
+        if (mState == STOPPED && ret == -ENODATA) {
+            mDisableWaitCnt = 1;
+        }
 
         // clear auxiliary effect input buffer for next accumulation
         if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
@@ -5216,6 +5235,10 @@
     if (status == 0) {
         status = cmdStatus;
     }
+
+    mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
+            (1000 * mConfig.outputCfg.buffer.frameCount);
+
     return status;
 }
 
@@ -5292,21 +5315,19 @@
         switch (mState) {
         // going from disabled to enabled
         case IDLE:
-            mState = RESET;
+            mState = STARTING;
+            break;
+        case STOPPED:
+            mState = RESTART;
             break;
         case STOPPING:
             mState = ACTIVE;
             break;
-        case STOPPED:
-            mState = STARTING;
-            break;
 
         // going from enabled to disabled
-        case RESET:
-            mState = IDLE;
-            break;
+        case RESTART:
         case STARTING:
-            mState = STOPPED;
+            mState = IDLE;
             break;
         case ACTIVE:
             mState = STOPPING;
@@ -5325,7 +5346,7 @@
 bool AudioFlinger::EffectModule::isEnabled()
 {
     switch (mState) {
-    case RESET:
+    case RESTART:
     case STARTING:
     case ACTIVE:
         return true;
@@ -5772,6 +5793,9 @@
     for (size_t i = 0; i < size; i++) {
         mEffects[i]->process();
     }
+    for (size_t i = 0; i < size; i++) {
+        mEffects[i]->updateState();
+    }
     // if no track is active, input buffer must be cleared here as the mixer process
     // will not do it
     if (mSessionId > 0 && activeTracks() == 0) {
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index ec3d7f1..507c9ac 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -905,7 +905,7 @@
 
         enum effect_state {
             IDLE,
-            RESET,
+            RESTART,
             STARTING,
             ACTIVE,
             STOPPING,
@@ -914,6 +914,7 @@
 
         int         id() { return mId; }
         void process();
+        void updateState();
         status_t command(int cmdCode, int cmdSize, void *pCmdData, int *replySize, void *pReplyData);
 
         void reset_l();
@@ -948,6 +949,9 @@
 
     protected:
 
+        // Maximum time allocated to effect engines to complete the turn off sequence
+        static const uint32_t MAX_DISABLE_TIME_MS = 10000;
+
         EffectModule(const EffectModule&);
         EffectModule& operator = (const EffectModule&);
 
@@ -973,6 +977,9 @@
         status_t mStatus;               // initialization status
         uint32_t mState;                // current activation state (effect_state)
         Vector< wp<EffectHandle> > mHandles;    // list of client handles
+        uint32_t mMaxDisableWaitCnt;    // maximum grace period before forcing an effect off after
+                                        // sending disable command.
+        uint32_t mDisableWaitCnt;       // current process() calls count during disable period.
     };
 
     // The EffectHandle class implements the IEffect interface. It provides resources
diff --git a/libs/ui/Rect.cpp b/libs/ui/Rect.cpp
index 66b9576..5694e00 100644
--- a/libs/ui/Rect.cpp
+++ b/libs/ui/Rect.cpp
@@ -18,11 +18,11 @@
 
 namespace android {
 
-static inline int min(int a, int b) {
+static inline int32_t min(int32_t a, int32_t b) {
     return (a<b) ? a : b;
 }
 
-static inline int max(int a, int b) {
+static inline int32_t max(int32_t a, int32_t b) {
     return (a>b) ? a : b;
 }
 
@@ -53,7 +53,7 @@
     return false;
 }
 
-Rect& Rect::offsetTo(int x, int y)
+Rect& Rect::offsetTo(int32_t x, int32_t y)
 {
     right -= left - x;
     bottom -= top - y;
@@ -62,7 +62,7 @@
     return *this;
 }
 
-Rect& Rect::offsetBy(int x, int y)
+Rect& Rect::offsetBy(int32_t x, int32_t y)
 {
     left += x;
     top  += y;
diff --git a/libs/utils/ObbFile.cpp b/libs/utils/ObbFile.cpp
index 3a4a03a..fe49300 100644
--- a/libs/utils/ObbFile.cpp
+++ b/libs/utils/ObbFile.cpp
@@ -91,22 +91,24 @@
 
     fd = ::open(filename, O_RDONLY);
     if (fd < 0) {
+        LOGW("couldn't open file %s: %s", filename, strerror(errno));
         goto out;
     }
     success = readFrom(fd);
     close(fd);
 
-out:
     if (!success) {
-        LOGW("failed to read from %s\n", filename);
+        LOGW("failed to read from %s (fd=%d)\n", filename, fd);
     }
+
+out:
     return success;
 }
 
 bool ObbFile::readFrom(int fd)
 {
     if (fd < 0) {
-        LOGW("failed to read file\n");
+        LOGW("attempt to read from invalid fd\n");
         return false;
     }
 
@@ -149,10 +151,16 @@
         footerSize = get4LE((unsigned char*)footer);
         if (footerSize > (size_t)fileLength - kFooterTagSize
                 || footerSize > kMaxBufSize) {
-            LOGW("claimed footer size is too large (0x%08lx; file size is 0x%08llx)\n",
+            LOGW("claimed footer size is too large (0x%08zx; file size is 0x%08llx)\n",
                     footerSize, fileLength);
             return false;
         }
+
+        if (footerSize < kFooterMinSize) {
+            LOGW("claimed footer size is too small (%08zx; minimum size is 0x%x)\n",
+                    footerSize, kFooterMinSize);
+            return false;
+        }
     }
 
     my_off64_t fileOffset = fileLength - footerSize - kFooterTagSize;
@@ -161,26 +169,22 @@
         return false;
     }
 
-    size_t readAmount = kMaxBufSize;
-    if (readAmount > footerSize)
-        readAmount = footerSize;
-
-    char* scanBuf = (char*)malloc(readAmount);
+    char* scanBuf = (char*)malloc(footerSize);
     if (scanBuf == NULL) {
         LOGW("couldn't allocate scanBuf: %s\n", strerror(errno));
         return false;
     }
 
-    actual = TEMP_FAILURE_RETRY(read(fd, scanBuf, readAmount));
+    actual = TEMP_FAILURE_RETRY(read(fd, scanBuf, footerSize));
     // readAmount is guaranteed to be less than kMaxBufSize
-    if (actual != (ssize_t)readAmount) {
+    if (actual != (ssize_t)footerSize) {
         LOGI("couldn't read ObbFile footer: %s\n", strerror(errno));
         free(scanBuf);
         return false;
     }
 
 #ifdef DEBUG
-    for (int i = 0; i < readAmount; ++i) {
+    for (int i = 0; i < footerSize; ++i) {
         LOGI("char: 0x%02x", scanBuf[i]);
     }
 #endif
@@ -197,7 +201,8 @@
     uint32_t packageNameLen = get4LE((unsigned char*)scanBuf + kPackageNameLenOffset);
     if (packageNameLen <= 0
             || packageNameLen > (footerSize - kPackageNameOffset)) {
-        LOGW("bad ObbFile package name length (0x%08x)\n", packageNameLen);
+        LOGW("bad ObbFile package name length (0x%04x; 0x%04x possible)\n",
+                packageNameLen, footerSize - kPackageNameOffset);
         free(scanBuf);
         return false;
     }
@@ -206,6 +211,11 @@
     mPackageName = String8(const_cast<char*>(packageName), packageNameLen);
 
     free(scanBuf);
+
+#ifdef DEBUG
+    LOGI("Obb scan succeeded: packageName=%s, version=%d\n", mPackageName.string(), mVersion);
+#endif
+
     return true;
 }
 
@@ -234,6 +244,8 @@
         return false;
     }
 
+    my_lseek64(fd, 0, SEEK_END);
+
     if (mPackageName.size() == 0 || mVersion == -1) {
         LOGW("tried to write uninitialized ObbFile data");
         return false;
diff --git a/libs/utils/tests/ObbFile_test.cpp b/libs/utils/tests/ObbFile_test.cpp
index 05aaf08..29bb70a 100644
--- a/libs/utils/tests/ObbFile_test.cpp
+++ b/libs/utils/tests/ObbFile_test.cpp
@@ -22,6 +22,8 @@
 
 #include <gtest/gtest.h>
 
+#include <fcntl.h>
+
 namespace android {
 
 #define TEST_FILENAME "/test.obb"
@@ -39,6 +41,11 @@
         const int totalLen = strlen(mExternalStorage) + strlen(TEST_FILENAME) + 1;
         mFileName = new char[totalLen];
         snprintf(mFileName, totalLen, "%s%s", mExternalStorage, TEST_FILENAME);
+
+        int fd = ::open(mFileName, O_CREAT | O_TRUNC);
+        if (fd < 0) {
+            FAIL() << "Couldn't create " << mFileName << " for tests";
+        }
     }
 
     virtual void TearDown() {
@@ -46,8 +53,8 @@
 };
 
 TEST_F(ObbFileTest, ReadFailure) {
-	EXPECT_FALSE(mObbFile->readFrom(-1))
-			<< "No failure on invalid file descriptor";
+    EXPECT_FALSE(mObbFile->readFrom(-1))
+            << "No failure on invalid file descriptor";
 }
 
 TEST_F(ObbFileTest, WriteThenRead) {
@@ -66,10 +73,10 @@
             << "couldn't read from fake .obb file";
 
     EXPECT_EQ(versionNum, mObbFile->getVersion())
-			<< "version didn't come out the same as it went in";
+            << "version didn't come out the same as it went in";
     const char* currentPackageName = mObbFile->getPackageName().string();
     EXPECT_STREQ(packageName, currentPackageName)
-			<< "package name didn't come out the same as it went in";
+            << "package name didn't come out the same as it went in";
 }
 
 }