Merge "Replace libGLESv3 symlink with shared library"
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 3c9d899..5a66bc30 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <sys/sendfile.h>
 #include <time.h>
+#include <unistd.h>
 #include <zlib.h>
 
 #include <binder/IBinder.h>
@@ -96,6 +97,7 @@
     { "sched",      "CPU Scheduling",   0, {
         { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
         { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/sched/sched_blocked_reason/enable" },
     } },
     { "irq",        "IRQ Events",   0, {
         { REQ,      "/sys/kernel/debug/tracing/events/irq/enable" },
@@ -210,6 +212,9 @@
 static const char* k_tracePath =
     "/sys/kernel/debug/tracing/trace";
 
+static const char* k_traceStreamPath =
+    "/sys/kernel/debug/tracing/trace_pipe";
+
 static const char* k_traceMarkerPath =
     "/sys/kernel/debug/tracing/trace_marker";
 
@@ -728,6 +733,31 @@
     setTracingEnabled(false);
 }
 
+// Read data from the tracing pipe and forward to stdout
+static void streamTrace()
+{
+    char trace_data[4096];
+    int traceFD = open(k_traceStreamPath, O_RDWR);
+    if (traceFD == -1) {
+        fprintf(stderr, "error opening %s: %s (%d)\n", k_traceStreamPath,
+                strerror(errno), errno);
+        return;
+    }
+    while (!g_traceAborted) {
+        ssize_t bytes_read = read(traceFD, trace_data, 4096);
+        if (bytes_read > 0) {
+            write(STDOUT_FILENO, trace_data, bytes_read);
+            fflush(stdout);
+        } else {
+            if (!g_traceAborted) {
+                fprintf(stderr, "read returned %zd bytes err %d (%s)\n",
+                        bytes_read, errno, strerror(errno));
+            }
+            break;
+        }
+    }
+}
+
 // Read the current kernel trace and write it to stdout.
 static void dumpTrace()
 {
@@ -874,6 +904,10 @@
                     "  --async_dump    dump the current contents of circular trace buffer\n"
                     "  --async_stop    stop tracing and dump the current contents of circular\n"
                     "                    trace buffer\n"
+                    "  --stream        stream trace to stdout as it enters the trace buffer\n"
+                    "                    Note: this can take significant CPU time, and is best\n"
+                    "                    used for measuring things that are not affected by\n"
+                    "                    CPU performance, like pagecache usage.\n"
                     "  --list_categories\n"
                     "                  list the available tracing categories\n"
             );
@@ -885,6 +919,7 @@
     bool traceStart = true;
     bool traceStop = true;
     bool traceDump = true;
+    bool traceStream = false;
 
     if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
         showHelp(argv[0]);
@@ -899,6 +934,7 @@
             {"async_stop",      no_argument, 0,  0 },
             {"async_dump",      no_argument, 0,  0 },
             {"list_categories", no_argument, 0,  0 },
+            {"stream",          no_argument, 0,  0 },
             {           0,                0, 0,  0 }
         };
 
@@ -965,6 +1001,9 @@
                     async = true;
                     traceStart = false;
                     traceStop = false;
+                } else if (!strcmp(long_options[option_index].name, "stream")) {
+                    traceStream = true;
+                    traceDump = false;
                 } else if (!strcmp(long_options[option_index].name, "list_categories")) {
                     listSupportedCategories();
                     exit(0);
@@ -990,8 +1029,10 @@
     ok &= startTrace();
 
     if (ok && traceStart) {
-        printf("capturing trace...");
-        fflush(stdout);
+        if (!traceStream) {
+            printf("capturing trace...");
+            fflush(stdout);
+        }
 
         // We clear the trace after starting it because tracing gets enabled for
         // each CPU individually in the kernel. Having the beginning of the trace
@@ -1001,7 +1042,7 @@
         ok = clearTrace();
 
         writeClockSyncMarker();
-        if (ok && !async) {
+        if (ok && !async && !traceStream) {
             // Sleep to allow the trace to be captured.
             struct timespec timeLeft;
             timeLeft.tv_sec = g_traceDurationSeconds;
@@ -1012,6 +1053,10 @@
                 }
             } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR);
         }
+
+        if (traceStream) {
+            streamTrace();
+        }
     }
 
     // Stop the trace and restore the default settings.
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index cde9c37..3373192 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -12,6 +12,7 @@
     chown root shell /sys/kernel/debug/tracing/options/print-tgid
     chown root shell /sys/kernel/debug/tracing/events/sched/sched_switch/enable
     chown root shell /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
