Merge "String8: ensure static init done prior to empty string reference"
diff --git a/cmds/flatland/Main.cpp b/cmds/flatland/Main.cpp
index 99715d3..d6ac3d2 100644
--- a/cmds/flatland/Main.cpp
+++ b/cmds/flatland/Main.cpp
@@ -56,7 +56,7 @@
 
 static const BenchmarkDesc benchmarks[] = {
     { "16:10 Single Static Window",
-        2560, 1600, { 800, 1600, 2400 },
+        2560, 1600, { 800, 1200, 1600, 2400 },
         {
             {   // Window
                 0, staticGradient, opaque,
@@ -73,8 +73,26 @@
         },
     },
 
+    { "3:2 Single Static Window",
+        2048, 1536, { 1536 },
+        {
+            {   // Window
+                0, staticGradient, opaque,
+                0,    50,     2048,   1440,
+            },
+            {   // Status bar
+                0, staticGradient, opaque,
+                0,    0,      2048,   50,
+            },
+            {   // Navigation bar
+                0, staticGradient, opaque,
+                0,    1440,   2048,   96,
+            },
+        },
+    },
+
     { "16:10 App -> Home Transition",
-        2560, 1600, { 800, 1600, 2400 },
+        2560, 1600, { 800, 1200, 1600, 2400 },
         {
             {   // Wallpaper
                 0, staticGradient, opaque,
@@ -99,8 +117,34 @@
         },
     },
 
+    { "3:2 App -> Home Transition",
+        2048, 1536, { 1536 },
+        {
+            {   // Wallpaper
+                0, staticGradient, opaque,
+                0,    50,     2048,   1440,
+            },
+            {   // Launcher
+                0, staticGradient, blend,
+                0,    50,     2048,   1440,
+            },
+            {   // Outgoing activity
+                0, staticGradient, blendShrink,
+                20,    70,     2048,   1400,
+            },
+            {   // Status bar
+                0, staticGradient, opaque,
+                0,    0,      2048,   50,
+            },
+            {   // Navigation bar
+                0, staticGradient, opaque,
+                0,    1440,   2048,   96,
+            },
+        },
+    },
+
     { "16:10 SurfaceView -> Home Transition",
-        2560, 1600, { 800, 1600, 2400 },
+        2560, 1600, { 800, 1200, 1600, 2400 },
         {
             {   // Wallpaper
                 0, staticGradient, opaque,
@@ -128,6 +172,36 @@
             },
         },
     },
+
+    { "3:2 SurfaceView -> Home Transition",
+        2048, 1536, { 1536 },
+        {
+            {   // Wallpaper
+                0, staticGradient, opaque,
+                0,    50,     2048,   1440,
+            },
+            {   // Launcher
+                0, staticGradient, blend,
+                0,    50,     2048,   1440,
+            },
+            {   // Outgoing SurfaceView
+                0, staticGradient, blendShrink,
+                20,    70,     2048,   1400,
+            },
+            {   // Outgoing activity
+                0, staticGradient, blendShrink,
+                20,    70,     2048,   1400,
+            },
+            {   // Status bar
+                0, staticGradient, opaque,
+                0,    0,      2048,   50,
+            },
+            {   // Navigation bar
+                0, staticGradient, opaque,
+                0,    1440,   2048,   96,
+            },
+        },
+    },
 };
 
 static const ShaderDesc shaders[] = {
diff --git a/include/utils/Looper.h b/include/utils/Looper.h
index d4a0067..2e0651a 100644
--- a/include/utils/Looper.h
+++ b/include/utils/Looper.h
@@ -297,6 +297,13 @@
     void removeMessages(const sp<MessageHandler>& handler, int what);
 
     /**
+     * Return whether this looper's thread is currently idling -- that is, whether it
+     * stopped waiting for more work to do.  Note that this is intrinsically racy, since
+     * its state can change before you get the result back.
+     */
+    bool isIdling() const;
+
+    /**
      * Prepares a looper associated with the calling thread, and returns it.
      * If the thread already has a looper, it is returned.  Otherwise, a new
      * one is created, associated with the thread, and returned.
@@ -353,6 +360,10 @@
     Vector<MessageEnvelope> mMessageEnvelopes; // guarded by mLock
     bool mSendingMessage; // guarded by mLock
 
+    // Whether we are currently waiting for work.  Not protected by a lock,
+    // any use of it is racy anyway.
+    volatile bool mIdling;
+
     int mEpollFd; // immutable
 
     // Locked list of file descriptor monitoring requests.
diff --git a/libs/utils/Looper.cpp b/libs/utils/Looper.cpp
index a5e6645..c51df2d 100644
--- a/libs/utils/Looper.cpp
+++ b/libs/utils/Looper.cpp
@@ -84,6 +84,8 @@
     LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
             errno);
 
+    mIdling = false;
+
     // Allocate the epoll instance and register the wake pipe.
     mEpollFd = epoll_create(EPOLL_SIZE_HINT);
     LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);
@@ -214,9 +216,15 @@
     mResponses.clear();
     mResponseIndex = 0;
 
+    // We are about to idle.
+    mIdling = true;
+
     struct epoll_event eventItems[EPOLL_MAX_EVENTS];
     int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
 
+    // No longer idling.
+    mIdling = false;
+
     // Acquire lock.
     mLock.lock();
 
@@ -558,4 +566,8 @@
     } // release lock
 }
 
+bool Looper::isIdling() const {
+    return mIdling;
+}
+
 } // namespace android