Merge "Add top level sanitize options for ADB."
diff --git a/adb/device.py b/adb/device.py
index 57f17fc..b6eaad6 100644
--- a/adb/device.py
+++ b/adb/device.py
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+import logging
 import os
 import re
 import subprocess
@@ -146,10 +147,12 @@
         return result, out
 
     def _simple_call(self, cmd):
+        logging.info(' '.join(self.adb_cmd + cmd))
         return subprocess.check_output(
             self.adb_cmd + cmd, stderr=subprocess.STDOUT)
 
     def shell(self, cmd):
+        logging.info(' '.join(self.adb_cmd + ['shell'] + cmd))
         cmd = self._make_shell_cmd(cmd)
         out = subprocess.check_output(cmd)
         rc, out = self._parse_shell_output(out)
@@ -161,6 +164,7 @@
 
     def shell_nocheck(self, cmd):
         cmd = self._make_shell_cmd(cmd)
+        logging.info(' '.join(cmd))
         p = subprocess.Popen(
             cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
         out, _ = p.communicate()
@@ -190,6 +194,9 @@
     def usb(self):
         return self._simple_call(['usb'])
 
+    def reboot(self):
+        return self._simple_call(['reboot'])
+
     def root(self):
         return self._simple_call(['root'])
 
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index 5cd4988..a8abade 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -234,7 +234,7 @@
 
 #else /* USE_SELECT */
 
-#ifdef HAVE_WINSOCK
+#if defined(_WIN32)
 #include <winsock2.h>
 #else
 #include <sys/select.h>
@@ -617,7 +617,7 @@
     fde->func = func;
     fde->arg = arg;
 
-#ifndef HAVE_WINSOCK
+#if !defined(_WIN32)
     fcntl(fd, F_SETFL, O_NONBLOCK);
 #endif
     fdevent_register(fde);
diff --git a/adb/services.cpp b/adb/services.cpp
index 82efb1c..708ef42 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -443,7 +443,7 @@
             return -1;
 #endif
         }