+    chown root shell /sys/kernel/debug/tracing/events/sched/sched_blocked_reason/enable
     chown root shell /sys/kernel/debug/tracing/events/power/cpu_frequency/enable
     chown root shell /sys/kernel/debug/tracing/events/power/cpu_idle/enable
     chown root shell /sys/kernel/debug/tracing/events/power/clock_set_rate/enable
@@ -34,6 +35,7 @@
     chmod 0664 /sys/kernel/debug/tracing/options/print-tgid
     chmod 0664 /sys/kernel/debug/tracing/events/sched/sched_switch/enable
     chmod 0664 /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/sched/sched_blocked_reason/enable
     chmod 0664 /sys/kernel/debug/tracing/events/power/cpu_frequency/enable
     chmod 0664 /sys/kernel/debug/tracing/events/power/cpu_idle/enable
     chmod 0664 /sys/kernel/debug/tracing/events/power/clock_set_rate/enable
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 757290f..1b99582 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -16,8 +16,8 @@
 
 #include "installd.h"
 
-#include <base/stringprintf.h>
-#include <base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/logging.h>
 #include <cutils/sched_policy.h>
 #include <diskusage/dirsize.h>
 #include <logwrap/logwrap.h>
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index 7a16150..30e4f8b 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -16,7 +16,7 @@
 
 #include "installd.h"
 
-#include <base/logging.h>
+#include <android-base/logging.h>
 
 #include <sys/capability.h>
 #include <sys/prctl.h>
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index abbd021..a98fec5 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -16,8 +16,8 @@
 
 #include "installd.h"
 
-#include <base/stringprintf.h>
-#include <base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/logging.h>
 
 #define CACHE_NOISY(x) //x
 
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 695d5f1..8dd9b65 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -20,6 +20,7 @@
 #include <vector>
 
 #include <cutils/native_handle.h>
+#include <nativehelper/ScopedFd.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 #include <utils/String16.h>
@@ -28,6 +29,7 @@
 #include <linux/binder.h>
 
 #include <binder/IInterface.h>
+#include <binder/Parcelable.h>
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -128,6 +130,10 @@
     status_t            writeStrongBinderVector(const std::vector<sp<IBinder>>& val);
 
     template<typename T>
+    status_t            writeParcelableVector(const std::vector<T>& val);
+    status_t            writeParcelable(const Parcelable& parcelable);
+
+    template<typename T>
     status_t            write(const Flattenable<T>& val);
 
     template<typename T>
@@ -149,6 +155,17 @@
     // will be closed once the parcel is destroyed.
     status_t            writeDupFileDescriptor(int fd);
 
+    // Place a file descriptor into the parcel.  This will not affect the
+    // semantics of the smart file descriptor. A new descriptor will be
+    // created, and will be closed when the parcel is destroyed.
+    status_t            writeUniqueFileDescriptor(
+                            const ScopedFd& fd);
+
+    // Place a vector of file desciptors into the parcel. Each descriptor is
+    // dup'd as in writeDupFileDescriptor
+    status_t            writeUniqueFileDescriptorVector(
+                            const std::vector<ScopedFd>& val);
+
     // Writes a blob to the parcel.
     // If the blob is small, then it is stored in-place, otherwise it is
     // transferred by way of an anonymous shared memory region.  Prefer sending
@@ -204,6 +221,10 @@
     wp<IBinder>         readWeakBinder() const;
 
     template<typename T>
+    status_t            readParcelableVector(std::vector<T>* val) const;
+    status_t            readParcelable(Parcelable* parcelable) const;
+
+    template<typename T>
     status_t            readStrongBinder(sp<T>* val) const;
 
     status_t            readStrongBinderVector(std::vector<sp<IBinder>>* val) const;
@@ -241,6 +262,15 @@
     // in the parcel, which you do not own -- use dup() to get your own copy.
     int                 readFileDescriptor() const;
 
