diff options
32 files changed, 483 insertions, 121 deletions
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp index 9def406ea0..8bda880256 100644 --- a/cmds/atrace/atrace.cpp +++ b/cmds/atrace/atrace.cpp @@ -36,6 +36,7 @@ #include <utils/String8.h> #include <utils/Timers.h> +#include <utils/Tokenizer.h> #include <utils/Trace.h> using namespace android; @@ -90,6 +91,7 @@ static const TracingCategory k_categories[] = { { "rs", "RenderScript", ATRACE_TAG_RS, { } }, { "bionic", "Bionic C Library", ATRACE_TAG_BIONIC, { } }, { "power", "Power Management", ATRACE_TAG_POWER, { } }, + { "pm", "Package Manager", ATRACE_TAG_PACKAGE_MANAGER, { } }, { "sched", "CPU Scheduling", 0, { { REQ, "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" }, { REQ, "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" }, @@ -140,6 +142,15 @@ static const TracingCategory k_categories[] = { { "regulators", "Voltage and Current Regulators", 0, { { REQ, "/sys/kernel/debug/tracing/events/regulator/enable" }, } }, + { "binder_driver", "Binder Kernel driver", 0, { + { REQ, "/sys/kernel/debug/tracing/events/binder/binder_transaction/enable" }, + { REQ, "/sys/kernel/debug/tracing/events/binder/binder_transaction_received/enable" }, + } }, + { "binder_lock", "Binder global lock trace", 0, { + { REQ, "/sys/kernel/debug/tracing/events/binder/binder_lock/enable" }, + { REQ, "/sys/kernel/debug/tracing/events/binder/binder_locked/enable" }, + { REQ, "/sys/kernel/debug/tracing/events/binder/binder_unlock/enable" }, + } }, }; /* Command line options */ @@ -149,6 +160,7 @@ static int g_traceBufferSizeKB = 2048; static bool g_compress = false; static bool g_nohup = false; static int g_initialSleepSecs = 0; +static const char* g_categoriesFile = NULL; static const char* g_kernelTraceFuncs = NULL; static const char* g_debugAppCmdLine = ""; @@ -566,6 +578,52 @@ static bool setKernelTraceFuncs(const char* funcs) return ok; } +static bool setCategoryEnable(const char* name, bool enable) +{ + for (int i = 0; i < NELEM(k_categories); i++) { + const TracingCategory& c = k_categories[i]; + if (strcmp(name, c.name) == 0) { + if (isCategorySupported(c)) { + g_categoryEnables[i] = enable; + return true; + } else { + if (isCategorySupportedForRoot(c)) { + fprintf(stderr, "error: category \"%s\" requires root " + "privileges.\n", name); + } else { + fprintf(stderr, "error: category \"%s\" is not supported " + "on this device.\n", name); + } + return false; + } + } + } + fprintf(stderr, "error: unknown tracing category \"%s\"\n", name); + return false; +} + +static bool setCategoriesEnableFromFile(const char* categories_file) +{ + if (!categories_file) { + return true; + } + Tokenizer* tokenizer = NULL; + if (Tokenizer::open(String8(categories_file), &tokenizer) != NO_ERROR) { + return false; + } + bool ok = true; + while (!tokenizer->isEol()) { + String8 token = tokenizer->nextToken(" "); + if (token.isEmpty()) { + tokenizer->skipDelimiters(" "); + continue; + } + ok &= setCategoryEnable(token.string(), true); + } + delete tokenizer; + return ok; +} + // Set all the kernel tracing settings to the desired state for this trace // capture. static bool setUpTrace() @@ -573,6 +631,7 @@ static bool setUpTrace() bool ok = true; // Set up the tracing options. + ok &= setCategoriesEnableFromFile(g_categoriesFile); ok &= setTraceOverwriteEnable(g_traceOverwrite); ok &= setTraceBufferSizeKB(g_traceBufferSizeKB); ok &= setGlobalClockEnable(true); @@ -766,30 +825,6 @@ static void registerSigHandler() sigaction(SIGTERM, &sa, NULL); } -static bool setCategoryEnable(const char* name, bool enable) -{ - for (int i = 0; i < NELEM(k_categories); i++) { - const TracingCategory& c = k_categories[i]; - if (strcmp(name, c.name) == 0) { - if (isCategorySupported(c)) { - g_categoryEnables[i] = enable; - return true; - } else { - if (isCategorySupportedForRoot(c)) { - fprintf(stderr, "error: category \"%s\" requires root " - "privileges.\n", name); - } else { - fprintf(stderr, "error: category \"%s\" is not supported " - "on this device.\n", name); - } - return false; - } - } - } - fprintf(stderr, "error: unknown tracing category \"%s\"\n", name); - return false; -} - static void listSupportedCategories() { for (int i = 0; i < NELEM(k_categories); i++) { @@ -809,6 +844,8 @@ static void showHelp(const char *cmd) "separated list of cmdlines\n" " -b N use a trace buffer size of N KB\n" " -c trace into a circular buffer\n" + " -f filename use the categories written in a file as space-separated\n" + " values in a line\n" " -k fname,... trace the listed kernel functions\n" " -n ignore signals\n" " -s N sleep for N seconds before tracing [default 0]\n" @@ -846,7 +883,7 @@ int main(int argc, char **argv) { 0, 0, 0, 0 } }; - ret = getopt_long(argc, argv, "a:b:ck:ns:t:z", + ret = getopt_long(argc, argv, "a:b:cf:k:ns:t:z", long_options, &option_index); if (ret < 0) { @@ -872,6 +909,10 @@ int main(int argc, char **argv) g_traceOverwrite = true; break; + case 'f': + g_categoriesFile = optarg; + break; + case 'k': g_kernelTraceFuncs = optarg; break; diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk index 9065ee1d2c..8c7c4a840e 100644 --- a/cmds/dumpstate/Android.mk +++ b/cmds/dumpstate/Android.mk @@ -17,5 +17,6 @@ LOCAL_MODULE := dumpstate LOCAL_SHARED_LIBRARIES := libcutils liblog libselinux LOCAL_HAL_STATIC_LIBRARIES := libdumpstate LOCAL_CFLAGS += -Wall -Wno-unused-parameter -std=gnu99 +LOCAL_INIT_RC := dumpstate.rc include $(BUILD_EXECUTABLE) diff --git a/cmds/dumpstate/dumpstate.rc b/cmds/dumpstate/dumpstate.rc new file mode 100644 index 0000000000..cd5d6c4d53 --- /dev/null +++ b/cmds/dumpstate/dumpstate.rc @@ -0,0 +1,5 @@ +service dumpstate /system/bin/dumpstate -s + class main + socket dumpstate stream 0660 shell log + disabled + oneshot diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c index d679787966..0dd0c21a9f 100644 --- a/cmds/dumpstate/utils.c +++ b/cmds/dumpstate/utils.c @@ -626,24 +626,6 @@ const char *dump_traces() { return NULL; // Can't rename old traces.txt -- no permission? -- leave it alone instead } - /* make the directory if necessary */ - char anr_traces_dir[PATH_MAX]; - strlcpy(anr_traces_dir, traces_path, sizeof(anr_traces_dir)); - char *slash = strrchr(anr_traces_dir, '/'); - if (slash != NULL) { - *slash = '\0'; - if (!mkdir(anr_traces_dir, 0775)) { - chown(anr_traces_dir, AID_SYSTEM, AID_SYSTEM); - chmod(anr_traces_dir, 0775); - if (selinux_android_restorecon(anr_traces_dir, 0) == -1) { - fprintf(stderr, "restorecon failed for %s: %s\n", anr_traces_dir, strerror(errno)); - } - } else if (errno != EEXIST) { - fprintf(stderr, "mkdir(%s): %s\n", anr_traces_dir, strerror(errno)); - return NULL; - } - } - /* create a new, empty traces.txt file to receive stack dumps */ int fd = TEMP_FAILURE_RETRY(open(traces_path, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC, 0666)); /* -rw-rw-rw- */ diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk index 6dec7f6895..eaeeb2226e 100644 --- a/cmds/installd/Android.mk +++ b/cmds/installd/Android.mk @@ -38,5 +38,6 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_STATIC_LIBRARIES := libdiskusage LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk +LOCAL_INIT_RC := installd.rc LOCAL_CLANG := true include $(BUILD_EXECUTABLE) diff --git a/cmds/installd/installd.rc b/cmds/installd/installd.rc new file mode 100644 index 0000000000..5e4c925d2b --- /dev/null +++ b/cmds/installd/installd.rc @@ -0,0 +1,3 @@ +service installd /system/bin/installd + class main + socket installd stream 600 system system diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp index 7db3fb90c9..e58391fb04 100644 --- a/cmds/installd/utils.cpp +++ b/cmds/installd/utils.cpp @@ -256,7 +256,7 @@ static int _delete_dir_contents(DIR *d, if ((name[1] == '.') && (name[2] == 0)) continue; } - subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); + subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC); if (subfd < 0) { ALOGE("Couldn't openat %s: %s\n", name, strerror(errno)); result = -1; @@ -316,7 +316,7 @@ int delete_dir_contents_fd(int dfd, const char *name) int fd, res; DIR *d; - fd = openat(dfd, name, O_RDONLY | O_DIRECTORY); + fd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC); if (fd < 0) { ALOGE("Couldn't openat %s: %s\n", name, strerror(errno)); return -1; @@ -656,7 +656,7 @@ static int _add_cache_files(cache_t *cache, cache_dir_t *parentDir, const char * if ((name[1] == '.') && (name[2] == 0)) continue; } - subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); + subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC); if (subfd < 0) { ALOGE("Couldn't openat %s: %s\n", name, strerror(errno)); continue; diff --git a/cmds/servicemanager/Android.mk b/cmds/servicemanager/Android.mk index 155cfc503e..7ee0dd184e 100644 --- a/cmds/servicemanager/Android.mk +++ b/cmds/servicemanager/Android.mk @@ -22,4 +22,5 @@ LOCAL_SHARED_LIBRARIES := liblog libselinux LOCAL_SRC_FILES := service_manager.c binder.c LOCAL_CFLAGS += $(svc_c_flags) LOCAL_MODULE := servicemanager +LOCAL_INIT_RC := servicemanager.rc include $(BUILD_EXECUTABLE) diff --git a/cmds/servicemanager/servicemanager.rc b/cmds/servicemanager/servicemanager.rc new file mode 100644 index 0000000000..e73516dbbd --- /dev/null +++ b/cmds/servicemanager/servicemanager.rc @@ -0,0 +1,10 @@ +service servicemanager /system/bin/servicemanager + class core + user system + group system + critical + onrestart restart healthd + onrestart restart zygote + onrestart restart media + onrestart restart surfaceflinger + onrestart restart drm diff --git a/include/batteryservice/BatteryService.h b/include/batteryservice/BatteryService.h index f0a2790a93..9a8e2f7017 100644 --- a/include/batteryservice/BatteryService.h +++ b/include/batteryservice/BatteryService.h @@ -64,6 +64,9 @@ struct BatteryProperties { int batteryLevel; int batteryVoltage; int batteryTemperature; + int batteryCurrent; + int batteryCycleCount; + int batteryFullCharge; String8 batteryTechnology; status_t writeToParcel(Parcel* parcel) const; diff --git a/include/binder/Binder.h b/include/binder/Binder.h index 86628a03d3..f849fd4327 100644 --- a/include/binder/Binder.h +++ b/include/binder/Binder.h @@ -17,7 +17,7 @@ #ifndef ANDROID_BINDER_H #define ANDROID_BINDER_H -#include <stdatomic.h> +#include <atomic> #include <stdint.h> #include <binder/IBinder.h> @@ -71,7 +71,7 @@ private: class Extras; - atomic_uintptr_t mExtras; // should be atomic<Extras *> + std::atomic<Extras*> mExtras; void* mReserved0; }; @@ -95,7 +95,7 @@ private: IBinder* const mRemote; RefBase::weakref_type* mRefs; - volatile int32_t mState; + std::atomic<int32_t> mState; }; }; // namespace android diff --git a/include/input/Input.h b/include/input/Input.h index 4a67f47f9e..093219ada7 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -134,7 +134,7 @@ struct AInputDevice { namespace android { -#ifdef HAVE_ANDROID_OS +#ifdef __ANDROID__ class Parcel; #endif @@ -229,7 +229,7 @@ struct PointerCoords { return getAxisValue(AMOTION_EVENT_AXIS_Y); } -#ifdef HAVE_ANDROID_OS +#ifdef __ANDROID__ status_t readFromParcel(Parcel* parcel); status_t writeToParcel(Parcel* parcel) const; #endif @@ -567,7 +567,7 @@ public: // Matrix is in row-major form and compatible with SkMatrix. void transform(const float matrix[9]); -#ifdef HAVE_ANDROID_OS +#ifdef __ANDROID__ status_t readFromParcel(Parcel* parcel); status_t writeToParcel(Parcel* parcel) const; #endif diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h index e70666ab28..111139be15 100644 --- a/include/input/KeyCharacterMap.h +++ b/include/input/KeyCharacterMap.h @@ -19,7 +19,7 @@ #include <stdint.h> -#if HAVE_ANDROID_OS +#ifdef __ANDROID__ #include <binder/IBinder.h> #endif @@ -124,7 +124,7 @@ public: * the mapping in some way. */ status_t mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const; -#if HAVE_ANDROID_OS +#ifdef __ANDROID__ /* Reads a key map from a parcel. */ static sp<KeyCharacterMap> readFromParcel(Parcel* parcel); diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp index 9d200fb219..e39093d52e 100644 --- a/libs/binder/Binder.cpp +++ b/libs/binder/Binder.cpp @@ -16,7 +16,7 @@ #include <binder/Binder.h> -#include <stdatomic.h> +#include <atomic> #include <utils/misc.h> #include <binder/BpBinder.h> #include <binder/IInterface.h> @@ -70,9 +70,8 @@ public: // --------------------------------------------------------------------------- -BBinder::BBinder() +BBinder::BBinder() : mExtras(nullptr) { - atomic_init(&mExtras, static_cast<uintptr_t>(0)); } bool BBinder::isBinderAlive() const @@ -139,19 +138,16 @@ void BBinder::attachObject( const void* objectID, void* object, void* cleanupCookie, object_cleanup_func func) { - Extras* e = reinterpret_cast<Extras*>( - atomic_load_explicit(&mExtras, memory_order_acquire)); + Extras* e = mExtras.load(std::memory_order_acquire); if (!e) { e = new Extras; - uintptr_t expected = 0; - if (!atomic_compare_exchange_strong_explicit( - &mExtras, &expected, - reinterpret_cast<uintptr_t>(e), - memory_order_release, - memory_order_acquire)) { + Extras* expected = nullptr; + if (!mExtras.compare_exchange_strong(expected, e, + std::memory_order_release, + std::memory_order_acquire)) { delete e; - e = reinterpret_cast<Extras*>(expected); // Filled in by CAS + e = expected; // Filled in by CAS } if (e == 0) return; // out of memory } @@ -160,18 +156,9 @@ void BBinder::attachObject( e->mObjects.attach(objectID, object, cleanupCookie, func); } -// The C11 standard doesn't allow atomic loads from const fields, -// though C++11 does. Fudge it until standards get straightened out. -static inline uintptr_t load_const_atomic(const atomic_uintptr_t* p, - memory_order mo) { - atomic_uintptr_t* non_const_p = const_cast<atomic_uintptr_t*>(p); - return atomic_load_explicit(non_const_p, mo); -} - void* BBinder::findObject(const void* objectID) const { - Extras* e = reinterpret_cast<Extras*>( - load_const_atomic(&mExtras, memory_order_acquire)); + Extras* e = mExtras.load(std::memory_order_acquire); if (!e) return NULL; AutoMutex _l(e->mLock); @@ -180,8 +167,7 @@ void* BBinder::findObject(const void* objectID) const void BBinder::detachObject(const void* objectID) { - Extras* e = reinterpret_cast<Extras*>( - atomic_load_explicit(&mExtras, memory_order_acquire)); + Extras* e = mExtras.load(std::memory_order_acquire); if (!e) return; AutoMutex _l(e->mLock); @@ -195,8 +181,7 @@ BBinder* BBinder::localBinder() BBinder::~BBinder() { - Extras* e = reinterpret_cast<Extras*>( - atomic_load_explicit(&mExtras, memory_order_relaxed)); + Extras* e = mExtras.load(std::memory_order_relaxed); if (e) delete e; } @@ -252,7 +237,7 @@ BpRefBase::BpRefBase(const sp<IBinder>& o) BpRefBase::~BpRefBase() { if (mRemote) { - if (!(mState&kRemoteAcquired)) { + if (!(mState.load(std::memory_order_relaxed)&kRemoteAcquired)) { mRemote->decStrong(this); } mRefs->decWeak(this); @@ -261,7 +246,7 @@ BpRefBase::~BpRefBase() void BpRefBase::onFirstRef() { - android_atomic_or(kRemoteAcquired, &mState); + mState.fetch_or(kRemoteAcquired, std::memory_order_relaxed); } void BpRefBase::onLastStrongRef(const void* /*id*/) diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index ef88181d6d..a237684783 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -852,7 +852,7 @@ status_t IPCThreadState::talkWithDriver(bool doReceive) IF_LOG_COMMANDS() { alog << "About to read/write, write size = " << mOut.dataSize() << endl; } -#if defined(HAVE_ANDROID_OS) +#if defined(__ANDROID__) if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0) err = NO_ERROR; else @@ -1158,7 +1158,7 @@ void IPCThreadState::threadDestructor(void *st) IPCThreadState* const self = static_cast<IPCThreadState*>(st); if (self) { self->flushCommands(); -#if defined(HAVE_ANDROID_OS) +#if defined(__ANDROID__) if (self->mProcess->mDriverFD > 0) { ioctl(self->mProcess->mDriverFD, BINDER_THREAD_EXIT, 0); } diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp index 016d3c54b0..821ab6cb9b 100644 --- a/libs/binder/ProcessState.cpp +++ b/libs/binder/ProcessState.cpp @@ -350,10 +350,6 @@ ProcessState::ProcessState() , mThreadPoolSeq(1) { if (mDriverFD >= 0) { - // XXX Ideally, there should be a specific define for whether we - // have mmap (or whether we could possibly have the kernel module - // availabla). -#if !defined(HAVE_WIN32_IPC) // mmap the binder, providing a chunk of virtual address space to receive transactions. mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); if (mVMStart == MAP_FAILED) { @@ -362,9 +358,6 @@ ProcessState::ProcessState() close(mDriverFD); mDriverFD = -1; } -#else - mDriverFD = -1; -#endif } LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating."); diff --git a/libs/binder/tests/Android.mk b/libs/binder/tests/Android.mk index 36687296fb..a40523d4b3 100644 --- a/libs/binder/tests/Android.mk +++ b/libs/binder/tests/Android.mk @@ -32,3 +32,11 @@ LOCAL_MODULE := binderLibTest LOCAL_SRC_FILES := binderLibTest.cpp LOCAL_SHARED_LIBRARIES := libbinder libutils include $(BUILD_NATIVE_TEST) + +include $(CLEAR_VARS) +LOCAL_MODULE := binderThroughputTest +LOCAL_SRC_FILES := binderThroughputTest.cpp +LOCAL_SHARED_LIBRARIES := libbinder libutils +LOCAL_CLANG := true +LOCAL_CFLAGS += -g -Wall -Werror -std=c++11 -Wno-missing-field-initializers -Wno-sign-compare -O3 +include $(BUILD_NATIVE_TEST) diff --git a/libs/binder/tests/binderThroughputTest.cpp b/libs/binder/tests/binderThroughputTest.cpp new file mode 100644 index 0000000000..71b96d4947 --- /dev/null +++ b/libs/binder/tests/binderThroughputTest.cpp @@ -0,0 +1,317 @@ +#include <binder/Binder.h> +#include <binder/IBinder.h> +#include <binder/IPCThreadState.h> +#include <binder/IServiceManager.h> +#include <string> +#include <cstring> +#include <cstdlib> +#include <cstdio> + +#include <iostream> +#include <vector> +#include <tuple> + +#include <unistd.h> +#include <sys/wait.h> + +using namespace std; +using namespace android; + +enum BinderWorkerServiceCode { + BINDER_NOP = IBinder::FIRST_CALL_TRANSACTION, +}; + +#define ASSERT_TRUE(cond) \ +do { \ + if (!(cond)) {\ + cerr << __func__ << ":" << __LINE__ << " condition:" << #cond << " failed\n" << endl; \ + exit(EXIT_FAILURE); \ + } \ +} while (0) + +class BinderWorkerService : public BBinder +{ +public: + BinderWorkerService() {} + ~BinderWorkerService() {} + virtual status_t onTransact(uint32_t code, + const Parcel& data, Parcel* reply, + uint32_t flags = 0) { + (void)flags; + (void)data; + (void)reply; + switch (code) { + case BINDER_NOP: + return NO_ERROR; + default: + return UNKNOWN_TRANSACTION; + }; + } +}; + +class Pipe { + int m_readFd; + int m_writeFd; + Pipe(int readFd, int writeFd) : m_readFd{readFd}, m_writeFd{writeFd} {} + Pipe(const Pipe &) = delete; + Pipe& operator=(const Pipe &) = delete; + Pipe& operator=(const Pipe &&) = delete; +public: + Pipe(Pipe&& rval) noexcept { + m_readFd = rval.m_readFd; + m_writeFd = rval.m_writeFd; + rval.m_readFd = 0; + rval.m_writeFd = 0; + } + ~Pipe() { + if (m_readFd) + close(m_readFd); + if (m_writeFd) + close(m_writeFd); + } + void signal() { + bool val = true; + int error = write(m_writeFd, &val, sizeof(val)); + ASSERT_TRUE(error >= 0); + }; + void wait() { + bool val = false; + int error = read(m_readFd, &val, sizeof(val)); + ASSERT_TRUE(error >= 0); + } + template <typename T> void send(const T& v) { + int error = write(m_writeFd, &v, sizeof(T)); + ASSERT_TRUE(error >= 0); + } + template <typename T> void recv(T& v) { + int error = read(m_readFd, &v, sizeof(T)); + ASSERT_TRUE(error >= 0); + } + static tuple<Pipe, Pipe> createPipePair() { + int a[2]; + int b[2]; + + int error1 = pipe(a); + int error2 = pipe(b); + ASSERT_TRUE(error1 >= 0); + ASSERT_TRUE(error2 >= 0); + + return make_tuple(Pipe(a[0], b[1]), Pipe(b[0], a[1])); + } +}; + +static const uint32_t num_buckets = 128; +static const uint64_t max_time_bucket = 50ull * 1000000; +static const uint64_t time_per_bucket = max_time_bucket / num_buckets; +static constexpr float time_per_bucket_ms = time_per_bucket / 1.0E6; + +struct ProcResults { + uint64_t m_best = max_time_bucket; + uint64_t m_worst = 0; + uint32_t m_buckets[num_buckets] = {0}; + uint64_t m_transactions = 0; + uint64_t m_total_time = 0; + + void add_time(uint64_t time) { + m_buckets[min(time, max_time_bucket-1) / time_per_bucket] += 1; + m_best = min(time, m_best); + m_worst = max(time, m_worst); + m_transactions += 1; + m_total_time += time; + } + static ProcResults combine(const ProcResults& a, const ProcResults& b) { + ProcResults ret; + for (int i = 0; i < num_buckets; i++) { + ret.m_buckets[i] = a.m_buckets[i] + b.m_buckets[i]; + } + ret.m_worst = max(a.m_worst, b.m_worst); + ret.m_best = min(a.m_best, b.m_best); + ret.m_transactions = a.m_transactions + b.m_transactions; + ret.m_total_time = a.m_total_time + b.m_total_time; + return ret; + } + void dump() { + double best = (double)m_best / 1.0E6; + double worst = (double)m_worst / 1.0E6; + double average = (double)m_total_time / m_transactions / 1.0E6; + cout << "average:" << average << "ms worst:" << worst << "ms best:" << best << "ms" << endl; + + uint64_t cur_total = 0; + for (int i = 0; i < num_buckets; i++) { + float cur_time = time_per_bucket_ms * i + 0.5f * time_per_bucket_ms; + if ((cur_total < 0.5f * m_transactions) && (cur_total + m_buckets[i] >= 0.5f * m_transactions)) { + cout << "50%: " << cur_time << " "; + } + if ((cur_total < 0.9f * m_transactions) && (cur_total + m_buckets[i] >= 0.9f * m_transactions)) { + cout << "90%: " << cur_time << " "; + } + if ((cur_total < 0.95f * m_transactions) && (cur_total + m_buckets[i] >= 0.95f * m_transactions)) { + cout << "95%: " << cur_time << " "; + } + if ((cur_total < 0.99f * m_transactions) && (cur_total + m_buckets[i] >= 0.99f * m_transactions)) { + cout << "99%: " << cur_time << " "; + } + cur_total += m_buckets[i]; + } + cout << endl; + + } +}; + +String16 generateServiceName(int num) +{ + char num_str[32]; + snprintf(num_str, sizeof(num_str), "%d", num); + String16 serviceName = String16("binderWorker") + String16(num_str); + return serviceName; +} + +void worker_fx( + int num, + int worker_count, + int iterations, + Pipe p) +{ + // Create BinderWorkerService and for go. + ProcessState::self()->startThreadPool(); + sp<IServiceManager> serviceMgr = defaultServiceManager(); + sp<BinderWorkerService> service = new BinderWorkerService; + serviceMgr->addService(generateServiceName(num), service); + + srand(num); + p.signal(); + p.wait(); + + // Get references to other binder services. + cout << "Created BinderWorker" << num << endl; + (void)worker_count; + vector<sp<IBinder> > workers; + for (int i = 0; i < worker_count; i++) { + if (num == i) + continue; + workers.push_back(serviceMgr->getService(generateServiceName(i))); + } + + // Run the benchmark. + ProcResults results; + chrono::time_point<chrono::high_resolution_clock> start, end; + for (int i = 0; i < iterations; i++) { + int target = rand() % workers.size(); + Parcel data, reply; + start = chrono::high_resolution_clock::now(); + status_t ret = workers[target]->transact(BINDER_NOP, data, &reply); + end = chrono::high_resolution_clock::now(); + + uint64_t cur_time = uint64_t(chrono::duration_cast<chrono::nanoseconds>(end - start).count()); + results.add_time(cur_time); + + if (ret != NO_ERROR) { + cout << "thread " << num << " failed " << ret << "i : " << i << endl; + exit(EXIT_FAILURE); + } + } + // Signal completion to master and wait. + p.signal(); + p.wait(); + + // Send results to master and wait for go to exit. + p.send(results); + p.wait(); + + exit(EXIT_SUCCESS); +} + +Pipe make_worker(int num, int iterations, int worker_count) +{ + auto pipe_pair = Pipe::createPipePair(); + pid_t pid = fork(); + if (pid) { + /* parent */ + return move(get<0>(pipe_pair)); + } else { + /* child */ + worker_fx(num, worker_count, iterations, move(get<1>(pipe_pair))); + /* never get here */ + return move(get<0>(pipe_pair)); + } + +} + +void wait_all(vector<Pipe>& v) +{ + for (int i = 0; i < v.size(); i++) { + v[i].wait(); + } +} + +void signal_all(vector<Pipe>& v) +{ + for (int i = 0; i < v.size(); i++) { + v[i].signal(); + } +} + +int main(int argc, char *argv[]) +{ + int workers = 2; + int iterations = 10000; + (void)argc; + (void)argv; + vector<Pipe> pipes; + + // Parse arguments. + for (int i = 1; i < argc; i++) { + if (string(argv[i]) == "-w") { + workers = atoi(argv[i+1]); + i++; + continue; + } + if (string(argv[i]) == "-i") { + iterations = atoi(argv[i+1]); + i++; + continue; + } + } + + // Create all the workers and wait for them to spawn. + for (int i = 0; i < workers; i++) { + pipes.push_back(make_worker(i, iterations, workers)); + } + wait_all(pipes); + + + // Run the workers and wait for completion. + chrono::time_point<chrono::high_resolution_clock> start, end; + cout << "waiting for workers to complete" << endl; + start = chrono::high_resolution_clock::now(); + signal_all(pipes); + wait_all(pipes); + end = chrono::high_resolution_clock::now(); + + // Calculate overall throughput. + double iterations_per_sec = double(iterations * workers) / (chrono::duration_cast<chrono::nanoseconds>(end - start).count() / 1.0E9); + cout << "iterations per sec: " << iterations_per_sec << endl; + + // Collect all results from the workers. + cout << "collecting results" << endl; + signal_all(pipes); + ProcResults tot_results; + for (int i = 0; i < workers; i++) { + ProcResults tmp_results; + pipes[i].recv(tmp_results); + tot_results = ProcResults::combine(tot_results, tmp_results); + } + tot_results.dump(); + + // Kill all the workers. + cout << "killing workers" << endl; + signal_all(pipes); + for (int i = 0; i < workers; i++) { + int status; + wait(&status); + if (status != 0) { + cout << "nonzero child status" << status << endl; + } + } + return 0; +} diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index 2c1418e074..88cd6536b6 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -23,7 +23,7 @@ #include <input/Input.h> #include <input/InputEventLabels.h> -#ifdef HAVE_ANDROID_OS +#ifdef __ANDROID__ #include <binder/Parcel.h> #endif @@ -144,7 +144,7 @@ void PointerCoords::applyOffset(float xOffset, float yOffset) { setAxisValue(AMOTION_EVENT_AXIS_Y, getY() + yOffset); } -#ifdef HAVE_ANDROID_OS +#ifdef __ANDROID__ status_t PointerCoords::readFromParcel(Parcel* parcel) { bits = parcel->readInt64(); @@ -420,7 +420,7 @@ void MotionEvent::transform(const float matrix[9]) { } } -#ifdef HAVE_ANDROID_OS +#ifdef __ANDROID__ status_t MotionEvent::readFromParcel(Parcel* parcel) { size_t pointerCount = parcel->readInt32(); size_t sampleCount = parcel->readInt32(); diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp index b03e01effb..732ebd032a 100644 --- a/libs/input/KeyCharacterMap.cpp +++ b/libs/input/KeyCharacterMap.cpp @@ -19,7 +19,7 @@ #include <stdlib.h> #include <string.h> -#if HAVE_ANDROID_OS +#ifdef __ANDROID__ #include <binder/Parcel.h> #endif @@ -557,7 +557,7 @@ void KeyCharacterMap::addLockedMetaKey(Vector<KeyEvent>& outEvents, } } -#if HAVE_ANDROID_OS +#ifdef __ANDROID__ sp<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) { sp<KeyCharacterMap> map = new KeyCharacterMap(); map->mType = parcel->readInt32(); diff --git a/opengl/libagl/context.h b/opengl/libagl/context.h index c599a55aaf..d23f43568e 100644 --- a/opengl/libagl/context.h +++ b/opengl/libagl/context.h @@ -21,7 +21,7 @@ #include <stddef.h> #include <sys/types.h> #include <pthread.h> -#ifdef HAVE_ANDROID_OS +#ifdef __ANDROID__ #include <bionic_tls.h> #endif @@ -579,7 +579,7 @@ private: // state // ---------------------------------------------------------------------------- -#ifdef HAVE_ANDROID_OS +#ifdef __ANDROID__ // We have a dedicated TLS slot in bionic inline void setGlThreadSpecific(ogles_context_t *value) { __get_tls()[TLS_SLOT_OPENGL] = value; diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index 593d0c2d05..7560d8fdf0 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -64,7 +64,7 @@ const unsigned int NUM_DISPLAYS = 1; static pthread_mutex_t gInitMutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t gErrorKeyMutex = PTHREAD_MUTEX_INITIALIZER; static pthread_key_t gEGLErrorKey = -1; -#ifndef HAVE_ANDROID_OS +#ifndef __ANDROID__ namespace gl { pthread_key_t gGLKey = -1; }; // namespace gl @@ -1373,7 +1373,7 @@ static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config, int32_t w = 0; int32_t h = 0; - while (attrib_list[0]) { + while (attrib_list[0] != EGL_NONE) { if (attrib_list[0] == EGL_WIDTH) w = attrib_list[1]; if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1]; attrib_list+=2; @@ -1403,7 +1403,7 @@ using namespace android; EGLDisplay eglGetDisplay(NativeDisplayType display) { -#ifndef HAVE_ANDROID_OS +#ifndef __ANDROID__ // this just needs to be done once if (gGLKey == -1) { pthread_mutex_lock(&gInitMutex); diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk index 18ad3003e1..8d426907fd 100644 --- a/opengl/libs/Android.mk +++ b/opengl/libs/Android.mk @@ -59,6 +59,11 @@ ifneq ($(MAX_EGL_CACHE_SIZE),) LOCAL_CFLAGS += -DMAX_EGL_CACHE_SIZE=$(MAX_EGL_CACHE_SIZE) endif +ifeq (address, $(strip $(SANITIZE_TARGET))) + LOCAL_CFLAGS_32 += -DEGL_WRAPPER_DIR=\"/$(TARGET_COPY_OUT_DATA)/lib\" + LOCAL_CFLAGS_64 += -DEGL_WRAPPER_DIR=\"/$(TARGET_COPY_OUT_DATA)/lib64\" +endif + LOCAL_REQUIRED_MODULES := $(egl.cfg_config_module) egl.cfg_config_module := diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp index 1fcc048b28..8df9af3e44 100644 --- a/opengl/libs/EGL/Loader.cpp +++ b/opengl/libs/EGL/Loader.cpp @@ -167,6 +167,14 @@ static void* load_wrapper(const char* path) { return so; } +#ifndef EGL_WRAPPER_DIR +#if defined(__LP64__) +#define EGL_WRAPPER_DIR "/system/lib64" +#else +#define EGL_WRAPPER_DIR "/system/lib" +#endif +#endif + void* Loader::open(egl_connection_t* cnx) { void* dso; @@ -187,15 +195,10 @@ void* Loader::open(egl_connection_t* cnx) LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation"); -#if defined(__LP64__) - cnx->libEgl = load_wrapper("/system/lib64/libEGL.so"); - cnx->libGles2 = load_wrapper("/system/lib64/libGLESv2.so"); - cnx->libGles1 = load_wrapper("/system/lib64/libGLESv1_CM.so"); -#else - cnx->libEgl = load_wrapper("/system/lib/libEGL.so"); - cnx->libGles2 = load_wrapper("/system/lib/libGLESv2.so"); - cnx->libGles1 = load_wrapper("/system/lib/libGLESv1_CM.so"); -#endif + cnx->libEgl = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so"); + cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so"); + cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so"); + LOG_ALWAYS_FATAL_IF(!cnx->libEgl, "couldn't load system EGL wrapper libraries"); diff --git a/opengl/tests/gl_perfapp/jni/gl_code.cpp b/opengl/tests/gl_perfapp/jni/gl_code.cpp index 2f0418373a..378c8e88db 100644 --- a/opengl/tests/gl_perfapp/jni/gl_code.cpp +++ b/opengl/tests/gl_perfapp/jni/gl_code.cpp @@ -26,8 +26,6 @@ uint32_t h; // The stateClock starts at zero and increments by 1 every time we draw a frame. It is used to control which phase of the test we are in. int stateClock; -const int doLoopStates = 2; -const int doSingleTestStates = 2; bool done; // Saves the parameters of the test (so we can print them out when we finish the timing.) diff --git a/services/sensorservice/BatteryService.cpp b/services/sensorservice/BatteryService.cpp index cb962a6349..81f32cdc58 100644 --- a/services/sensorservice/BatteryService.cpp +++ b/services/sensorservice/BatteryService.cpp @@ -83,7 +83,7 @@ void BatteryService::cleanupImpl(uid_t uid) { if (mBatteryStatService != 0) { Mutex::Autolock _l(mActivationsLock); int64_t identity = IPCThreadState::self()->clearCallingIdentity(); - for (ssize_t i=0 ; i<mActivations.size() ; i++) { + for (size_t i=0 ; i<mActivations.size() ; i++) { const Info& info(mActivations[i]); if (info.uid == uid) { mBatteryStatService->noteStopSensor(info.uid, info.handle); diff --git a/services/sensorservice/GravitySensor.cpp b/services/sensorservice/GravitySensor.cpp index 3cb3745202..61118bc54a 100644 --- a/services/sensorservice/GravitySensor.cpp +++ b/services/sensorservice/GravitySensor.cpp @@ -44,7 +44,6 @@ GravitySensor::GravitySensor(sensor_t const* list, size_t count) bool GravitySensor::process(sensors_event_t* outEvent, const sensors_event_t& event) { - const static double NS2S = 1.0 / 1000000000.0; if (event.type == SENSOR_TYPE_ACCELEROMETER) { vec3_t g; if (!mSensorFusion.hasEstimate()) diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp index dd1bccfbec..40d596f36b 100644 --- a/services/sensorservice/SensorDevice.cpp +++ b/services/sensorservice/SensorDevice.cpp @@ -388,7 +388,7 @@ void SensorDevice::disableAllSensors() { status_t SensorDevice::injectSensorData(const sensors_event_t *injected_sensor_event) { ALOGD_IF(DEBUG_CONNECTIONS, - "sensor_event handle=%d ts=%lld data=%.2f, %.2f, %.2f %.2f %.2f %.2f", + "sensor_event handle=%d ts=%" PRId64 " data=%.2f, %.2f, %.2f %.2f %.2f %.2f", injected_sensor_event->sensor, injected_sensor_event->timestamp, injected_sensor_event->data[0], injected_sensor_event->data[1], injected_sensor_event->data[2], diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index 40b21a96a0..1a486a34c8 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -118,7 +118,7 @@ void SensorService::onFirstRef() // it's safe to instantiate the SensorFusion object here // (it wants to be instantiated after h/w sensors have been // registered) - const SensorFusion& fusion(SensorFusion::getInstance()); + SensorFusion::getInstance(); // build the sensor list returned to users mUserSensorList = mSensorList; @@ -381,7 +381,7 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) mActiveSensors.valueAt(i)->getNumConnections()); } - result.appendFormat("Socket Buffer size = %d events\n", + result.appendFormat("Socket Buffer size = %zd events\n", mSocketBufferSize/sizeof(sensors_event_t)); result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" : "not held"); @@ -1104,7 +1104,7 @@ bool SensorService::canAccessSensor(const Sensor& sensor, const char* operation, AppOpsManager appOps; if (appOps.noteOp(opCode, IPCThreadState::self()->getCallingUid(), opPackageName) != AppOpsManager::MODE_ALLOWED) { - ALOGE("%s a sensor (%s) without enabled required app op: %D", + ALOGE("%s a sensor (%s) without enabled required app op: %d", operation, sensor.getName().string(), opCode); return false; } @@ -1307,13 +1307,13 @@ void SensorService::CircularBuffer::printBuffer(String8& result) const { } result.appendFormat("%d) ", eventNum++); if (mSensorType == SENSOR_TYPE_STEP_COUNTER) { - result.appendFormat("%llu,", mTrimmedSensorEventArr[i]->mStepCounter); + result.appendFormat("%" PRIu64 ",", mTrimmedSensorEventArr[i]->mStepCounter); } else { for (int j = 0; j < numData; ++j) { result.appendFormat("%5.1f,", mTrimmedSensorEventArr[i]->mData[j]); } } - result.appendFormat("%lld %02d:%02d:%02d ", mTrimmedSensorEventArr[i]->mTimestamp, + result.appendFormat("%" PRId64 " %02d:%02d:%02d ", mTrimmedSensorEventArr[i]->mTimestamp, mTrimmedSensorEventArr[i]->mHour, mTrimmedSensorEventArr[i]->mMin, mTrimmedSensorEventArr[i]->mSec); i = (i + 1) % mBufSize; diff --git a/services/sensorservice/vec.h b/services/sensorservice/vec.h index 24f30ff436..a142bad3a1 100644 --- a/services/sensorservice/vec.h +++ b/services/sensorservice/vec.h @@ -37,7 +37,7 @@ template <typename TYPE, size_t SIZE> class vec; template <typename TYPE, size_t SIZE> -class vbase; +struct vbase; namespace helpers { diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 1eb23616c3..17ca10e9b8 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -122,6 +122,8 @@ LOCAL_LDFLAGS := -Wl,--version-script,art/sigchainlib/version-script.txt -Wl,--e LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CPPFLAGS := -std=c++11 +LOCAL_INIT_RC := surfaceflinger.rc + LOCAL_SRC_FILES := \ main_surfaceflinger.cpp diff --git a/services/surfaceflinger/surfaceflinger.rc b/services/surfaceflinger/surfaceflinger.rc new file mode 100644 index 0000000000..718b6b65ff --- /dev/null +++ b/services/surfaceflinger/surfaceflinger.rc @@ -0,0 +1,5 @@ +service surfaceflinger /system/bin/surfaceflinger + class core + user system + group graphics drmrpc + onrestart restart zygote |