Merge "media/hardware/HardwareAPI.h: Added metadata struct used by video decoder"
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 7cd5afd..ce8993d 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -39,7 +39,11 @@
 
     Vector<String16> services;
     Vector<String16> args;
-    if (argc == 1) {
+    bool showListOnly = false;
+    if ((argc == 2) && (strcmp(argv[1], "-l") == 0)) {
+        showListOnly = true;
+    }
+    if ((argc == 1) || showListOnly) {
         services = sm->listServices();
         services.sort(sort_func);
         args.add(String16("-a"));
@@ -64,6 +68,10 @@
         }
     }
 
+    if (showListOnly) {
+        return 0;
+    }
+
     for (size_t i=0; i<N; i++) {
         sp<IBinder> service = sm->checkService(services[i]);
         if (service != NULL) {
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 8e14a2c..131e03f 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -540,7 +540,6 @@
 }
 
 
-/* a simpler version of dexOptGenerateCacheFileName() */
 int create_cache_path(char path[PKG_PATH_MAX], const char *src)
 {
     char *tmp;
@@ -580,7 +579,7 @@
 }
 
 static void run_dexopt(int zip_fd, int odex_fd, const char* input_file_name,
-    const char* dexopt_flags)
+    const char* output_file_name, const char* dexopt_flags)
 {
     static const char* DEX_OPT_BIN = "/system/bin/dexopt";
     static const int MAX_INT_LEN = 12;      // '-'+10dig+'\0' -OR- 0x+8dig
@@ -590,11 +589,35 @@
     sprintf(zip_num, "%d", zip_fd);
     sprintf(odex_num, "%d", odex_fd);
 
+    ALOGV("Running %s in=%s out=%s\n", DEX_OPT_BIN, input_file_name, output_file_name);
     execl(DEX_OPT_BIN, DEX_OPT_BIN, "--zip", zip_num, odex_num, input_file_name,
         dexopt_flags, (char*) NULL);
     ALOGE("execl(%s) failed: %s\n", DEX_OPT_BIN, strerror(errno));
 }
 