+    // Retrieve a smart file descriptor from the parcel.
+    status_t            readUniqueFileDescriptor(
+                            ScopedFd* val) const;
+
+
+    // Retrieve a vector of smart file descriptors from the parcel.
+    status_t            readUniqueFileDescriptorVector(
+                            std::vector<ScopedFd>* val) const;
+
     // Reads a blob from the parcel.
     // The caller should call release() on the blob after reading its contents.
     status_t            readBlob(size_t len, ReadableBlob* outBlob) const;
@@ -296,6 +326,22 @@
     template<class T>
     status_t            writeAligned(T val);
 
+    template<typename T, typename U>
+    status_t            unsafeReadTypedVector(std::vector<T>* val,
+                                              status_t(Parcel::*read_func)(U*) const) const;
+    template<typename T>
+    status_t            readTypedVector(std::vector<T>* val,
+                                        status_t(Parcel::*read_func)(T*) const) const;
+    template<typename T, typename U>
+    status_t            unsafeWriteTypedVector(const std::vector<T>& val,
+                                               status_t(Parcel::*write_func)(U));
+    template<typename T>
+    status_t            writeTypedVector(const std::vector<T>& val,
+                                         status_t(Parcel::*write_func)(const T&));
+    template<typename T>
+    status_t            writeTypedVector(const std::vector<T>& val,
+                                         status_t(Parcel::*write_func)(T));
+
     status_t            mError;
     uint8_t*            mData;
     size_t              mDataSize;
@@ -456,6 +502,87 @@
     return ret;
 }
 