-#ifndef HAVE_WINSOCK   /* winsock doesn't implement unix domain sockets */
+#if !defined(_WIN32)   /* winsock doesn't implement unix domain sockets */
     } else if(!strncmp(name, "local:", 6)) {
         ret = socket_local_client(name + 6,
                 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
diff --git a/adb/test_device.py b/adb/test_device.py
index 8003eaa..81c4a94 100644
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -55,10 +55,15 @@
 class GetDeviceTest(unittest.TestCase):
     def setUp(self):
         self.android_serial = os.getenv('ANDROID_SERIAL')
-        del os.environ['ANDROID_SERIAL']
+        if 'ANDROID_SERIAL' in os.environ:
+            del os.environ['ANDROID_SERIAL']
 
     def tearDown(self):
-        os.environ['ANDROID_SERIAL'] = self.android_serial
+        if self.android_serial is not None:
+            os.environ['ANDROID_SERIAL'] = self.android_serial
+        else:
+            if 'ANDROID_SERIAL' in os.environ:
+                del os.environ['ANDROID_SERIAL']
 
     @mock.patch('adb.device.get_devices')
     def test_explicit(self, mock_get_devices):
@@ -311,7 +316,7 @@
         size = random.randrange(min_size, max_size, 1024)
 
         base_name = 'device_tmpfile' + str(file_num)
-        full_path = os.path.join(in_dir, base_name)
+        full_path = posixpath.join(in_dir, base_name)
 
         device.shell(['dd', 'if=/dev/urandom', 'of={}'.format(full_path),
                       'bs={}'.format(size), 'count=1'])
diff --git a/debuggerd/crasher.c b/debuggerd/crasher.c
index af86fe9..b5064b4 100644
--- a/debuggerd/crasher.c
+++ b/debuggerd/crasher.c
@@ -157,12 +157,6 @@
     } else if (!strcmp(arg, "SIGFPE")) {
         raise(SIGFPE);
         return EXIT_SUCCESS;
-    } else if (!strcmp(arg, "SIGPIPE")) {
-        int pipe_fds[2];
-        pipe(pipe_fds);
-        close(pipe_fds[0]);
-        write(pipe_fds[1], "oops", 4);
-        return EXIT_SUCCESS;
     } else if (!strcmp(arg, "SIGTRAP")) {
         raise(SIGTRAP);
         return EXIT_SUCCESS;
@@ -189,7 +183,6 @@
     fprintf(stderr, "  LOG_ALWAYS_FATAL      call LOG_ALWAYS_FATAL\n");
     fprintf(stderr, "  LOG_ALWAYS_FATAL_IF   call LOG_ALWAYS_FATAL\n");
     fprintf(stderr, "  SIGFPE                cause a SIGFPE\n");
-    fprintf(stderr, "  SIGPIPE               cause a SIGPIPE\n");
     fprintf(stderr, "  SIGSEGV               cause a SIGSEGV at address 0x0 (synonym: crash)\n");
     fprintf(stderr, "  SIGSEGV-non-null      cause a SIGSEGV at a non-zero address\n");
     fprintf(stderr, "  SIGSEGV-unmapped      mmap/munmap a region of memory and then attempt to access it\n");
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 787b7aa..599995c 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -408,7 +408,6 @@
             case SIGBUS:
             case SIGFPE:
             case SIGILL:
-            case SIGPIPE:
             case SIGSEGV:
 #ifdef SIGSTKFLT
             case SIGSTKFLT:
diff --git a/debuggerd/test/tombstone_test.cpp b/debuggerd/test/tombstone_test.cpp
index a771a39..d945d27 100644
--- a/debuggerd/test/tombstone_test.cpp
+++ b/debuggerd/test/tombstone_test.cpp
@@ -76,7 +76,7 @@
     resetLogs();
     elf_set_fake_build_id("");
     siginfo_t si;
-    si.si_signo = SIGPIPE;
+    si.si_signo = SIGABRT;
     ptrace_set_fake_getsiginfo(si);
   }
 
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index 114c7e4..e283923 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -81,7 +81,6 @@
     case SIGBUS: return "SIGBUS";
     case SIGFPE: return "SIGFPE";
     case SIGILL: return "SIGILL";
-    case SIGPIPE: return "SIGPIPE";
     case SIGSEGV: return "SIGSEGV";
 #if defined(SIGSTKFLT)
     case SIGSTKFLT: return "SIGSTKFLT";
diff --git a/include/cutils/sockets.h b/include/cutils/sockets.h
index 07d1351..2d3c743 100644
--- a/include/cutils/sockets.h
+++ b/include/cutils/sockets.h
@@ -23,7 +23,7 @@
 #include <string.h>
 #include <stdbool.h>
 
-#ifdef HAVE_WINSOCK
+#if defined(_WIN32)
 #include <winsock2.h>
 typedef int  socklen_t;
 #else
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 0c071ca..9046fbe 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -26,7 +26,7 @@
 #include <sys/types.h>
 #include <stdint.h>
 
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
 #include <linux/capability.h>
 #else
 #include "android_filesystem_capability.h"
diff --git a/include/utils/AndroidThreads.h b/include/utils/AndroidThreads.h
index aad1e82..4c2dd49 100644
--- a/include/utils/AndroidThreads.h
+++ b/include/utils/AndroidThreads.h
@@ -73,7 +73,7 @@
 // ------------------------------------------------------------------
 // Extra functions working with raw pids.
 
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
 // Change the priority AND scheduling group of a particular thread.  The priority
 // should be one of the ANDROID_PRIORITY constants.  Returns INVALID_OPERATION
 // if the priority set failed, else another value if just the group set failed;
diff --git a/include/utils/ByteOrder.h b/include/utils/ByteOrder.h
index baa3a83..44ea13d 100644
--- a/include/utils/ByteOrder.h
+++ b/include/utils/ByteOrder.h
@@ -21,7 +21,7 @@
 
 #include <stdint.h>
 #include <sys/types.h>
-#ifdef HAVE_WINSOCK
+#if defined(_WIN32)
 #include <winsock2.h>
 #else
 #include <netinet/in.h>
diff --git a/include/utils/FileMap.h b/include/utils/FileMap.h
index f70fc92..afd7bfd 100644
--- a/include/utils/FileMap.h
+++ b/include/utils/FileMap.h
@@ -26,7 +26,7 @@
 
 #if defined(__MINGW32__)
 // Ensure that we always pull in winsock2.h before windows.h
-#ifdef HAVE_WINSOCK
+#if defined(_WIN32)
 #include <winsock2.h>
 #endif
 #include <windows.h>
diff --git a/include/utils/Mutex.h b/include/utils/Mutex.h
index 757519b..f027c79 100644
--- a/include/utils/Mutex.h
+++ b/include/utils/Mutex.h
@@ -59,7 +59,7 @@
     // lock if possible; returns 0 on success, error otherwise
     status_t    tryLock();
 
-#if HAVE_ANDROID_OS
+#if defined(__ANDROID__)
     // lock the mutex, but don't wait longer than timeoutMilliseconds.
     // Returns 0 on success, TIMED_OUT for failure due to timeout expiration.
     //
@@ -128,7 +128,7 @@
 inline status_t Mutex::tryLock() {
     return -pthread_mutex_trylock(&mMutex);
 }
-#if HAVE_ANDROID_OS
+#if defined(__ANDROID__)
 inline status_t Mutex::timedLock(nsecs_t timeoutNs) {
     const struct timespec ts = {
         /* .tv_sec = */ static_cast<time_t>(timeoutNs / 1000000000),
diff --git a/include/utils/Thread.h b/include/utils/Thread.h
index 28839fd..1532b7e 100644
--- a/include/utils/Thread.h
+++ b/include/utils/Thread.h
@@ -70,7 +70,7 @@
     // Indicates whether this thread is running or not.
             bool        isRunning() const;
 
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
     // Return the thread's kernel ID, same as the thread itself calling gettid(),
     // or -1 if the thread is not running.
             pid_t       getTid() const;
@@ -101,7 +101,7 @@
     volatile bool           mExitPending;
     volatile bool           mRunning;
             sp<Thread>      mHoldSelf;
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
     // legacy for debugging, not used by getTid() as it is set by the child thread
     // and so is not initialized until the child reaches that point
             pid_t           mTid;
diff --git a/include/utils/Trace.h b/include/utils/Trace.h
index 6ee343d..6ba68f6 100644
--- a/include/utils/Trace.h
+++ b/include/utils/Trace.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_TRACE_H
 #define ANDROID_TRACE_H
 
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
 
 #include <fcntl.h>
 #include <stdint.h>
@@ -59,11 +59,11 @@
 
 }; // namespace android
 
-#else // HAVE_ANDROID_OS
+#else // !__ANDROID__
 
 #define ATRACE_NAME(...)
 #define ATRACE_CALL()
 
-#endif // HAVE_ANDROID_OS
+#endif // __ANDROID__
 
 #endif // ANDROID_TRACE_H
diff --git a/include/ziparchive/zip_archive.h b/include/ziparchive/zip_archive.h
index 5ef2ab0..3591a6b 100644
--- a/include/ziparchive/zip_archive.h
+++ b/include/ziparchive/zip_archive.h
@@ -22,6 +22,7 @@
 
 #include <stdint.h>
 #include <string.h>
+#include <sys/cdefs.h>
 #include <sys/types.h>
 #include <utils/Compat.h>
 
diff --git a/init/perfboot.py b/init/perfboot.py
new file mode 100755
index 0000000..2cd4699
--- /dev/null
+++ b/init/perfboot.py
@@ -0,0 +1,411 @@
+#!/usr/bin/env python
+# 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.
+"""Record the event logs during boot and output them to a file.
+
+This script repeats the record of each event log during Android boot specified
+times. By default, interval between measurements is adjusted in such a way that
+CPUs are cooled down sufficiently to avoid boot time slowdown caused by CPU
+thermal throttling. The result is output in a tab-separated value format.
+
+Examples:
+
+Repeat measurements 10 times. Interval between iterations is adjusted based on
+CPU temperature of the device.
+
+$ ./perfboot.py --iterations=10
+
+Repeat measurements 20 times. 60 seconds interval is taken between each
+iteration.
+
+$ ./perfboot.py --iterations=20 --interval=60
+
+Repeat measurements 20 times, show verbose output, output the result to
+data.tsv, and read event tags from eventtags.txt.
+
+$ ./perfboot.py --iterations=30 -v --output=data.tsv --tags=eventtags.txt
+"""
+
+import argparse
+import atexit
+import cStringIO
+import inspect
+import logging
+import math
+import os
+import re
+import subprocess
+import sys
+import threading
+import time
+
+sys.path.append(os.path.dirname(os.path.dirname(__file__)))
+import adb
+
+# The default event tags to record.
+_DEFAULT_EVENT_TAGS = [
+    'boot_progress_start',
+    'boot_progress_preload_start',
+    'boot_progress_preload_end',
+    'boot_progress_system_run',
+    'boot_progress_pms_start',
+    'boot_progress_pms_system_scan_start',
+    'boot_progress_pms_data_scan_start',
+    'boot_progress_pms_scan_end',
+    'boot_progress_pms_ready',
+    'boot_progress_ams_ready',
+    'boot_progress_enable_screen',
+]
+
+
+class IntervalAdjuster(object):
+    """A helper class to take suffficient interval between iterations."""
+
+    # CPU temperature values per product used to decide interval
+    _CPU_COOL_DOWN_THRESHOLDS = {
+        'flo': 40,
+        'flounder': 40000,
+        'razor': 40,
+        'volantis': 40000,
+    }
+    # The interval between CPU temperature checks
+    _CPU_COOL_DOWN_WAIT_INTERVAL = 10
+    # The wait time used when the value of _CPU_COOL_DOWN_THRESHOLDS for
+    # the product is not defined.
+    _CPU_COOL_DOWN_WAIT_TIME_DEFAULT = 120
+
+    def __init__(self, interval, device):
+        self._interval = interval
+        self._device = device
+        self._temp_paths = device.shell(
+            ['ls', '/sys/class/thermal/thermal_zone*/temp']).splitlines()
+        self._product = device.get_prop('ro.build.product')
+        self._waited = False
+
+    def wait(self):
+        """Waits certain amount of time for CPUs cool-down."""
+        if self._interval is None:
+            self._wait_cpu_cool_down(self._product, self._temp_paths)
+        else:
+            if self._waited:
+                print 'Waiting for %d seconds' % self._interval
+                time.sleep(self._interval)
+        self._waited = True
+
+    def _get_cpu_temp(self, threshold):
+        max_temp = 0
+        for temp_path in self._temp_paths:
+            temp = int(self._device.shell(['cat', temp_path]).rstrip())
+            max_temp = max(max_temp, temp)
+            if temp >= threshold:
+                return temp
+        return max_temp
+
+    def _wait_cpu_cool_down(self, product, temp_paths):
+        threshold = IntervalAdjuster._CPU_COOL_DOWN_THRESHOLDS.get(
+            self._product)
+        if threshold is None:
+            print 'No CPU temperature threshold is set for ' + self._product
+            print ('Just wait %d seconds' %
+                   IntervalAdjuster._CPU_COOL_DOWN_WAIT_TIME_DEFAULT)
+            time.sleep(IntervalAdjuster._CPU_COOL_DOWN_WAIT_TIME_DEFAULT)
+            return
+        while True:
+            temp = self._get_cpu_temp(threshold)
+            if temp < threshold:
+                logging.info('Current CPU temperature %s' % temp)
+                return
+            print 'Waiting until CPU temperature (%d) falls below %d' % (
+                temp, threshold)
+            time.sleep(IntervalAdjuster._CPU_COOL_DOWN_WAIT_INTERVAL)
+
+
+class WatchdogTimer(object):
+    """A timer that makes is_timedout() return true in |timeout| seconds."""
+    def __init__(self, timeout):
+        self._timedout = False
+
+        def notify_timeout():
+            self._timedout = True
+        self._timer = threading.Timer(timeout, notify_timeout)
+        self._timer.start()
+
+    def is_timedout(self):
+        return self._timedout
+
+    def cancel(self):
+        self._timer.cancel()
+
+
+def readlines_unbuffered(proc):
+    """Read lines from |proc|'s standard out without buffering."""
+    while True:
+        buf = []
+        c = proc.stdout.read(1)
+        if c == '' and proc.poll() is not None:
+            break
+        while c != '\n':
+            if c == '' and proc.poll() is not None:
+                break
+            buf.append(c)
+            c = proc.stdout.read(1)
+        yield ''.join(buf)
+
+
+def disable_dropbox(device):
+    """Removes the files created by Dropbox and avoids creating the files."""
+    device.root()
+    device.wait()
+    device.shell(['rm', '-rf', '/system/data/dropbox'])
+    original_dropbox_max_files = device.shell(
+        ['settings', 'get', 'global', 'dropbox_max_files']).rstrip()
+    device.shell(['settings', 'put', 'global', 'dropbox_max_files', '0'])
+    return original_dropbox_max_files
+
+
+def restore_dropbox(device, original_dropbox_max_files):
+    """Restores the dropbox_max_files setting."""
+    device.root()
+    device.wait()
+    if original_dropbox_max_files == 'null':
+        device.shell(['settings', 'delete', 'global', 'dropbox_max_files'])
+    else:
+        device.shell(['settings', 'put', 'global', 'dropbox_max_files',
+                      original_dropbox_max_files])
+
+
+def init_perf(device, output, record_list, tags):
+    device.wait()
+    build_type = device.get_prop('ro.build.type')
+    original_dropbox_max_files = None
+    if build_type != 'user':
+        # Workaround for Dropbox issue (http://b/20890386).
+        original_dropbox_max_files = disable_dropbox(device)
+
+    def cleanup():
+        try:
+            if record_list:
+                print_summary(record_list, tags[-1])
+                output_results(output, record_list, tags)
+            if original_dropbox_max_files is not None:
+                restore_dropbox(device, original_dropbox_max_files)
+        except subprocess.CalledProcessError, RuntimeError:
+            pass
+    atexit.register(cleanup)
+
+
+def read_event_tags(tags_file):
+    """Reads event tags from |tags_file|."""
+    if not tags_file:
+        return _DEFAULT_EVENT_TAGS
+    tags = []
+    with open(tags_file) as f:
+        for line in f:
+            if '#' in line:
+                line = line[:line.find('#')]
+            line = line.strip()
+            if line:
+                tags.append(line)
+    return tags
+
+
+def make_event_tags_re(tags):
+    """Makes a regular expression object that matches event logs of |tags|."""
+    return re.compile(r'(?P<pid>[0-9]+) +[0-9]+ I (?P<tag>%s): (?P<time>\d+)' %
+                      '|'.join(tags))
+
+
+def get_values(record, tag):
+    """Gets values that matches |tag| from |record|."""
+    keys = [key for key in record.keys() if key[0] == tag]
+    return [record[k] for k in sorted(keys)]
+
+
+def get_last_value(record, tag):
+    """Gets the last value that matches |tag| from |record|."""
+    values = get_values(record, tag)
+    if not values:
+        return 0
+    return values[-1]
+
+
+def output_results(filename, record_list, tags):
+    """Outputs |record_list| into |filename| in a TSV format."""
+    # First, count the number of the values of each tag.
+    # This is for dealing with events that occur multiple times.
+    # For instance, boot_progress_preload_start and boot_progress_preload_end
+    # are recorded twice on 64-bit system. One is for 64-bit zygote process
+    # and the other is for 32-bit zygote process.
+    values_counter = {}
+    for record in record_list:
+        for tag in tags:
+            # Some record might lack values for some tags due to unanticipated
+            # problems (e.g. timeout), so take the maximum count among all the
+            # record.
+            values_counter[tag] = max(values_counter.get(tag, 1),
+                                      len(get_values(record, tag)))
+
+    # Then creates labels for the data. If there are multiple values for one
+    # tag, labels for these values are numbered except the first one as
+    # follows:
+    #
+    # event_tag event_tag2 event_tag3
+    #
+    # The corresponding values are sorted in an ascending order of PID.
+    labels = []
+    for tag in tags:
+        for i in range(1, values_counter[tag] + 1):
+            labels.append('%s%s' % (tag, '' if i == 1 else str(i)))
+
+    # Finally write the data into the file.
+    with open(filename, 'w') as f:
+        f.write('\t'.join(labels) + '\n')
+        for record in record_list:
+            line = cStringIO.StringIO()
+            invalid_line = False
+            for i, tag in enumerate(tags):
+                if i != 0:
+                    line.write('\t')
+                values = get_values(record, tag)
+                if len(values) < values_counter[tag]:
+                    invalid_line = True
+                    # Fill invalid record with 0
+                    values += [0] * (values_counter[tag] - len(values))
+                line.write('\t'.join(str(t) for t in values))
+            if invalid_line:
+                logging.error('Invalid record found: ' + line.getvalue())
+            line.write('\n')
+            f.write(line.getvalue())
+    print 'Wrote: ' + filename
+
+
+def median(data):
+    """Calculates the median value from |data|."""
+    data = sorted(data)
+    n = len(data)
+    if n % 2 == 1:
+        return data[n / 2]
+    else:
+        n2 = n / 2
+        return (data[n2 - 1] + data[n2]) / 2.0
+
+
+def mean(data):
+    """Calculates the mean value from |data|."""
+    return float(sum(data)) / len(data)
+
+
+def stddev(data):
+    """Calculates the standard deviation value from |value|."""
+    m = mean(data)
+    return math.sqrt(sum((x - m) ** 2 for x in data) / len(data))
+
+
+def print_summary(record_list, end_tag):
+    """Prints the summary of |record_list|."""
+    # Filter out invalid data.
+    end_times = [get_last_value(record, end_tag) for record in record_list
+                 if get_last_value(record, end_tag) != 0]
+    print 'mean: ', mean(end_times)
+    print 'median:', median(end_times)
+    print 'standard deviation:', stddev(end_times)
+
+
+def do_iteration(device, interval_adjuster, event_tags_re, end_tag):
+    """Measures the boot time once."""
+    device.wait()
+    interval_adjuster.wait()
+    device.reboot()
+    print 'Rebooted the device'
+    record = {}
+    booted = False
+    while not booted:
+        device.wait()
+        # Stop the iteration if it does not finish within 120 seconds.
+        timeout = 120
+        t = WatchdogTimer(timeout)
+        p = subprocess.Popen(
+                ['adb', 'logcat', '-b', 'events', '-v', 'threadtime'],
+                stdout=subprocess.PIPE)
+        for line in readlines_unbuffered(p):
+            if t.is_timedout():
+                print '*** Timed out ***'
+                return record
+            m = event_tags_re.search(line)
+            if not m:
+                continue
+            tag = m.group('tag')
+            event_time = int(m.group('time'))
+            pid = m.group('pid')
+            record[(tag, pid)] = event_time
+            print 'Event log recorded: %s (%s) - %d ms' % (
+                tag, pid, event_time)
+            if tag == end_tag:
+                booted = True
+                t.cancel()
+                break
+    return record
+
+
+def parse_args():
+    """Parses the command line arguments."""
+    parser = argparse.ArgumentParser(
+        description=inspect.getdoc(sys.modules[__name__]),
+        formatter_class=argparse.RawDescriptionHelpFormatter)
+    parser.add_argument('--iterations', type=int, default=5,
+                        help='Number of times to repeat boot measurements.')
+    parser.add_argument('--interval', type=int,
+                        help=('Duration between iterations. If this is not '
+                              'set explicitly, durations are determined '
+                              'adaptively based on CPUs temperature.'))
+    parser.add_argument('-o', '--output', help='File name of output data.')
+    parser.add_argument('-v', '--verbose', action='store_true',
+                        help='Show verbose output.')
+    parser.add_argument('-s', '--serial', default=os.getenv('ANDROID_SERIAL'),
+                        help='Adb device serial number.')
+    parser.add_argument('-t', '--tags', help='Specify the filename from which '
+                        'event tags are read. Every line contains one event '
+                        'tag and the last event tag is used to detect that '
+                        'the device has finished booting.')
+    return parser.parse_args()
+
+
+def main():
+    args = parse_args()
+    if args.verbose:
+        logging.getLogger().setLevel(logging.INFO)
+
+    device = adb.get_device(args.serial)
+
+    if not args.output:
+        device.wait()
+        args.output = 'perf-%s-%s.tsv' % (
+            device.get_prop('ro.build.flavor'),
+            device.get_prop('ro.build.version.incremental'))
+
+    record_list = []
+    event_tags = read_event_tags(args.tags)
+    init_perf(device, args.output, record_list, event_tags)
+    interval_adjuster = IntervalAdjuster(args.interval, device)
+    event_tags_re = make_event_tags_re(event_tags)
+    end_tag = event_tags[-1]
+    for i in range(args.iterations):
+        print 'Run #%d ' % i
+        record = do_iteration(
+            device, interval_adjuster, event_tags_re, end_tag)
+        record_list.append(record)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/init/readme.txt b/init/readme.txt
index 5a758d7..d70c6f3 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -377,6 +377,29 @@
 bootanimation ends at: 33790 31230 (-2560)
 
 
+Systrace
+--------
+Systrace [1] can be used for obtaining performance analysis reports during boot
+time on userdebug or eng builds.
+Here is an example of trace events of "wm" and "am" categories:
+
+  $ANDROID_BUILD_TOP/external/chromium-trace/systrace.py wm am --boot
+
+This command will cause the device to reboot. After the device is rebooted and
+the boot sequence has finished, the trace report is obtained from the device
+and written as trace.html on the host by hitting Ctrl+C.
+
+LIMITATION
+Recording trace events is started after persistent properties are loaded, so
+the trace events that are emitted before that are not recorded. Several
+services such as vold, surfaceflinger, and servicemanager are affected by this
+limitation since they are started before persistent properties are loaded.
+Zygote initialization and the processes that are forked from the zygote are not
+affected.
+
+[1] http://developer.android.com/tools/help/systrace.html
+
+
 Debugging init
 --------------
 By default, programs executed by init will drop stdout and stderr into
diff --git a/libcutils/iosched_policy.c b/libcutils/iosched_policy.c
index 8946d3c..71bc94b 100644
--- a/libcutils/iosched_policy.c
+++ b/libcutils/iosched_policy.c
@@ -23,7 +23,7 @@
 
 #include <cutils/iosched_policy.h>
 
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
 #include <linux/ioprio.h>
 #include <sys/syscall.h>
 #define __android_unused
@@ -32,7 +32,7 @@
 #endif
 
 int android_set_ioprio(int pid __android_unused, IoSchedClass clazz __android_unused, int ioprio __android_unused) {
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
     if (syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, pid, ioprio | (clazz << IOPRIO_CLASS_SHIFT))) {
         return -1;
     }
@@ -41,7 +41,7 @@
 }
 
 int android_get_ioprio(int pid __android_unused, IoSchedClass *clazz, int *ioprio) {
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
     int rc;
 
     if ((rc = syscall(SYS_ioprio_get, IOPRIO_WHO_PROCESS, pid)) < 0) {
diff --git a/libcutils/process_name.c b/libcutils/process_name.c
index cc931eb..5d28b6f 100644
--- a/libcutils/process_name.c
+++ b/libcutils/process_name.c
@@ -25,19 +25,19 @@
 #include <unistd.h>
 
 #include <cutils/process_name.h>
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
 #include <cutils/properties.h>
 #endif
 
 #define PROCESS_NAME_DEVICE "/sys/qemu_trace/process_name"
 
 static const char* process_name = "unknown";
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
 static int running_in_emulator = -1;
 #endif
 
 void set_process_name(const char* new_name) {
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
     char  propBuf[PROPERTY_VALUE_MAX];
 #endif
 
@@ -59,7 +59,7 @@
     }
 #endif
 
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
     // If we know we are not running in the emulator, then return.
     if (running_in_emulator == 0) {
         return;
diff --git a/libcutils/record_stream.c b/libcutils/record_stream.c
index 6994904..2bc4226 100644
--- a/libcutils/record_stream.c
+++ b/libcutils/record_stream.c
@@ -22,7 +22,7 @@
 #include <cutils/record_stream.h>
 #include <string.h>
 #include <stdint.h>
-#ifdef HAVE_WINSOCK
+#if defined(_WIN32)
 #include <winsock2.h>   /* for ntohl */
 #else
 #include <netinet/in.h>
diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c
index dfc8777..103ff66 100644
--- a/libcutils/sched_policy.c
+++ b/libcutils/sched_policy.c
@@ -37,7 +37,7 @@
    return p == SP_DEFAULT ? SP_SYSTEM_DEFAULT : p;
 }
 
-#if defined(HAVE_ANDROID_OS)
+#if defined(__ANDROID__)
 
 #include <pthread.h>
 #include <sched.h>
@@ -142,7 +142,7 @@
  */
 static int getSchedulerGroup(int tid, char* buf, size_t bufLen)
 {
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
     char pathBuf[32];
     char lineBuf[256];
     FILE *fp;
diff --git a/libcutils/socket_inaddr_any_server.c b/libcutils/socket_inaddr_any_server.c
index 6c849de..7f0ccb8 100644
--- a/libcutils/socket_inaddr_any_server.c
+++ b/libcutils/socket_inaddr_any_server.c
@@ -20,7 +20,7 @@
 #include <string.h>
 #include <unistd.h>
 
-#ifndef HAVE_WINSOCK
+#if !defined(_WIN32)
 #include <sys/socket.h>
 #include <sys/select.h>
 #include <sys/types.h>
diff --git a/libcutils/socket_local_client.c b/libcutils/socket_local_client.c
index 7b42daa..2526146 100644
--- a/libcutils/socket_local_client.c
+++ b/libcutils/socket_local_client.c
@@ -22,7 +22,7 @@
 
 #include <cutils/sockets.h>
 
-#ifdef HAVE_WINSOCK
+#if defined(_WIN32)
 
 int socket_local_client(const char *name, int namespaceId, int type)
 {
@@ -30,7 +30,7 @@
     return -1;
 }
 
-#else /* !HAVE_WINSOCK */
+#else /* !_WIN32 */
 
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -165,4 +165,4 @@
     return s;
 }
 
-#endif /* !HAVE_WINSOCK */
+#endif /* !_WIN32 */
diff --git a/libcutils/socket_local_server.c b/libcutils/socket_local_server.c
index 60eb86b..c9acdad 100644
--- a/libcutils/socket_local_server.c
+++ b/libcutils/socket_local_server.c
@@ -23,7 +23,7 @@
 #include <errno.h>
 #include <stddef.h>
 
-#ifdef HAVE_WINSOCK
+#if defined(_WIN32)
 
 int socket_local_server(const char *name, int namespaceId, int type)
 {
@@ -31,7 +31,7 @@
     return -1;
 }
 
-#else /* !HAVE_WINSOCK */
+#else /* !_WIN32 */
 
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -123,4 +123,4 @@
     return s;
 }
 
-#endif /* !HAVE_WINSOCK */
+#endif /* !_WIN32 */
diff --git a/libcutils/socket_loopback_client.c b/libcutils/socket_loopback_client.c
index 9aed7b7..e14cffb 100644
--- a/libcutils/socket_loopback_client.c
+++ b/libcutils/socket_loopback_client.c
@@ -20,7 +20,7 @@
 #include <string.h>
 #include <unistd.h>
 
-#ifndef HAVE_WINSOCK
+#if !defined(_WIN32)
 #include <sys/socket.h>
 #include <sys/select.h>
 #include <sys/types.h>
diff --git a/libcutils/socket_loopback_server.c b/libcutils/socket_loopback_server.c
index 71afce7..b600e34 100644
--- a/libcutils/socket_loopback_server.c
+++ b/libcutils/socket_loopback_server.c
@@ -22,7 +22,7 @@
 
 #define LISTEN_BACKLOG 4
 
-#ifndef HAVE_WINSOCK
+#if !defined(_WIN32)
 #include <sys/socket.h>
 #include <sys/select.h>
 #include <sys/types.h>
diff --git a/libcutils/sockets.c b/libcutils/sockets.c
index 15ede2b..d438782 100644
--- a/libcutils/sockets.c
+++ b/libcutils/sockets.c
@@ -17,7 +17,7 @@
 #include <cutils/sockets.h>
 #include <log/log.h>
 
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
 /* For the socket trust (credentials) check */
 #include <private/android_filesystem_config.h>
 #define __android_unused
@@ -27,7 +27,7 @@
 
 bool socket_peer_is_trusted(int fd __android_unused)
 {
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
     struct ucred cr;
     socklen_t len = sizeof(cr);
     int n = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &len);
diff --git a/liblog/log_read.c b/liblog/log_read.c
index 9c4af30..cfc8a7a 100644
--- a/liblog/log_read.c
+++ b/liblog/log_read.c
@@ -37,7 +37,7 @@
 /* branchless on many architectures. */
 #define min(x,y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
 
-#if (defined(USE_MINGW) || defined(HAVE_WINSOCK))
+#if defined(_WIN32)
 #define WEAK static
 #else
 #define WEAK __attribute__((weak))
@@ -48,7 +48,7 @@
 
 /* Private copy of ../libcutils/socket_local_client.c prevent library loops */
 
-#ifdef HAVE_WINSOCK
+#if defined(_WIN32)
 
 int WEAK socket_local_client(const char *name, int namespaceId, int type)
 {
@@ -56,7 +56,7 @@
     return -ENOSYS;
 }
 
-#else /* !HAVE_WINSOCK */
+#else /* !_WIN32 */
 
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -193,7 +193,7 @@
     return s;
 }
 
-#endif /* !HAVE_WINSOCK */
+#endif /* !_WIN32 */
 /* End of ../libcutils/socket_local_client.c */
 
 #define logger_for_each(logger, logger_list) \
diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc
index a9671a9..32a65ea 100644
--- a/libnativebridge/native_bridge.cc
+++ b/libnativebridge/native_bridge.cc
@@ -295,13 +295,13 @@
   // so we save the extra file existence check.
   char cpuinfo_path[1024];
 
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
   snprintf(cpuinfo_path, sizeof(cpuinfo_path), "/system/lib"
 #ifdef __LP64__
       "64"
 #endif  // __LP64__
       "/%s/cpuinfo", instruction_set);
-#else   // !HAVE_ANDROID_OS
+#else   // !__ANDROID__
   // To be able to test on the host, we hardwire a relative path.
   snprintf(cpuinfo_path, sizeof(cpuinfo_path), "./cpuinfo");
 #endif
diff --git a/libnativebridge/tests/PreInitializeNativeBridge_test.cpp b/libnativebridge/tests/PreInitializeNativeBridge_test.cpp
index cec26ce..d3bbebe 100644
--- a/libnativebridge/tests/PreInitializeNativeBridge_test.cpp
+++ b/libnativebridge/tests/PreInitializeNativeBridge_test.cpp
@@ -32,8 +32,8 @@
 
 TEST_F(NativeBridgeTest, PreInitializeNativeBridge) {
     ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
-#ifndef __APPLE__         // Mac OS does not support bind-mount.
-#ifndef HAVE_ANDROID_OS   // Cannot write into the hard-wired location.
+#if !defined(__APPLE__)         // Mac OS does not support bind-mount.
+#if !defined(__ANDROID__)       // Cannot write into the hard-wired location.
     // Try to create our mount namespace.
     if (unshare(CLONE_NEWNS) != -1) {
         // Create a dummy file.
diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c
index 7d2a5fb..956ed30 100644
--- a/libnetutils/ifc_utils.c
+++ b/libnetutils/ifc_utils.c
@@ -50,7 +50,7 @@
 #define ALOGW printf
 #endif
 
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
 /* SIOCKILLADDR is an Android extension. */
 #define SIOCKILLADDR 0x8939
 #endif
@@ -596,7 +596,7 @@
 
 int ifc_reset_connections(const char *ifname, const int reset_mask)
 {
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
     int result, success;
     in_addr_t myaddr = 0;
     struct ifreq ifr;
diff --git a/libutils/SystemClock.cpp b/libutils/SystemClock.cpp
index 64204a8..1fca2b2 100644
--- a/libutils/SystemClock.cpp
+++ b/libutils/SystemClock.cpp
@@ -19,7 +19,7 @@
  * System clock functions.
  */
 
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
 #include <linux/ioctl.h>
 #include <linux/rtc.h>
 #include <utils/Atomic.h>
@@ -107,7 +107,7 @@
  */
 int64_t elapsedRealtimeNano()
 {
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
     struct timespec ts;
     int result;
     int64_t timestamp;
diff --git a/libutils/Threads.cpp b/libutils/Threads.cpp
index c3666e4..6dda6b5 100644
--- a/libutils/Threads.cpp
+++ b/libutils/Threads.cpp
@@ -45,7 +45,7 @@
 
 #include <cutils/sched_policy.h>
 
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
 # define __android_unused
 #else
 # define __android_unused __attribute__((__unused__))
@@ -132,7 +132,7 @@
     pthread_attr_init(&attr);
     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
-#ifdef HAVE_ANDROID_OS  /* valgrind is rejecting RT-priority create reqs */
+#if defined(__ANDROID__)  /* valgrind is rejecting RT-priority create reqs */
     if (threadPriority != PRIORITY_DEFAULT || threadName != NULL) {
         // Now that the pthread_t has a method to find the associated
         // android_thread_id_t (pid) from pthread_t, it would be possible to avoid
@@ -176,7 +176,7 @@
     return 1;
 }
 
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
 static pthread_t android_thread_id_t_to_pthread(android_thread_id_t thread)
 {
     return (pthread_t) thread;
@@ -302,12 +302,10 @@
     gCreateThreadFn = func;
 }
 
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
 int androidSetThreadPriority(pid_t tid, int pri)
 {
     int rc = 0;
-
-#if !defined(_WIN32)
     int lasterr = 0;
 
     if (pri >= ANDROID_PRIORITY_BACKGROUND) {
@@ -325,17 +323,12 @@
     } else {
         errno = lasterr;
     }
-#endif
 
     return rc;
 }
 
 int androidGetThreadPriority(pid_t tid) {
-#if !defined(_WIN32)
     return getpriority(PRIO_PROCESS, tid);
-#else
-    return ANDROID_PRIORITY_NORMAL;
-#endif
 }
 
 #endif
@@ -658,7 +651,7 @@
         mLock("Thread::mLock"),
         mStatus(NO_ERROR),
         mExitPending(false), mRunning(false)
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
         , mTid(-1)
 #endif
 {
@@ -728,7 +721,7 @@
     wp<Thread> weak(strong);
     self->mHoldSelf.clear();
 
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
     // this is very useful for debugging with gdb
     self->mTid = gettid();
 #endif
@@ -839,7 +832,7 @@
     return mRunning;
 }
 
-#ifdef HAVE_ANDROID_OS
+#if defined(__ANDROID__)
 pid_t Thread::getTid() const
 {
     // mTid is not defined until the child initializes it, and the caller may need it earlier
diff --git a/libutils/Timers.cpp b/libutils/Timers.cpp
index fb70e15..201bc41 100644
--- a/libutils/Timers.cpp
+++ b/libutils/Timers.cpp
@@ -23,7 +23,7 @@
 #include <sys/time.h>
 #include <time.h>
 
-#if defined(HAVE_ANDROID_OS)
+#if defined(__ANDROID__)
 nsecs_t systemTime(int clock)
 {
     static const clockid_t clocks[] = {
diff --git a/libutils/Unicode.cpp b/libutils/Unicode.cpp
index fb876c9..6f4b721 100644
--- a/libutils/Unicode.cpp
+++ b/libutils/Unicode.cpp
@@ -18,7 +18,7 @@
 
 #include <stddef.h>
 
-#ifdef HAVE_WINSOCK
+#if defined(_WIN32)
 # undef  nhtol
 # undef  htonl
 # undef  nhtos
diff --git a/rootdir/init.rc b/rootdir/init.rc
index f5febde..12999bd 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -259,6 +259,7 @@
     chmod 0660 /data/misc/wifi/wpa_supplicant.conf
     mkdir /data/local 0751 root root
     mkdir /data/misc/media 0700 media media
+    mkdir /data/misc/boottrace 0771 system shell
 
     # For security reasons, /data/local/tmp should always be empty.
     # Do not place files or directories in /data/local/tmp
diff --git a/rootdir/init.trace.rc b/rootdir/init.trace.rc
index 50944e6..ed4629e 100644
--- a/rootdir/init.trace.rc
+++ b/rootdir/init.trace.rc
@@ -33,3 +33,11 @@
 # Allow only the shell group to read and truncate the kernel trace.
     chown root shell /sys/kernel/debug/tracing/trace
     chmod 0660 /sys/kernel/debug/tracing/trace
+
+on property:persist.debug.atrace.boottrace=1
+    start boottrace
+
+# Run atrace with the categories written in a file
+service boottrace /system/bin/atrace --async_start -f /data/misc/boottrace/categories
+    disabled
+    oneshot