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() {