+template<typename T, typename U>
+status_t Parcel::unsafeReadTypedVector(
+        std::vector<T>* val, status_t(Parcel::*read_func)(U*) const) const {
+    val->clear();
+
+    int32_t size;
+    status_t status = this->readInt32(&size);
+
+    if (status != OK) {
+        return status;
+    }
+
+    if (size < 0) {
+        return UNEXPECTED_NULL;
+    }
+
+    val->resize(size);
+
+    for (auto& v: *val) {
+        status = (this->*read_func)(&v);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+template<typename T>
+status_t Parcel::readTypedVector(std::vector<T>* val,
+                                 status_t(Parcel::*read_func)(T*) const) const {
+    return unsafeReadTypedVector(val, read_func);
+}
+
+template<typename T, typename U>
+status_t Parcel::unsafeWriteTypedVector(const std::vector<T>& val,
+                                        status_t(Parcel::*write_func)(U)) {
+    if (val.size() > std::numeric_limits<int32_t>::max()) {
+        return BAD_VALUE;
+    }
+
+    status_t status = this->writeInt32(val.size());
+
+    if (status != OK) {
+        return status;
+    }
+
+    for (const auto& item : val) {
+        status = (this->*write_func)(item);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+template<typename T>
+status_t Parcel::writeTypedVector(const std::vector<T>& val,
+                          status_t(Parcel::*write_func)(const T&)) {
+    return unsafeWriteTypedVector(val, write_func);
+}
+
+template<typename T>
+status_t Parcel::writeTypedVector(const std::vector<T>& val,
+                          status_t(Parcel::*write_func)(T)) {
+    return unsafeWriteTypedVector(val, write_func);
+}
+
+template<typename T>
+status_t Parcel::readParcelableVector(std::vector<T>* val) const {
+    return unsafeReadTypedVector(val, &Parcel::readParcelable);
+}
+
+template<typename T>
+status_t Parcel::writeParcelableVector(const std::vector<T>& val) {
+    return unsafeWriteTypedVector(val, &Parcel::writeParcelable);
+}
+
 // ---------------------------------------------------------------------------
 
 inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
diff --git a/include/binder/Parcelable.h b/include/binder/Parcelable.h
new file mode 100644
index 0000000..faf0d34
--- /dev/null
+++ b/include/binder/Parcelable.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ANDROID_PARCELABLE_H
+#define ANDROID_PARCELABLE_H
+
+#include <vector>
+
+#include <utils/Errors.h>
+#include <utils/String16.h>
+
+namespace android {
+
+class Parcel;
+
+// Abstract interface of all parcelables.
+class Parcelable {
+public:
+    virtual ~Parcelable() = default;
+
+    // Write |this| parcelable to the given |parcel|.  Keep in mind that
+    // implementations of writeToParcel must be manually kept in sync
+    // with readFromParcel and the Java equivalent versions of these methods.
+    //
+    // Returns android::OK on success and an appropriate error otherwise.
+    virtual status_t writeToParcel(Parcel* parcel) const = 0;
+
+    // Read data from the given |parcel| into |this|.  After readFromParcel
+    // completes, |this| should have equivalent state to the object that
+    // wrote itself to the parcel.
+    //
+    // Returns android::OK on success and an appropriate error otherwise.
+    virtual status_t readFromParcel(const Parcel* parcel) = 0;
+};  // class Parcelable
+
+}  // namespace android
+
+#endif // ANDROID_PARCELABLE_H
diff --git a/include/binder/Status.h b/include/binder/Status.h
new file mode 100644
index 0000000..d19824d
--- /dev/null
+++ b/include/binder/Status.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ANDROID_BINDER_STATUS_H
+#define ANDROID_BINDER_STATUS_H
+
+#include <cstdint>
+
+#include <binder/Parcel.h>
+#include <utils/String8.h>
+
+namespace android {
+namespace binder {
+
+// An object similar in function to a status_t except that it understands
+// how exceptions are encoded in the prefix of a Parcel. Used like:
+//
+//     Parcel data;
+//     Parcel reply;
+//     status_t status;
+//     binder::Status remote_exception;
+//     if ((status = data.writeInterfaceToken(interface_descriptor)) != OK ||
+//         (status = data.writeInt32(function_input)) != OK) {
+//         // We failed to write into the memory of our local parcel?
+//     }
+//     if ((status = remote()->transact(transaction, data, &reply)) != OK) {
+//        // Something has gone wrong in the binder driver or libbinder.
+//     }
+//     if ((status = remote_exception.readFromParcel(reply)) != OK) {
+//         // The remote didn't correctly write the exception header to the
+//         // reply.
+//     }
+//     if (!remote_exception.isOk()) {
+//         // The transaction went through correctly, but the remote reported an
+//         // exception during handling.
+//     }
+//
+class Status final {
+public:
+    // Keep the exception codes in sync with android/os/Parcel.java.
+    enum Exception {
+        EX_NONE = 0,
+        EX_SECURITY = -1,
+        EX_BAD_PARCELABLE = -2,
+        EX_ILLEGAL_ARGUMENT = -3,
+        EX_NULL_POINTER = -4,
+        EX_ILLEGAL_STATE = -5,
+        EX_NETWORK_MAIN_THREAD = -6,
+        EX_UNSUPPORTED_OPERATION = -7,
+
+        // This is special and Java specific; see Parcel.java.
+        EX_HAS_REPLY_HEADER = -128,
+        // This is special, and indicates to C++ binder proxies that the
+        // transaction has failed at a low level.
+        EX_TRANSACTION_FAILED = -129,
+    };
+
+    // A more readable alias for the default constructor.
+    static Status ok();
+    // Allow authors to explicitly pick whether their integer is a status_t or
+    // exception code.
+    static Status fromExceptionCode(int32_t exceptionCode);
+    static Status fromExceptionCode(int32_t exceptionCode,
+                                    const String8& message);
+    static Status fromStatusT(status_t status);
+
+    Status() = default;
+    ~Status() = default;
+
+    // Status objects are copyable and contain just simple data.
+    Status(const Status& status) = default;
+    Status(Status&& status) = default;
+    Status& operator=(const Status& status) = default;
+
+    // Bear in mind that if the client or service is a Java endpoint, this
+    // is not the logic which will provide/interpret the data here.
+    status_t readFromParcel(const Parcel& parcel);
+    status_t writeToParcel(Parcel* parcel) const;
+
+    // Set one of the pre-defined exception types defined above.
+    void setException(int32_t ex, const String8& message);
+    // Setting a |status| != OK causes generated code to return |status|
+    // from Binder transactions, rather than writing an exception into the
+    // reply Parcel.
+    void setFromStatusT(status_t status);
+
+    // Get information about an exception.
+    int32_t exceptionCode() const  { return mException; }
+    const String8& exceptionMessage() const { return mMessage; }
+    status_t transactionError() const {
+        return mException == EX_TRANSACTION_FAILED ? mErrorCode : OK;
+    }
+
+    bool isOk() const { return mException == EX_NONE; }
+
+    // For logging.
+    String8 toString8() const;
+
+private:
+    Status(int32_t exception_code);
+    Status(int32_t exception_code, const String8& message);
+
+    // If |mException| == EX_TRANSACTION_FAILED, generated code will return
+    // |mErrorCode| as the result of the transaction rather than write an
+    // exception to the reply parcel.
+    //
+    // Otherwise, we always write |mException| to the parcel.
+    // If |mException| !=  EX_NONE, we write |mMessage| as well.
+    int32_t mException = EX_NONE;
+    int32_t mErrorCode = 0;
+    String8 mMessage;
+};  // class Status
+
+}  // namespace binder
+}  // namespace android
+
+#endif // ANDROID_BINDER_STATUS_H
diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk
index ce29ea6..bd11177 100644
--- a/libs/binder/Android.mk
+++ b/libs/binder/Android.mk
@@ -36,6 +36,7 @@
     PermissionCache.cpp \
     ProcessState.cpp \
     Static.cpp \
+    Status.cpp \
     TextOutput.cpp \
 
 LOCAL_PATH:= $(call my-dir)
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index c808948..9496821 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -23,6 +23,7 @@
 #include <binder/Binder.h>
 #include <binder/BpBinder.h>
 #include <binder/ProcessState.h>
+#include <binder/Status.h>
 #include <binder/TextOutput.h>
 
 #include <errno.h>
@@ -69,9 +70,6 @@
 // Note: must be kept in sync with android/os/StrictMode.java's PENALTY_GATHER
 #define STRICT_MODE_PENALTY_GATHER (0x40 << 16)
 
-// Note: must be kept in sync with android/os/Parcel.java's EX_HAS_REPLY_HEADER
-#define EX_HAS_REPLY_HEADER -128
-
 // XXX This can be made public if we want to provide
 // support for typed data.
 struct small_flat_data
@@ -310,39 +308,6 @@
     return BAD_TYPE;
 }
 
-namespace {
-
-template<typename T>
-status_t readTypedVector(std::vector<T>* val, const Parcel* p,
-                         status_t(Parcel::*read_func)(T*) const) {
-    val->clear();
-
-    int32_t size;
-    status_t status = p->readInt32(&size);
-
-    if (status != OK) {
-        return status;
-    }
-
-    if (size < 0) {
-        return UNEXPECTED_NULL;
-    }
-
-    val->resize(size);
-
-    for (auto& v: *val) {
-        status = (p->*read_func)(&v);
-
-        if (status != OK) {
-            return status;
-        }
-    }
-
-    return OK;
-}
-
-}  // namespace
-
 // ---------------------------------------------------------------------------
 
 Parcel::Parcel()
@@ -750,46 +715,6 @@
     return NULL;
 }
 
-namespace {
-
-template<typename T, typename U>
-status_t unsafeWriteTypedVector(const std::vector<T>& val, Parcel* p,
-                                status_t(Parcel::*write_func)(U)) {
-    if (val.size() > std::numeric_limits<int32_t>::max()) {
-        return BAD_VALUE;
-    }
-
-    status_t status = p->writeInt32(val.size());
-
-    if (status != OK) {
-        return status;
-    }
-
-    for (const auto& item : val) {
-        status = (p->*write_func)(item);
-
-        if (status != OK) {
-            return status;
-        }
-    }
-
-    return OK;
-}
-
-template<typename T>
-status_t writeTypedVector(const std::vector<T>& val, Parcel* p,
-                          status_t(Parcel::*write_func)(const T&)) {
-    return unsafeWriteTypedVector(val, p, write_func);
-}
-
-template<typename T>
-status_t writeTypedVector(const std::vector<T>& val, Parcel* p,
-                          status_t(Parcel::*write_func)(T)) {
-    return unsafeWriteTypedVector(val, p, write_func);
-}
-
-}  // namespace
-
 status_t Parcel::writeByteVector(const std::vector<int8_t>& val)
 {
     status_t status;
@@ -815,37 +740,37 @@
 
 status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val)
 {
-    return writeTypedVector(val, this, &Parcel::writeInt32);
+    return writeTypedVector(val, &Parcel::writeInt32);
 }
 
 status_t Parcel::writeInt64Vector(const std::vector<int64_t>& val)
 {
-    return writeTypedVector(val, this, &Parcel::writeInt64);
+    return writeTypedVector(val, &Parcel::writeInt64);
 }
 
 status_t Parcel::writeFloatVector(const std::vector<float>& val)
 {
-    return writeTypedVector(val, this, &Parcel::writeFloat);
+    return writeTypedVector(val, &Parcel::writeFloat);
 }
 
 status_t Parcel::writeDoubleVector(const std::vector<double>& val)
 {
-    return writeTypedVector(val, this, &Parcel::writeDouble);
+    return writeTypedVector(val, &Parcel::writeDouble);
 }
 
 status_t Parcel::writeBoolVector(const std::vector<bool>& val)
 {
-    return writeTypedVector(val, this, &Parcel::writeBool);
+    return writeTypedVector(val, &Parcel::writeBool);
 }
 
 status_t Parcel::writeCharVector(const std::vector<char16_t>& val)
 {
-    return writeTypedVector(val, this, &Parcel::writeChar);
+    return writeTypedVector(val, &Parcel::writeChar);
 }
 
 status_t Parcel::writeString16Vector(const std::vector<String16>& val)
 {
-    return writeTypedVector(val, this, &Parcel::writeString16);
+    return writeTypedVector(val, &Parcel::writeString16);
 }
 
 status_t Parcel::writeInt32(int32_t val)
@@ -994,11 +919,11 @@
 
 status_t Parcel::writeStrongBinderVector(const std::vector<sp<IBinder>>& val)
 {
-    return writeTypedVector(val, this, &Parcel::writeStrongBinder);
+    return writeTypedVector(val, &Parcel::writeStrongBinder);
 }
 
 status_t Parcel::readStrongBinderVector(std::vector<sp<IBinder>>* val) const {
-    return readTypedVector(val, this, &Parcel::readStrongBinder);
+    return readTypedVector(val, &Parcel::readStrongBinder);
 }
 
 status_t Parcel::writeWeakBinder(const wp<IBinder>& val)
@@ -1006,6 +931,14 @@
     return flatten_binder(ProcessState::self(), val, this);
 }
 
+status_t Parcel::writeParcelable(const Parcelable& parcelable) {
+    status_t status = writeInt32(1);  // parcelable is not null.
+    if (status != OK) {
+        return status;
+    }
+    return parcelable.writeToParcel(this);
+}
+
 status_t Parcel::writeNativeHandle(const native_handle* handle)
 {
     if (!handle || handle->version != sizeof(native_handle))
@@ -1047,12 +980,20 @@
         return -errno;
     }
     status_t err = writeFileDescriptor(dupFd, true /*takeOwnership*/);
-    if (err) {
+    if (err != OK) {
         close(dupFd);
     }
     return err;
 }
 
+status_t Parcel::writeUniqueFileDescriptor(const ScopedFd& fd) {
+    return writeDupFileDescriptor(fd.get());
+}
+
+status_t Parcel::writeUniqueFileDescriptorVector(const std::vector<ScopedFd>& val) {
+    return writeTypedVector(val, &Parcel::writeUniqueFileDescriptor);
+}
+
 status_t Parcel::writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob)
 {
     if (len > INT32_MAX) {
@@ -1206,7 +1147,8 @@
 
 status_t Parcel::writeNoException()
 {
-    return writeInt32(0);
+    binder::Status status;
+    return status.writeToParcel(this);
 }
 
 void Parcel::remove(size_t /*start*/, size_t /*amt*/)
@@ -1320,19 +1262,19 @@
 }
 
 status_t Parcel::readInt32Vector(std::vector<int32_t>* val) const {
-    return readTypedVector(val, this, &Parcel::readInt32);
+    return readTypedVector(val, &Parcel::readInt32);
 }
 
 status_t Parcel::readInt64Vector(std::vector<int64_t>* val) const {
-    return readTypedVector(val, this, &Parcel::readInt64);
+    return readTypedVector(val, &Parcel::readInt64);
 }
 
 status_t Parcel::readFloatVector(std::vector<float>* val) const {
-    return readTypedVector(val, this, &Parcel::readFloat);
+    return readTypedVector(val, &Parcel::readFloat);
 }
 
 status_t Parcel::readDoubleVector(std::vector<double>* val) const {
-    return readTypedVector(val, this, &Parcel::readDouble);
+    return readTypedVector(val, &Parcel::readDouble);
 }
 
 status_t Parcel::readBoolVector(std::vector<bool>* val) const {
@@ -1368,11 +1310,11 @@
 }
 
 status_t Parcel::readCharVector(std::vector<char16_t>* val) const {
-    return readTypedVector(val, this, &Parcel::readChar);
+    return readTypedVector(val, &Parcel::readChar);
 }
 
 status_t Parcel::readString16Vector(std::vector<String16>* val) const {
-    return readTypedVector(val, this, &Parcel::readString16);
+    return readTypedVector(val, &Parcel::readString16);
 }
 
 
@@ -1617,20 +1559,23 @@
     return val;
 }
 