+static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
+    const char* output_file_name, const char* dexopt_flags)
+{
+    static const char* DEX2OAT_BIN = "/system/bin/dex2oat";
+    static const int MAX_INT_LEN = 12;      // '-'+10dig+'\0' -OR- 0x+8dig
+    char zip_fd_arg[strlen("--zip-fd=") + MAX_INT_LEN];
+    char zip_location_arg[strlen("--zip-location=") + PKG_PATH_MAX];
+    char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN];
+    char oat_location_arg[strlen("--oat-name=") + PKG_PATH_MAX];
+
+    sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
+    sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
+    sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);
+    sprintf(oat_location_arg, "--oat-location=%s", output_file_name);
+
+    ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
+    execl(DEX2OAT_BIN, DEX2OAT_BIN,
+          zip_fd_arg, zip_location_arg,
+          oat_fd_arg, oat_location_arg,
+          (char*) NULL);
+    ALOGE("execl(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno));
+}
+
 static int wait_dexopt(pid_t pid, const char* apk_path)
 {
     int status;
@@ -631,31 +654,33 @@
 {
     struct utimbuf ut;
     struct stat apk_stat, dex_stat;
-    char dex_path[PKG_PATH_MAX];
+    char out_path[PKG_PATH_MAX];
     char dexopt_flags[PROPERTY_VALUE_MAX];
+    char dalvik_vm_lib[PROPERTY_VALUE_MAX];
     char *end;
-    int res, zip_fd=-1, odex_fd=-1;
+    int res, zip_fd=-1, out_fd=-1;
 
-        /* Before anything else: is there a .odex file?  If so, we have
-         * pre-optimized the apk and there is nothing to do here.
-         */
     if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
         return -1;
     }
 
     /* platform-specific flags affecting optimization and verification */
     property_get("dalvik.vm.dexopt-flags", dexopt_flags, "");
+    ALOGV("dalvik.vm.dexopt_flags=%s\n", dexopt_flags);
 
-    strcpy(dex_path, apk_path);
-    end = strrchr(dex_path, '.');
-    if (end != NULL) {
-        strcpy(end, ".odex");
-        if (stat(dex_path, &dex_stat) == 0) {
-            return 0;
-        }
+    /* The command to run depend ones the value of dalvik.vm.lib */
+    property_get("dalvik.vm.lib", dalvik_vm_lib, "libdvm.so");
+    ALOGV("dalvik.vm.lib=%s\n", dalvik_vm_lib);
+
+    /* Before anything else: is there a .odex file?  If so, we have
+     * precompiled the apk and there is nothing to do here.
+     */
+    sprintf(out_path, "%s%s", apk_path, ".odex");
+    if (stat(out_path, &dex_stat) == 0) {
+        return 0;
     }
 
-    if (create_cache_path(dex_path, apk_path)) {
+    if (create_cache_path(out_path, apk_path)) {
         return -1;
     }
 
@@ -664,24 +689,24 @@
 
     zip_fd = open(apk_path, O_RDONLY, 0);
     if (zip_fd < 0) {
-        ALOGE("dexopt cannot open '%s' for input\n", apk_path);
+        ALOGE("installd cannot open '%s' for input during dexopt\n", apk_path);
         return -1;
     }
 
-    unlink(dex_path);
-    odex_fd = open(dex_path, O_RDWR | O_CREAT | O_EXCL, 0644);
-    if (odex_fd < 0) {
-        ALOGE("dexopt cannot open '%s' for output\n", dex_path);
+    unlink(out_path);
+    out_fd = open(out_path, O_RDWR | O_CREAT | O_EXCL, 0644);
+    if (out_fd < 0) {
+        ALOGE("installd cannot open '%s' for output during dexopt\n", out_path);
         goto fail;
     }
-    if (fchmod(odex_fd,
+    if (fchmod(out_fd,
                S_IRUSR|S_IWUSR|S_IRGRP |
                (is_public ? S_IROTH : 0)) < 0) {
-        ALOGE("dexopt cannot chmod '%s'\n", dex_path);
+        ALOGE("installd cannot chmod '%s' during dexopt\n", out_path);
         goto fail;
     }
-    if (fchown(odex_fd, AID_SYSTEM, uid) < 0) {
-        ALOGE("dexopt cannot chown '%s'\n", dex_path);
+    if (fchown(out_fd, AID_SYSTEM, uid) < 0) {
+        ALOGE("installd cannot chown '%s' during dexopt\n", out_path);
         goto fail;
     }
 
@@ -692,11 +717,11 @@
     if (pid == 0) {
         /* child -- drop privileges before continuing */
         if (setgid(uid) != 0) {
-            ALOGE("setgid(%d) failed during dexopt\n", uid);
+            ALOGE("setgid(%d) failed in installd during dexopt\n", uid);
             exit(64);
         }
         if (setuid(uid) != 0) {
-            ALOGE("setuid(%d) during dexopt\n", uid);
+            ALOGE("setuid(%d) failed in installd during dexopt\n", uid);
             exit(65);
         }
         // drop capabilities
@@ -709,33 +734,39 @@
             ALOGE("capset failed: %s\n", strerror(errno));
             exit(66);
         }
-        if (flock(odex_fd, LOCK_EX | LOCK_NB) != 0) {
-            ALOGE("flock(%s) failed: %s\n", dex_path, strerror(errno));
+        if (flock(out_fd, LOCK_EX | LOCK_NB) != 0) {
+            ALOGE("flock(%s) failed: %s\n", out_path, strerror(errno));
             exit(67);
         }
 
-        run_dexopt(zip_fd, odex_fd, apk_path, dexopt_flags);
+        if (strncmp(dalvik_vm_lib, "libdvm", 6) == 0) {
+            run_dexopt(zip_fd, out_fd, apk_path, out_path, dexopt_flags);
+        } else if (strncmp(dalvik_vm_lib, "libart", 6) == 0) {
+            run_dex2oat(zip_fd, out_fd, apk_path, out_path, dexopt_flags);
+        } else {
+            exit(69);   /* Unexpected dalvik.vm.lib value */
+        }
         exit(68);   /* only get here on exec failure */
     } else {
         res = wait_dexopt(pid, apk_path);
         if (res != 0) {
-            ALOGE("dexopt failed on '%s' res = %d\n", dex_path, res);
+            ALOGE("dexopt in='%s' out='%s' res=%d\n", apk_path, out_path, res);
             goto fail;
         }
     }
 
     ut.actime = apk_stat.st_atime;
     ut.modtime = apk_stat.st_mtime;
-    utime(dex_path, &ut);
-    
-    close(odex_fd);
+    utime(out_path, &ut);
+
+    close(out_fd);
     close(zip_fd);
     return 0;
 
 fail:
-    if (odex_fd >= 0) {
-        close(odex_fd);
-        unlink(dex_path);
+    if (out_fd >= 0) {
+        close(out_fd);
+        unlink(out_path);
     }
     if (zip_fd >= 0) {
         close(zip_fd);
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index c918633..87f900a 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -198,7 +198,7 @@
     unsigned short count;
     int ret = -1;
 
-//    ALOGI("execute('%s')\n", cmd);
+    // ALOGI("execute('%s')\n", cmd);
 
         /* default reply is "" */
     reply[0] = 0;
@@ -240,7 +240,7 @@
     if (n > BUFFER_MAX) n = BUFFER_MAX;
     count = n;
 
-//    ALOGI("reply: '%s'\n", cmd);
+    // ALOGI("reply: '%s'\n", cmd);
     if (writex(s, &count, sizeof(count))) return -1;
     if (writex(s, cmd, count)) return -1;
     return 0;
diff --git a/cmds/rawbu/backup.cpp b/cmds/rawbu/backup.cpp
index 70e7b57..ff6719f 100644
--- a/cmds/rawbu/backup.cpp
+++ b/cmds/rawbu/backup.cpp
@@ -639,6 +639,12 @@
     fprintf(stderr, "options include:\n"
                     "  -h              Show this help text.\n"
                     "  -a              Backup all files.\n");
+    fprintf(stderr, "\n backup-file-path Defaults to /sdcard/backup.dat .\n"
+                    "                  On devices that emulate the sdcard, you will need to\n"
+                    "                  explicitly specify the directory it is mapped to,\n"
+                    "                  to avoid recursive backup or deletion of the backup file\n"
+                    "                  during restore.\n\n"
+                    "                  Eg. /data/media/0/backup.dat\n");
     fprintf(stderr, "\nThe %s command allows you to perform low-level\n"
                     "backup and restore of the /data partition.  This is\n"
                     "where all user data is kept, allowing for a fairly\n"
diff --git a/include/gui/CpuConsumer.h b/include/gui/CpuConsumer.h
index cf1dab6..3c178ef 100644
--- a/include/gui/CpuConsumer.h
+++ b/include/gui/CpuConsumer.h
@@ -72,6 +72,18 @@
     // log messages.
     void setName(const String8& name);
 
+    // setDefaultBufferSize is used to set the size of buffers returned by
+    // requestBuffers when a width and height of zero is requested.
+    // A call to setDefaultBufferSize() may trigger requestBuffers() to
+    // be called from the client. Default size is 1x1.
+    status_t setDefaultBufferSize(uint32_t width, uint32_t height);
+
+    // setDefaultBufferFormat allows CpuConsumer's BufferQueue to create buffers
+    // of a defaultFormat if no format is specified by producer. Formats are
+    // enumerated in graphics.h; the initial default is
+    // HAL_PIXEL_FORMAT_RGBA_8888.
+    status_t setDefaultBufferFormat(uint32_t defaultFormat);
+
     // Gets the next graphics buffer from the producer and locks it for CPU use,
     // filling out the passed-in locked buffer structure with the native pointer
     // and metadata. Returns BAD_VALUE if no new buffer is available, and
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 2780d9a..28b74ba 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -467,6 +467,10 @@
 
 
             result = executeCommand(cmd);
+        } else if (result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
+            ALOGE("talkWithDriver(fd=%d) returned unexpected error %d, aborting",
+                  mProcess->mDriverFD, result);
+            abort();
         }
         
         // After executing the command, ensure that the thread is returned to the
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index 0834361..123b470 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -55,6 +55,18 @@
     mBufferQueue->setConsumerName(name);
 }
 
+status_t CpuConsumer::setDefaultBufferSize(uint32_t width, uint32_t height)
+{
+    Mutex::Autolock _l(mMutex);
+    return mBufferQueue->setDefaultBufferSize(width, height);
+}
+
+status_t CpuConsumer::setDefaultBufferFormat(uint32_t defaultFormat)
+{
+    Mutex::Autolock _l(mMutex);
+    return mBufferQueue->setDefaultBufferFormat(defaultFormat);
+}
+
 status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {
     status_t err;
 
diff --git a/opengl/tools/glgen/gen b/opengl/tools/glgen/gen
index d236c1e..7146a29 100755
--- a/opengl/tools/glgen/gen
+++ b/opengl/tools/glgen/gen
@@ -32,10 +32,6 @@
 echo "package android.util; public class Log {public static void w(String a, String b) {} public static void e(String a, String b) {}}" > out/android/util/Log.java
 
 echo "package android.opengl; public abstract class EGLObjectHandle { public int getHandle() { return 0; } }" > out/android/opengl/EGLObjectHandle.java
-echo "package android.opengl; public class EGLSurface extends EGLObjectHandle {  }" > out/android/opengl/EGLSurface.java
-echo "package android.opengl; public class EGLContext extends EGLObjectHandle {  }" > out/android/opengl/EGLContext.java
-echo "package android.opengl; public class EGLDisplay extends EGLObjectHandle {  }" > out/android/opengl/EGLDisplay.java
-echo "package android.opengl; public class EGLConfig extends EGLObjectHandle {  }" > out/android/opengl/EGLConfig.java
 
 
 echo "package android.graphics;" > out/android/graphics/SurfaceTexture.java
@@ -47,6 +43,7 @@
 echo "package android.view;" > out/android/view/SurfaceHolder.java
 echo "public interface SurfaceHolder { Surface getSurface(); }" >> out/android/view/SurfaceHolder.java
 
+cp static/egl/*.java out/android/opengl/
 
 GLFILE=out/javax/microedition/khronos/opengles/GL.java
 cp stubs/jsr239/GLHeader.java-if $GLFILE
@@ -141,8 +138,8 @@
             echo
             SAID_PLEASE=1
         fi
-        echo "    " cp $2/$3 $1
-        echo "    " git add $1/$3
+        echo "    cp $2/$3 $1"
+        echo "    (cd $1; git add $3)"
         KEEP_GENERATED=1
     fi
 }
@@ -161,6 +158,11 @@
     compareGenerated ../../../../base/core/jni generated/C android_opengl_${x}.cpp
 done
 
+for x in EGLConfig EGLContext EGLDisplay EGLObjectHandle EGLSurface
+do
+    compareGenerated ../../../../base/opengl/java/android/opengl generated/android/opengl ${x}.java
+done
+
 if [ $KEEP_GENERATED == "0" ] ; then
     rm -rf generated
 fi
diff --git a/opengl/tools/glgen/static/egl/EGLConfig.java b/opengl/tools/glgen/static/egl/EGLConfig.java
index d457c9f..a7a6bbb 100644
--- a/opengl/tools/glgen/static/egl/EGLConfig.java
+++ b/opengl/tools/glgen/static/egl/EGLConfig.java
@@ -29,7 +29,7 @@
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
+        if (!(o instanceof EGLConfig)) return false;
 
         EGLConfig that = (EGLConfig) o;
         return getHandle() == that.getHandle();
diff --git a/opengl/tools/glgen/static/egl/EGLContext.java b/opengl/tools/glgen/static/egl/EGLContext.java
index 41b8ef1..c93bd6e 100644
--- a/opengl/tools/glgen/static/egl/EGLContext.java
+++ b/opengl/tools/glgen/static/egl/EGLContext.java
@@ -29,7 +29,7 @@
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
+        if (!(o instanceof EGLContext)) return false;
 
         EGLContext that = (EGLContext) o;
         return getHandle() == that.getHandle();
diff --git a/opengl/tools/glgen/static/egl/EGLDisplay.java b/opengl/tools/glgen/static/egl/EGLDisplay.java
index 17d1a64..5b8043a 100644
--- a/opengl/tools/glgen/static/egl/EGLDisplay.java
+++ b/opengl/tools/glgen/static/egl/EGLDisplay.java
@@ -29,7 +29,7 @@
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
+        if (!(o instanceof EGLDisplay)) return false;
 
         EGLDisplay that = (EGLDisplay) o;
         return getHandle() == that.getHandle();
diff --git a/opengl/tools/glgen/static/egl/EGLSurface.java b/opengl/tools/glgen/static/egl/EGLSurface.java
index 65bec4f..c379dc9 100644
--- a/opengl/tools/glgen/static/egl/EGLSurface.java
+++ b/opengl/tools/glgen/static/egl/EGLSurface.java
@@ -29,7 +29,7 @@
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
+        if (!(o instanceof EGLSurface)) return false;
 
         EGLSurface that = (EGLSurface) o;
         return getHandle() == that.getHandle();
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 71b235a..f2051dd 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -18,6 +18,8 @@
     DisplayHardware/HWComposer.cpp \
     DisplayHardware/PowerHAL.cpp \
     DisplayHardware/VirtualDisplaySurface.cpp \
+    EventLog/EventLogTags.logtags \
+    EventLog/EventLog.cpp
 
 LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
diff --git a/services/surfaceflinger/EventLog/EventLog.cpp b/services/surfaceflinger/EventLog/EventLog.cpp
new file mode 100644
index 0000000..815242b
--- /dev/null
+++ b/services/surfaceflinger/EventLog/EventLog.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2013 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <cutils/log.h>
+#include <utils/String8.h>
+
+#include "EventLog.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+ANDROID_SINGLETON_STATIC_INSTANCE(EventLog)
+
+
+EventLog::EventLog() {
+}
+
+void EventLog::doLogJank(const String8& window, int32_t value) {
+    EventLog::TagBuffer buffer(LOGTAG_SF_JANK);
+    buffer.startList(2);
+    buffer.writeString8(window);
+    buffer.writeInt32(value);
+    buffer.endList();
+    buffer.log();
+}
+
+void EventLog::logJank(const String8& window, int32_t value) {
+    EventLog::getInstance().doLogJank(window, value);
+}
+
+// ---------------------------------------------------------------------------
+
+EventLog::TagBuffer::TagBuffer(int32_t tag)
+    : mPos(0), mTag(tag), mOverflow(false) {
+}
+
+void EventLog::TagBuffer::log() {
+    if (mOverflow) {
+        ALOGW("couldn't log to binary event log: overflow.");
+    } else if (android_bWriteLog(mTag, mStorage, mPos) < 0) {
+        ALOGE("couldn't log to EventLog: %s", strerror(errno));
+    }
+    // purge the buffer
+    mPos = 0;
+    mOverflow = false;
+}
+
+void EventLog::TagBuffer::startList(int8_t count) {
+    if (mOverflow) return;
+    const size_t needed = 1 + sizeof(count);
+    if (mPos + needed > STORAGE_MAX_SIZE) {
+        mOverflow = true;
+        return;
+    }
+    mStorage[mPos + 0] = EVENT_TYPE_LIST;
+    mStorage[mPos + 1] = count;
+    mPos += needed;
+}
+
+void EventLog::TagBuffer::endList() {
+    if (mOverflow) return;
+    const size_t needed = 1;
+    if (mPos + needed > STORAGE_MAX_SIZE) {
+        mOverflow = true;
+        return;
+    }
+    mStorage[mPos + 0] = '\n';
+    mPos += needed;
+}
+
+void EventLog::TagBuffer::writeInt32(int32_t value) {
+    if (mOverflow) return;
+    const size_t needed = 1 + sizeof(value);
+    if (mPos + needed > STORAGE_MAX_SIZE) {
+        mOverflow = true;
+        return;
+    }
+    mStorage[mPos + 0] = EVENT_TYPE_INT;
+    memcpy(&mStorage[mPos + 1], &value, sizeof(value));
+    mPos += needed;
+}
+
+void EventLog::TagBuffer::writeInt64(int64_t value) {
+    if (mOverflow) return;
+    const size_t needed = 1 + sizeof(value);
+    if (mPos + needed > STORAGE_MAX_SIZE) {
+        mOverflow = true;
+        return;
+    }
+    mStorage[mPos + 0] = EVENT_TYPE_LONG;
+    memcpy(&mStorage[mPos + 1], &value, sizeof(value));
+    mPos += needed;
+}
+
+void EventLog::TagBuffer::writeString8(const String8& value) {
+    if (mOverflow) return;
+    const int32_t stringLen = value.length();
+    const size_t needed = 1 + sizeof(int32_t) + stringLen;
+    if (mPos + needed > STORAGE_MAX_SIZE) {
+        mOverflow = true;
+        return;
+    }
+    mStorage[mPos + 0] = EVENT_TYPE_STRING;
+    memcpy(&mStorage[mPos + 1], &stringLen, sizeof(int32_t));
+    memcpy(&mStorage[mPos + 5], value.string(), stringLen);
+    mPos += needed;
+}
+
+// ---------------------------------------------------------------------------
+}// namespace android
+
+// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/EventLog/EventLog.h b/services/surfaceflinger/EventLog/EventLog.h
new file mode 100644
index 0000000..2f1cd9b
--- /dev/null
+++ b/services/surfaceflinger/EventLog/EventLog.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2013 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.
+ */
+
+#include <stdint.h>
+#include <utils/Errors.h>
+#include <utils/Singleton.h>
+
+#ifndef ANDROID_SF_EVENTLOG_H
+#define ANDROID_SF_EVENTLOG_H
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class String8;
+
+class EventLog : public Singleton<EventLog> {
+
+public:
+    static void logJank(const String8& window, int32_t value);
+
+protected:
+    EventLog();
+
+private:
+    /*
+     * EventLogBuffer is a helper class to construct an in-memory event log
+     * tag. In this version the buffer is not dynamic, so write operation can
+     * fail if there is not enough space in the temporary buffer.
+     * Once constructed, the buffer can be logger by calling the log()
+     * method.
+     */
+
+    class TagBuffer {
+        enum { STORAGE_MAX_SIZE = 128 };
+        int32_t mPos;
+        int32_t mTag;
+        bool mOverflow;
+        char mStorage[STORAGE_MAX_SIZE];
+    public:
+        TagBuffer(int32_t tag);
+
+        // starts list of items
+        void startList(int8_t count);
+        // terminates the list
+        void endList();
+        // write a 32-bit integer
+        void writeInt32(int32_t value);
+        // write a 64-bit integer
+        void writeInt64(int64_t value);
+        // write a C string
+        void writeString8(const String8& value);
+
+        // outputs the the buffer to the log
+        void log();
+    };
+
+    friend class Singleton<EventLog>;
+    EventLog(const EventLog&);
+    EventLog& operator =(const EventLog&);
+
+    enum { LOGTAG_SF_JANK = 60100 };
+    void doLogJank(const String8& window, int32_t value);
+};
+
+// ---------------------------------------------------------------------------
+}// namespace android
+// ---------------------------------------------------------------------------
+
+#endif /* ANDROID_SF_EVENTLOG_H */
diff --git a/services/surfaceflinger/EventLog/EventLogTags.logtags b/services/surfaceflinger/EventLog/EventLogTags.logtags
new file mode 100644
index 0000000..c83692f
--- /dev/null
+++ b/services/surfaceflinger/EventLog/EventLogTags.logtags
@@ -0,0 +1,38 @@
+# The entries in this file map a sparse set of log tag numbers to tag names.
+# This is installed on the device, in /system/etc, and parsed by logcat.
+#
+# Tag numbers are decimal integers, from 0 to 2^31.  (Let's leave the
+# negative values alone for now.)
+#
+# Tag names are one or more ASCII letters and numbers or underscores, i.e.
+# "[A-Z][a-z][0-9]_".  Do not include spaces or punctuation (the former
+# impacts log readability, the latter makes regex searches more annoying).
+#
+# Tag numbers and names are separated by whitespace.  Blank lines and lines
+# starting with '#' are ignored.
+#
+# Optionally, after the tag names can be put a description for the value(s)
+# of the tag. Description are in the format
+#    (<name>|data type[|data unit])
+# Multiple values are separated by commas.
+#
+# The data type is a number from the following values:
+# 1: int
+# 2: long
+# 3: string
+# 4: list
+#
+# The data unit is a number taken from the following list:
+# 1: Number of objects
+# 2: Number of bytes
+# 3: Number of milliseconds
+# 4: Number of allocations
+# 5: Id
+# 6: Percent
+# Default value for data of type int/long is 2 (bytes).
+
+# surfaceflinger
+60100 sf_jank (window|3),(value|1)
+
+# NOTE - the range 1000000-2000000 is reserved for partners and others who
+# want to define their own log tags without conflicting with the core platform.
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index ee69222..b08b8d1 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -165,7 +165,7 @@
 // set-up
 // ---------------------------------------------------------------------------
 
-String8 Layer::getName() const {
+const String8& Layer::getName() const {
     return mName;
 }
 
@@ -281,7 +281,7 @@
 }
 
 Rect Layer::computeBounds() const {
-    const Layer::State& s(drawingState());
+    const Layer::State& s(getDrawingState());
     Rect win(s.active.w, s.active.h);
     if (!s.active.crop.isEmpty()) {
         win.intersect(s.active.crop, &win);
@@ -305,7 +305,7 @@
 
     // the active.crop is the area of the window that gets cropped, but not
     // scaled in any ways.
-    const State& s(drawingState());
+    const State& s(getDrawingState());
 
     // apply the projection's clipping to the window crop in
     // layerstack space, and convert-back to layer space.
@@ -372,7 +372,7 @@
     }
 
     // this gives us only the "orientation" component of the transform
-    const State& s(drawingState());
+    const State& s(getDrawingState());
     if (!isOpaque() || s.alpha != 0xFF) {
         layer.setBlending(mPremultipliedAlpha ?
                 HWC_BLENDING_PREMULT :
@@ -627,7 +627,7 @@
 void Layer::drawWithOpenGL(
         const sp<const DisplayDevice>& hw, const Region& clip) const {
     const uint32_t fbHeight = hw->getHeight();
-    const State& s(drawingState());
+    const State& s(getDrawingState());
 
     if (mFlinger->getGlesVersion() == GLES_VERSION_1_0) {
         setupOpenGL10(mPremultipliedAlpha, isOpaque(), s.alpha);
@@ -730,7 +730,7 @@
 
 void Layer::computeGeometry(const sp<const DisplayDevice>& hw, LayerMesh* mesh) const
 {
-    const Layer::State& s(drawingState());
+    const Layer::State& s(getDrawingState());
     const Transform tr(hw->getTransform() * s.transform);
     const uint32_t hw_h = hw->getHeight();
     Rect win(s.active.w, s.active.h);
@@ -805,11 +805,11 @@
 uint32_t Layer::doTransaction(uint32_t flags) {
     ATRACE_CALL();
 
-    const Layer::State& front(drawingState());
-    const Layer::State& temp(currentState());
+    const Layer::State& s(getDrawingState());
+    const Layer::State& c(getCurrentState());
 
-    const bool sizeChanged = (temp.requested.w != front.requested.w) ||
-                             (temp.requested.h != front.requested.h);
+    const bool sizeChanged = (c.requested.w != s.requested.w) ||
+                             (c.requested.h != s.requested.h);
 
     if (sizeChanged) {
         // the size changed, we need to ask our client to request a new buffer
@@ -819,46 +819,46 @@
                 "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
                 "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
                 "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
-                this, (const char*) getName(), mCurrentTransform, mCurrentScalingMode,
-                temp.active.w, temp.active.h,
-                temp.active.crop.left,
-                temp.active.crop.top,
-                temp.active.crop.right,
-                temp.active.crop.bottom,
-                temp.active.crop.getWidth(),
-                temp.active.crop.getHeight(),
-                temp.requested.w, temp.requested.h,
-                temp.requested.crop.left,
-                temp.requested.crop.top,
-                temp.requested.crop.right,
-                temp.requested.crop.bottom,
-                temp.requested.crop.getWidth(),
-                temp.requested.crop.getHeight(),
-                front.active.w, front.active.h,
-                front.active.crop.left,
-                front.active.crop.top,
-                front.active.crop.right,
-                front.active.crop.bottom,
-                front.active.crop.getWidth(),
-                front.active.crop.getHeight(),
-                front.requested.w, front.requested.h,
-                front.requested.crop.left,
-                front.requested.crop.top,
-                front.requested.crop.right,
-                front.requested.crop.bottom,
-                front.requested.crop.getWidth(),
-                front.requested.crop.getHeight());
+                this, getName().string(), mCurrentTransform, mCurrentScalingMode,
+                c.active.w, c.active.h,
+                c.active.crop.left,
+                c.active.crop.top,
+                c.active.crop.right,
+                c.active.crop.bottom,
+                c.active.crop.getWidth(),
+                c.active.crop.getHeight(),
+                c.requested.w, c.requested.h,
+                c.requested.crop.left,
+                c.requested.crop.top,
+                c.requested.crop.right,
+                c.requested.crop.bottom,
+                c.requested.crop.getWidth(),
+                c.requested.crop.getHeight(),
+                s.active.w, s.active.h,
+                s.active.crop.left,
+                s.active.crop.top,
+                s.active.crop.right,
+                s.active.crop.bottom,
+                s.active.crop.getWidth(),
+                s.active.crop.getHeight(),
+                s.requested.w, s.requested.h,
+                s.requested.crop.left,
+                s.requested.crop.top,
+                s.requested.crop.right,
+                s.requested.crop.bottom,
+                s.requested.crop.getWidth(),
+                s.requested.crop.getHeight());
 
         // record the new size, form this point on, when the client request
         // a buffer, it'll get the new size.
         mSurfaceFlingerConsumer->setDefaultBufferSize(
-                temp.requested.w, temp.requested.h);
+                c.requested.w, c.requested.h);
     }
 
     if (!isFixedSize()) {
 
-        const bool resizePending = (temp.requested.w != temp.active.w) ||
-                                   (temp.requested.h != temp.active.h);
+        const bool resizePending = (c.requested.w != c.active.w) ||
+                                   (c.requested.h != c.active.h);
 
         if (resizePending) {
             // don't let Layer::doTransaction update the drawing state
@@ -878,23 +878,23 @@
     // this is used by Layer, which special cases resizes.
     if (flags & eDontUpdateGeometryState)  {
     } else {
-        Layer::State& editTemp(currentState());
-        editTemp.active = temp.requested;
+        Layer::State& editCurrentState(getCurrentState());
+        editCurrentState.active = c.requested;
     }
 
-    if (front.active != temp.active) {
+    if (s.active != c.active) {
         // invalidate and recompute the visible regions if needed
         flags |= Layer::eVisibleRegion;
     }
 
-    if (temp.sequence != front.sequence) {
+    if (c.sequence != s.sequence) {
         // invalidate and recompute the visible regions if needed
         flags |= eVisibleRegion;
         this->contentDirty = true;
 
         // we may use linear filtering, if the matrix scales us
-        const uint8_t type = temp.transform.getType();
-        mNeedsFiltering = (!temp.transform.preserveRects() ||
+        const uint8_t type = c.transform.getType();
+        mNeedsFiltering = (!c.transform.preserveRects() ||
                 (type >= Transform::SCALE));
     }
 
@@ -1159,7 +1159,7 @@
         };
 
 
-        Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
+        Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions);
 
         if (mSurfaceFlingerConsumer->updateTexImage(&r) != NO_ERROR) {
             // something happened!
@@ -1213,11 +1213,11 @@
         glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
         // FIXME: postedRegion should be dirty & bounds
-        const Layer::State& front(drawingState());
-        Region dirtyRegion(Rect(front.active.w, front.active.h));
+        const Layer::State& s(getDrawingState());
+        Region dirtyRegion(Rect(s.active.w, s.active.h));
 
         // transform the dirty region to window-manager space
-        outDirtyRegion = (front.transform.transform(dirtyRegion));
+        outDirtyRegion = (s.transform.transform(dirtyRegion));
     }
     return outDirtyRegion;
 }
@@ -1254,7 +1254,7 @@
 
 void Layer::dump(String8& result, Colorizer& colorizer) const
 {
-    const Layer::State& s(drawingState());
+    const Layer::State& s(getDrawingState());
 
     colorizer.colorize(result, Colorizer::GREEN);
     result.appendFormat(
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 11fdbb5..f79bf2d 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -131,6 +131,7 @@
 
     Layer(SurfaceFlinger* flinger, const sp<Client>& client,
             const String8& name, uint32_t w, uint32_t h, uint32_t flags);
+
     virtual ~Layer();
 
     // the this layer's size and format
@@ -147,8 +148,6 @@
     bool setCrop(const Rect& crop);
     bool setLayerStack(uint32_t layerStack);
 
-    void commitTransaction();
-
     uint32_t getTransactionFlags(uint32_t flags);
     uint32_t setTransactionFlags(uint32_t flags);
 
@@ -157,89 +156,13 @@
 
     sp<IBinder> getHandle();
     sp<BufferQueue> getBufferQueue() const;
-    String8 getName() const;
+    const String8& getName() const;
 
     // -----------------------------------------------------------------------
+    // Virtuals
 
     virtual const char* getTypeId() const { return "Layer"; }
 
-    virtual void setGeometry(const sp<const DisplayDevice>& hw,
-            HWComposer::HWCLayerInterface& layer);
-    virtual void setPerFrameData(const sp<const DisplayDevice>& hw,
-            HWComposer::HWCLayerInterface& layer);
-    virtual void setAcquireFence(const sp<const DisplayDevice>& hw,
-            HWComposer::HWCLayerInterface& layer);
-
-    /*
-     * called after page-flip
-     */
-    virtual void onLayerDisplayed(const sp<const DisplayDevice>& hw,
-            HWComposer::HWCLayerInterface* layer);
-
-    /*
-     * called before composition.
-     * returns true if the layer has pending updates.
-     */
-    virtual bool onPreComposition();
-
-    /*
-     *  called after composition.
-     */
-    virtual void onPostComposition();
-
-    /*
-     * draw - performs some global clipping optimizations
-     * and calls onDraw().
-     * Typically this method is not overridden, instead implement onDraw()
-     * to perform the actual drawing.
-     */
-    virtual void draw(const sp<const DisplayDevice>& hw, const Region& clip) const;
-    virtual void draw(const sp<const DisplayDevice>& hw);
-
-    /*
-     * onDraw - draws the surface.
-     */
-    virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const;
-
-    /*
-     * needsLinearFiltering - true if this surface's state requires filtering
-     */
-    virtual bool needsFiltering(const sp<const DisplayDevice>& hw) const;
-
-    /*
-     * doTransaction - process the transaction. This is a good place to figure
-     * out which attributes of the surface have changed.
-     */
-    virtual uint32_t doTransaction(uint32_t transactionFlags);
-
-    /*
-     * setVisibleRegion - called to set the new visible region. This gives
-     * a chance to update the new visible region or record the fact it changed.
-     */
-    virtual void setVisibleRegion(const Region& visibleRegion);
-
-    /*
-     * setCoveredRegion - called when the covered region changes. The covered
-     * region corresponds to any area of the surface that is covered
-     * (transparently or not) by another surface.
-     */
-    virtual void setCoveredRegion(const Region& coveredRegion);
-
-    /*
-     * setVisibleNonTransparentRegion - called when the visible and
-     * non-transparent region changes.
-     */
-    virtual void setVisibleNonTransparentRegion(const Region&
-            visibleNonTransparentRegion);
-
-    /*
-     * latchBuffer - called each time the screen is redrawn and returns whether
-     * the visible regions need to be recomputed (this is a fairly heavy
-     * operation, so this should be set only if needed). Typically this is used
-     * to figure out if the content or size of a surface has changed.
-     */
-    virtual Region latchBuffer(bool& recomputeVisibleRegions);
-
     /*
      * isOpaque - true if this surface is opaque
      */
@@ -267,28 +190,102 @@
      */
     virtual bool isFixedSize() const;
 
+protected:
+    /*
+     * onDraw - draws the surface.
+     */
+    virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const;
+
+public:
+    // -----------------------------------------------------------------------
+
+    void setGeometry(const sp<const DisplayDevice>& hw,
+            HWComposer::HWCLayerInterface& layer);
+    void setPerFrameData(const sp<const DisplayDevice>& hw,
+            HWComposer::HWCLayerInterface& layer);
+    void setAcquireFence(const sp<const DisplayDevice>& hw,
+            HWComposer::HWCLayerInterface& layer);
+
+    /*
+     * called after page-flip
+     */
+    void onLayerDisplayed(const sp<const DisplayDevice>& hw,
+            HWComposer::HWCLayerInterface* layer);
+
+    /*
+     * called before composition.
+     * returns true if the layer has pending updates.
+     */
+    bool onPreComposition();
+
+    /*
+     *  called after composition.
+     */
+    void onPostComposition();
+
+    /*
+     * draw - performs some global clipping optimizations
+     * and calls onDraw().
+     */
+    void draw(const sp<const DisplayDevice>& hw, const Region& clip) const;
+    void draw(const sp<const DisplayDevice>& hw);
+
+    /*
+     * doTransaction - process the transaction. This is a good place to figure
+     * out which attributes of the surface have changed.
+     */
+    uint32_t doTransaction(uint32_t transactionFlags);
+
+    /*
+     * setVisibleRegion - called to set the new visible region. This gives
+     * a chance to update the new visible region or record the fact it changed.
+     */
+    void setVisibleRegion(const Region& visibleRegion);
+
+    /*
+     * setCoveredRegion - called when the covered region changes. The covered
+     * region corresponds to any area of the surface that is covered
+     * (transparently or not) by another surface.
+     */
+    void setCoveredRegion(const Region& coveredRegion);
+
+    /*
+     * setVisibleNonTransparentRegion - called when the visible and
+     * non-transparent region changes.
+     */
+    void setVisibleNonTransparentRegion(const Region&
+            visibleNonTransparentRegion);
+
+    /*
+     * latchBuffer - called each time the screen is redrawn and returns whether
+     * the visible regions need to be recomputed (this is a fairly heavy
+     * operation, so this should be set only if needed). Typically this is used
+     * to figure out if the content or size of a surface has changed.
+     */
+    Region latchBuffer(bool& recomputeVisibleRegions);
+
     /*
      * called with the state lock when the surface is removed from the
      * current list
      */
-    virtual void onRemoved();
+    void onRemoved();
 
 
     // Updates the transform hint in our SurfaceFlingerConsumer to match
     // the current orientation of the display device.
-    virtual void updateTransformHint(const sp<const DisplayDevice>& hw) const;
+    void updateTransformHint(const sp<const DisplayDevice>& hw) const;
 
     /*
      * returns the rectangle that crops the content of the layer and scales it
      * to the layer's size.
      */
-    virtual Rect getContentCrop() const;
+    Rect getContentCrop() const;
 
     /*
      * returns the transform bits (90 rotation / h-flip / v-flip) of the
      * layer's content
      */
-    virtual uint32_t getContentTransform() const;
+    uint32_t getContentTransform() const;
 
     // -----------------------------------------------------------------------
 
@@ -299,15 +296,15 @@
     // only for debugging
     inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
 
-    inline  const State&    drawingState() const    { return mDrawingState; }
-    inline  const State&    currentState() const    { return mCurrentState; }
-    inline  State&          currentState()          { return mCurrentState; }
+    inline  const State&    getDrawingState() const { return mDrawingState; }
+    inline  const State&    getCurrentState() const { return mCurrentState; }
+    inline  State&          getCurrentState()       { return mCurrentState; }
 
 
     /* always call base class first */
-    virtual void dump(String8& result, Colorizer& colorizer) const;
-    virtual void dumpStats(String8& result) const;
-    virtual void clearStats();
+    void dump(String8& result, Colorizer& colorizer) const;
+    void dumpStats(String8& result) const;
+    void clearStats();
 
 protected:
     // constant
@@ -333,6 +330,10 @@
     // Interface implementation for SurfaceFlingerConsumer::FrameAvailableListener
     virtual void onFrameAvailable();
 
+    void commitTransaction();
+
+    // needsLinearFiltering - true if this surface's state requires filtering
+    bool needsFiltering(const sp<const DisplayDevice>& hw) const;
 
     uint32_t getEffectiveUsage(uint32_t usage) const;
     Rect computeCrop(const sp<const DisplayDevice>& hw) const;
diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp
index 36bafdb..f4adeeb 100644
--- a/services/surfaceflinger/LayerDim.cpp
+++ b/services/surfaceflinger/LayerDim.cpp
@@ -43,7 +43,7 @@
 
 void LayerDim::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
 {
-    const State& s(drawingState());
+    const State& s(getDrawingState());
     if (s.alpha>0) {
         const GLfloat alpha = s.alpha/255.0f;
         const uint32_t fbHeight = hw->getHeight();
@@ -71,7 +71,7 @@
 }
 
 bool LayerDim::isVisible() const {
-    const Layer::State& s(drawingState());
+    const Layer::State& s(getDrawingState());
     return !(s.flags & layer_state_t::eLayerHidden) && s.alpha;
 }
 
diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h
index e19bf52..2a96149 100644
--- a/services/surfaceflinger/LayerDim.h
+++ b/services/surfaceflinger/LayerDim.h
@@ -36,13 +36,10 @@
                         const String8& name, uint32_t w, uint32_t h, uint32_t flags);
         virtual ~LayerDim();
 
+    virtual const char* getTypeId() const { return "LayerDim"; }
     virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const;
     virtual bool isOpaque() const         { return false; }
     virtual bool isSecure() const         { return false; }
-    virtual bool isProtectedByApp() const { return false; }
-    virtual bool isProtectedByDRM() const { return false; }
-    virtual const char* getTypeId() const { return "LayerDim"; }
-
     virtual bool isFixedSize() const      { return true; }
     virtual bool isVisible() const;
 };
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index fbd9f25..fc193e5 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -856,10 +856,10 @@
 void SurfaceFlinger::preComposition()
 {
     bool needExtraInvalidate = false;
-    const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
-    const size_t count = currentLayers.size();
+    const LayerVector& layers(mDrawingState.layersSortedByZ);
+    const size_t count = layers.size();
     for (size_t i=0 ; i<count ; i++) {
-        if (currentLayers[i]->onPreComposition()) {
+        if (layers[i]->onPreComposition()) {
             needExtraInvalidate = true;
         }
     }
@@ -870,10 +870,10 @@
 
 void SurfaceFlinger::postComposition()
 {
-    const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
-    const size_t count = currentLayers.size();
+    const LayerVector& layers(mDrawingState.layersSortedByZ);
+    const size_t count = layers.size();
     for (size_t i=0 ; i<count ; i++) {
-        currentLayers[i]->onPostComposition();
+        layers[i]->onPostComposition();
     }
 
     if (mAnimCompositionPending) {
@@ -900,7 +900,7 @@
         mVisibleRegionsDirty = false;
         invalidateHwcGeometry();
 
-        const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
+        const LayerVector& layers(mDrawingState.layersSortedByZ);
         for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
             Region opaqueRegion;
             Region dirtyRegion;
@@ -909,13 +909,13 @@
             const Transform& tr(hw->getTransform());
             const Rect bounds(hw->getBounds());
             if (hw->canDraw()) {
-                SurfaceFlinger::computeVisibleRegions(currentLayers,
+                SurfaceFlinger::computeVisibleRegions(layers,
                         hw->getLayerStack(), dirtyRegion, opaqueRegion);
 
-                const size_t count = currentLayers.size();
+                const size_t count = layers.size();
                 for (size_t i=0 ; i<count ; i++) {
-                    const sp<Layer>& layer(currentLayers[i]);
-                    const Layer::State& s(layer->drawingState());
+                    const sp<Layer>& layer(layers[i]);
+                    const Layer::State& s(layer->getDrawingState());
                     if (s.layerStack == hw->getLayerStack()) {
                         Region drawRegion(tr.transform(
                                 layer->visibleNonTransparentRegion));
@@ -1056,6 +1056,12 @@
 {
     ATRACE_CALL();
 
+    // here we keep a copy of the drawing state (that is the state that's
+    // going to be overwritten by handleTransactionLocked()) outside of
+    // mStateLock so that the side-effects of the State assignment
+    // don't happen with mStateLock held (which can cause deadlocks).
+    State drawingState(mDrawingState);
+
     Mutex::Autolock _l(mStateLock);
     const nsecs_t now = systemTime();
     mDebugInTransaction = now;
@@ -1251,7 +1257,7 @@
             // layerStack first (so we don't have to traverse the list
             // of displays for every layer).
             const sp<Layer>& layer(currentLayers[i]);
-            uint32_t layerStack = layer->drawingState().layerStack;
+            uint32_t layerStack = layer->getDrawingState().layerStack;
             if (i==0 || currentlayerStack != layerStack) {
                 currentlayerStack = layerStack;
                 // figure out if this layerstack is mirrored
@@ -1288,8 +1294,8 @@
      * Perform our own transaction if needed
      */
 
-    const LayerVector& previousLayers(mDrawingState.layersSortedByZ);
-    if (currentLayers.size() > previousLayers.size()) {
+    const LayerVector& layers(mDrawingState.layersSortedByZ);
+    if (currentLayers.size() > layers.size()) {
         // layers have been added
         mVisibleRegionsDirty = true;
     }
@@ -1299,15 +1305,15 @@
     if (mLayersRemoved) {
         mLayersRemoved = false;
         mVisibleRegionsDirty = true;
-        const size_t count = previousLayers.size();
+        const size_t count = layers.size();
         for (size_t i=0 ; i<count ; i++) {
-            const sp<Layer>& layer(previousLayers[i]);
+            const sp<Layer>& layer(layers[i]);
             if (currentLayers.indexOf(layer) < 0) {
                 // this layer is not visible anymore
                 // TODO: we could traverse the tree from front to back and
                 //       compute the actual visible region
                 // TODO: we could cache the transformed region
-                const Layer::State& s(layer->drawingState());
+                const Layer::State& s(layer->getDrawingState());
                 Region visibleReg = s.transform.transform(
                         Region(Rect(s.active.w, s.active.h)));
                 invalidateLayerStack(s.layerStack, visibleReg);
@@ -1355,7 +1361,7 @@
         const sp<Layer>& layer = currentLayers[i];
 
         // start with the whole surface at its current location
-        const Layer::State& s(layer->drawingState());
+        const Layer::State& s(layer->getDrawingState());
 
         // only consider the layers on the given layer stack
         if (s.layerStack != layerStack)
@@ -1492,12 +1498,12 @@
     Region dirtyRegion;
 
     bool visibleRegions = false;
-    const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
-    const size_t count = currentLayers.size();
+    const LayerVector& layers(mDrawingState.layersSortedByZ);
+    const size_t count = layers.size();
     for (size_t i=0 ; i<count ; i++) {
-        const sp<Layer>& layer(currentLayers[i]);
+        const sp<Layer>& layer(layers[i]);
         const Region dirty(layer->latchBuffer(visibleRegions));
-        const Layer::State& s(layer->drawingState());
+        const Layer::State& s(layer->getDrawingState());
         invalidateLayerStack(s.layerStack, dirty);
     }
 
@@ -2699,7 +2705,7 @@
     const size_t count = layers.size();
     for (size_t i=0 ; i<count ; ++i) {
         const sp<Layer>& layer(layers[i]);
-        const Layer::State& state(layer->drawingState());
+        const Layer::State& state(layer->getDrawingState());
         if (state.layerStack == hw->getLayerStack()) {
             if (state.z >= minLayerZ && state.z <= maxLayerZ) {
                 if (layer->isVisible()) {
@@ -2866,13 +2872,13 @@
     const sp<Layer>& l(*reinterpret_cast<const sp<Layer>*>(lhs));
     const sp<Layer>& r(*reinterpret_cast<const sp<Layer>*>(rhs));
 
-    uint32_t ls = l->currentState().layerStack;
-    uint32_t rs = r->currentState().layerStack;
+    uint32_t ls = l->getCurrentState().layerStack;
+    uint32_t rs = r->getCurrentState().layerStack;
     if (ls != rs)
         return ls - rs;
 
-    uint32_t lz = l->currentState().z;
-    uint32_t rz = r->currentState().z;
+    uint32_t lz = l->getCurrentState().z;
+    uint32_t rz = r->getCurrentState().z;
     if (lz != rz)
         return lz - rz;