+status_t Parcel::readParcelable(Parcelable* parcelable) const {
+    int32_t have_parcelable = 0;
+    status_t status = readInt32(&have_parcelable);
+    if (status != OK) {
+        return status;
+    }
+    if (!have_parcelable) {
+        return UNEXPECTED_NULL;
+    }
+    return parcelable->readFromParcel(this);
+}
+
 int32_t Parcel::readExceptionCode() const
 {
-  int32_t exception_code = readAligned<int32_t>();
-  if (exception_code == EX_HAS_REPLY_HEADER) {
-    int32_t header_start = dataPosition();
-    int32_t header_size = readAligned<int32_t>();
-    // Skip over fat responses headers.  Not used (or propagated) in
-    // native code
-    setDataPosition(header_start + header_size);
-    // And fat response headers are currently only used when there are no
-    // exceptions, so return no error:
-    return 0;
-  }
-  return exception_code;
+    binder::Status status;
+    status.readFromParcel(*this);
+    return status.exceptionCode();
 }
 
 native_handle* Parcel::readNativeHandle() const
@@ -1664,16 +1609,36 @@
 int Parcel::readFileDescriptor() const
 {
     const flat_binder_object* flat = readObject(true);
-    if (flat) {
-        switch (flat->type) {
-            case BINDER_TYPE_FD:
-                //ALOGI("Returning file descriptor %ld from parcel %p", flat->handle, this);
-                return flat->handle;
-        }
+
+    if (flat && flat->type == BINDER_TYPE_FD) {
+        return flat->handle;
     }
+
     return BAD_TYPE;
 }
 
+status_t Parcel::readUniqueFileDescriptor(ScopedFd* val) const
+{
+    int got = readFileDescriptor();
+
+    if (got == BAD_TYPE) {
+        return BAD_TYPE;
+    }
+
+    val->reset(dup(got));
+
+    if (val->get() < 0) {
+        return BAD_VALUE;
+    }
+
+    return OK;
+}
+
+
+status_t Parcel::readUniqueFileDescriptorVector(std::vector<ScopedFd>* val) const {
+    return readTypedVector(val, &Parcel::readUniqueFileDescriptor);
+}
+
 status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const
 {
     int32_t blobType;
diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp
new file mode 100644
index 0000000..67f0d59
--- /dev/null
+++ b/libs/binder/Status.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2015 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 <binder/Status.h>
+
+namespace android {
+namespace binder {
+
+Status Status::ok() {
+    return Status();
+}
+
+Status Status::fromExceptionCode(int32_t exceptionCode) {
+    return Status(exceptionCode);
+}
+
+Status Status::fromExceptionCode(int32_t exceptionCode,
+                                 const String8& message) {
+    return Status(exceptionCode, message);
+}
+
+Status Status::fromStatusT(status_t status) {
+    Status ret;
+    ret.setFromStatusT(status);
+    return ret;
+}
+
+Status::Status(int32_t exceptionCode) : mException(exceptionCode) {}
+Status::Status(int32_t exceptionCode, const String8& message)
+    : mException(exceptionCode),
+      mMessage(message) {}
+
+status_t Status::readFromParcel(const Parcel& parcel) {
+    status_t status = parcel.readInt32(&mException);
+    if (status != OK) {
+        setFromStatusT(status);
+        return status;
+    }
+
+    // Skip over fat response headers.  Not used (or propagated) in native code.
+    if (mException == EX_HAS_REPLY_HEADER) {
+        // Note that the header size includes the 4 byte size field.
+        const int32_t header_start = parcel.dataPosition();
+        int32_t header_size;
+        status = parcel.readInt32(&header_size);
+        if (status != OK) {
+            setFromStatusT(status);
+            return status;
+        }
+        parcel.setDataPosition(header_start + header_size);
+        // And fat response headers are currently only used when there are no
+        // exceptions, so act like there was no error.
+        mException = EX_NONE;
+    }
+
+    if (mException == EX_NONE) {
+        return status;
+    }
+
+    // The remote threw an exception.  Get the message back.
+    String16 message;
+    status = parcel.readString16(&message);
+    if (status != OK) {
+        setFromStatusT(status);
+        return status;
+    }
+    mMessage = String8(message);
+
+    return status;
+}
+
+status_t Status::writeToParcel(Parcel* parcel) const {
+    // Something really bad has happened, and we're not going to even
+    // try returning rich error data.
+    if (mException == EX_TRANSACTION_FAILED) {
+        return mErrorCode;
+    }
+
+    status_t status = parcel->writeInt32(mException);
+    if (status != OK) { return status; }
+    if (mException == EX_NONE) {
+        // We have no more information to write.
+        return status;
+    }
+    status = parcel->writeString16(String16(mMessage));
+    return status;
+}
+
+void Status::setFromStatusT(status_t status) {
+    mException = (status == NO_ERROR) ? EX_NONE : EX_TRANSACTION_FAILED;
+    mErrorCode = status;
+    mMessage.clear();
+}
+
+void Status::setException(int32_t ex, const String8& message) {
+    mException = ex;
+    mErrorCode = NO_ERROR;  // an exception, not a transaction failure.
+    mMessage.setTo(message);
+}
+
+String8 Status::toString8() const {
+    String8 ret;
+    if (mException == EX_NONE) {
+        ret.append("No error");
+    } else {
+        ret.appendFormat("Status(%d): '", mException);
+        if (mException == EX_TRANSACTION_FAILED) {
+            ret.appendFormat("%d: ", mErrorCode);
+        }
+        ret.append(String8(mMessage));
+        ret.append("'");
+    }
+    return ret;
+}
+
+}  // namespace binder
+}  // namespace android
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 13d44f3..bdf8f74 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -88,21 +88,22 @@
       mPowerMode(HWC_POWER_MODE_OFF),
       mActiveConfig(0)
 {
-    mNativeWindow = new Surface(producer, false);
+    Surface* surface;
+    mNativeWindow = surface = new Surface(producer, false);
     ANativeWindow* const window = mNativeWindow.get();
 
     /*
      * Create our display's surface
      */
 
-    EGLSurface surface;
+    EGLSurface eglSurface;
     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     if (config == EGL_NO_CONFIG) {
         config = RenderEngine::chooseEglConfig(display, format);
     }
-    surface = eglCreateWindowSurface(display, config, window, NULL);
-    eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth);
-    eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
+    eglSurface = eglCreateWindowSurface(display, config, window, NULL);
+    eglQuerySurface(display, eglSurface, EGL_WIDTH,  &mDisplayWidth);
+    eglQuerySurface(display, eglSurface, EGL_HEIGHT, &mDisplayHeight);
 
     // Make sure that composition can never be stalled by a virtual display
     // consumer that isn't processing buffers fast enough. We have to do this
@@ -116,7 +117,7 @@
 
     mConfig = config;
     mDisplay = display;
-    mSurface = surface;
+    mSurface = eglSurface;
     mFormat  = format;
     mPageFlipCount = 0;
     mViewport.makeInvalid();
@@ -142,6 +143,10 @@
 
     // initialize the display orientation transform.
     setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
+
+#ifdef NUM_FRAMEBUFFER_SURFACE_BUFFERS
+    surface->allocateBuffers();
+#endif
 }
 
 DisplayDevice::~DisplayDevice() {