am 16052ec5: Merge "ext4_utils: Fix long symbolic links"

* commit '16052ec56a0836db7de51d6ea4173c6b53f0a9b9':
  ext4_utils: Fix long symbolic links
diff --git a/atrace/Android.mk b/atrace/Android.mk
new file mode 100644
index 0000000..df79e82
--- /dev/null
+++ b/atrace/Android.mk
@@ -0,0 +1,16 @@
+# Copyright 2012 The Android Open Source Project
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= atrace.c
+
+LOCAL_C_INCLUDES += external/zlib
+
+LOCAL_MODULE:= atrace
+
+LOCAL_MODULE_TAGS:= debug
+
+LOCAL_STATIC_LIBRARIES := libz
+
+include $(BUILD_EXECUTABLE)
diff --git a/atrace/MODULE_LICENSE_APACHE2 b/atrace/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/atrace/MODULE_LICENSE_APACHE2
diff --git a/atrace/NOTICE b/atrace/NOTICE
new file mode 100644
index 0000000..c77f135
--- /dev/null
+++ b/atrace/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2012, 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.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/atrace/atrace.c b/atrace/atrace.c
new file mode 100644
index 0000000..7b4f55e
--- /dev/null
+++ b/atrace/atrace.c
@@ -0,0 +1,462 @@
+/*
+ * Copyright (C) 2012 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 <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/sendfile.h>
+#include <time.h>
+#include <zlib.h>
+
+/* Command line options */
+static int g_traceDurationSeconds = 5;
+static bool g_traceSchedSwitch = false;
+static bool g_traceCpuFrequency = false;
+static bool g_traceGovernorLoad = false;
+static bool g_traceWorkqueue = false;
+static bool g_traceOverwrite = false;
+static int g_traceBufferSizeKB = 2048;
+static bool g_compress = false;
+
+/* Global state */
+static bool g_traceAborted = false;
+
+/* Sys file paths */
+static const char* k_traceClockPath =
+    "/sys/kernel/debug/tracing/trace_clock";
+
+static const char* k_traceBufferSizePath =
+    "/sys/kernel/debug/tracing/buffer_size_kb";
+
+static const char* k_tracingOverwriteEnablePath =
+    "/sys/kernel/debug/tracing/options/overwrite";
+
+static const char* k_schedSwitchEnablePath =
+    "/sys/kernel/debug/tracing/events/sched/sched_switch/enable";
+
+static const char* k_cpuFreqEnablePath =
+    "/sys/kernel/debug/tracing/events/power/cpu_frequency/enable";
+
+static const char* k_governorLoadEnablePath =
+    "/sys/kernel/debug/tracing/events/cpufreq_interactive/enable";
+
+static const char* k_workqueueEnablePath =
+    "/sys/kernel/debug/tracing/events/workqueue/enable";
+
+static const char* k_tracingOnPath =
+    "/sys/kernel/debug/tracing/tracing_on";
+
+static const char* k_tracePath =
+    "/sys/kernel/debug/tracing/trace";
+
+static const char* k_traceMarkerPath =
+    "/sys/kernel/debug/tracing/trace_marker";
+
+// Write a string to a file, returning true if the write was successful.
+bool writeStr(const char* filename, const char* str)
+{
+    int fd = open(filename, O_WRONLY);
+    if (fd == -1) {
+        fprintf(stderr, "error opening %s: %s (%d)\n", filename,
+                strerror(errno), errno);
+        return false;
+    }
+
+    bool ok = true;
+    ssize_t len = strlen(str);
+    if (write(fd, str, len) != len) {
+        fprintf(stderr, "error writing to %s: %s (%d)\n", filename,
+                strerror(errno), errno);
+        ok = false;
+    }
+
+    close(fd);
+
+    return ok;
+}
+
+// Enable or disable a kernel option by writing a "1" or a "0" into a /sys file.
+static bool setKernelOptionEnable(const char* filename, bool enable)
+{
+    return writeStr(filename, enable ? "1" : "0");
+}
+
+// Enable or disable overwriting of the kernel trace buffers.  Disabling this
+// will cause tracing to stop once the trace buffers have filled up.
+static bool setTraceOverwriteEnable(bool enable)
+{
+    return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable);
+}
+
+// Enable or disable tracing of the kernel scheduler switching.
+static bool setSchedSwitchTracingEnable(bool enable)
+{
+    return setKernelOptionEnable(k_schedSwitchEnablePath, enable);
+}
+
+// Enable or disable tracing of the CPU clock frequency.
+static bool setCpuFrequencyTracingEnable(bool enable)
+{
+    return setKernelOptionEnable(k_cpuFreqEnablePath, enable);
+}
+
+// Enable or disable tracing of the interactive CPU frequency governor's idea of
+// the CPU load.
+static bool setGovernorLoadTracingEnable(bool enable)
+{
+    return setKernelOptionEnable(k_governorLoadEnablePath, enable);
+}
+
+// Enable or disable tracing of the kernel workqueues.
+static bool setWorkqueueTracingEnabled(bool enable)
+{
+    return setKernelOptionEnable(k_workqueueEnablePath, enable);
+}
+
+// Enable or disable kernel tracing.
+static bool setTracingEnabled(bool enable)
+{
+    return setKernelOptionEnable(k_tracingOnPath, enable);
+}
+
+// Clear the contents of the kernel trace.
+static bool clearTrace()
+{
+    int traceFD = creat(k_tracePath, 0);
+    if (traceFD == -1) {
+        fprintf(stderr, "error truncating %s: %s (%d)\n", k_tracePath,
+                strerror(errno), errno);
+        return false;
+    }
+
+    close(traceFD);
+
+    return true;
+}
+
+// Set the size of the kernel's trace buffer in kilobytes.
+static bool setTraceBufferSizeKB(int size)
+{
+    char str[32] = "1";
+    int len;
+    if (size < 1) {
+        size = 1;
+    }
+    snprintf(str, 32, "%d", size);
+    return writeStr(k_traceBufferSizePath, str);
+}
+
+// Enable or disable the kernel's use of the global clock.  Disabling the global
+// clock will result in the kernel using a per-CPU local clock.
+static bool setGlobalClockEnable(bool enable)
+{
+    return writeStr(k_traceClockPath, enable ? "global" : "local");
+}
+
+// Check whether a file exists.
+static bool fileExists(const char* filename) {
+    return access(filename, F_OK) != -1;
+}
+
+// Enable tracing in the kernel.
+static bool startTrace()
+{
+    bool ok = true;
+
+    // Set up the tracing options.
+    ok &= setTraceOverwriteEnable(g_traceOverwrite);
+    ok &= setSchedSwitchTracingEnable(g_traceSchedSwitch);
+    ok &= setCpuFrequencyTracingEnable(g_traceCpuFrequency);
+    if (fileExists(k_governorLoadEnablePath) || g_traceGovernorLoad) {
+        ok &= setGovernorLoadTracingEnable(g_traceGovernorLoad);
+    }
+    ok &= setWorkqueueTracingEnabled(g_traceWorkqueue);
+    ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
+    ok &= setGlobalClockEnable(true);
+
+    // Enable tracing.
+    ok &= setTracingEnabled(true);
+
+    if (!ok) {
+        fprintf(stderr, "error: unable to start trace\n");
+    }
+
+    return ok;
+}
+
+// Disable tracing in the kernel.
+static void stopTrace()
+{
+    // Disable tracing.
+    setTracingEnabled(false);
+
+    // Set the options back to their defaults.
+    setTraceOverwriteEnable(true);
+    setSchedSwitchTracingEnable(false);
+    setCpuFrequencyTracingEnable(false);
+    if (fileExists(k_governorLoadEnablePath)) {
+        setGovernorLoadTracingEnable(false);
+    }
+    setWorkqueueTracingEnabled(false);
+    setGlobalClockEnable(false);
+
+    // Note that we can't reset the trace buffer size here because that would
+    // clear the trace before we've read it.
+}
+
+// Read the current kernel trace and write it to stdout.
+static void dumpTrace()
+{
+    int traceFD = open(k_tracePath, O_RDWR);
+    if (traceFD == -1) {
+        fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath,
+                strerror(errno), errno);
+        return;
+    }
+
+    if (g_compress) {
+        z_stream zs;
+        uint8_t *in, *out;
+        int result, flush;
+
+        bzero(&zs, sizeof(zs));
+        result = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
+        if (result != Z_OK) {
+            fprintf(stderr, "error initializing zlib: %d\n", result);
+            close(traceFD);
+            return;
+        }
+
+        const size_t bufSize = 64*1024;
+        in = (uint8_t*)malloc(bufSize);
+        out = (uint8_t*)malloc(bufSize);
+        flush = Z_NO_FLUSH;
+
+        zs.next_out = out;
+        zs.avail_out = bufSize;
+
+        do {
+
+            if (zs.avail_in == 0) {
+                // More input is needed.
+                result = read(traceFD, in, bufSize);
+                if (result < 0) {
+                    fprintf(stderr, "error reading trace: %s (%d)\n",
+                            strerror(errno), errno);
+                    result = Z_STREAM_END;
+                    break;
+                } else if (result == 0) {
+                    flush = Z_FINISH;
+                } else {
+                    zs.next_in = in;
+                    zs.avail_in = result;
+                }
+            }
+
+            if (zs.avail_out == 0) {
+                // Need to write the output.
+                result = write(STDOUT_FILENO, out, bufSize);
+                if ((size_t)result < bufSize) {
+                    fprintf(stderr, "error writing deflated trace: %s (%d)\n",
+                            strerror(errno), errno);
+                    result = Z_STREAM_END; // skip deflate error message
+                    zs.avail_out = bufSize; // skip the final write
+                    break;
+                }
+                zs.next_out = out;
+                zs.avail_out = bufSize;
+            }
+
+        } while ((result = deflate(&zs, flush)) == Z_OK);
+
+        if (result != Z_STREAM_END) {
+            fprintf(stderr, "error deflating trace: %s\n", zs.msg);
+        }
+
+        if (zs.avail_out < bufSize) {
+            size_t bytes = bufSize - zs.avail_out;
+            result = write(STDOUT_FILENO, out, bytes);
+            if ((size_t)result < bytes) {
+                fprintf(stderr, "error writing deflated trace: %s (%d)\n",
+                        strerror(errno), errno);
+            }
+        }
+
+        result = deflateEnd(&zs);
+        if (result != Z_OK) {
+            fprintf(stderr, "error cleaning up zlib: %d\n", result);
+        }
+
+        free(in);
+        free(out);
+    } else {
+        ssize_t sent = 0;
+        while ((sent = sendfile(STDOUT_FILENO, traceFD, NULL, 64*1024*1024)) > 0);
+        if (sent == -1) {
+            fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno),
+                    errno);
+        }
+    }
+
+    close(traceFD);
+}
+
+// Print the command usage help to stderr.
+static void showHelp(const char *cmd)
+{
+    fprintf(stderr, "usage: %s [options]\n", cmd);
+    fprintf(stderr, "options include:\n"
+                    "  -b N            use a trace buffer size of N KB\n"
+                    "  -c              trace into a circular buffer\n"
+                    "  -f              trace CPU frequency changes\n"
+                    "  -l              trace CPU frequency governor load\n"
+                    "  -s              trace the kernel scheduler switches\n"
+                    "  -t N            trace for N seconds [defualt 5]\n"
+                    "  -w              trace the kernel workqueue\n"
+                    "  -z              compress the trace dump\n");
+}
+
+static void handleSignal(int signo) {
+    g_traceAborted = true;
+}
+
+static void registerSigHandler() {
+    struct sigaction sa;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = handleSignal;
+    sigaction(SIGHUP, &sa, NULL);
+    sigaction(SIGINT, &sa, NULL);
+    sigaction(SIGQUIT, &sa, NULL);
+    sigaction(SIGTERM, &sa, NULL);
+}
+
+int main(int argc, char **argv)
+{
+    if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
+        showHelp(argv[0]);
+        exit(0);
+    }
+
+    if (getuid() != 0) {
+        fprintf(stderr, "error: %s must be run as root.", argv[0]);
+        exit(1);
+    }
+
+    for (;;) {
+        int ret;
+
+        ret = getopt(argc, argv, "b:cflst:wz");
+
+        if (ret < 0) {
+            break;
+        }
+
+        switch(ret) {
+            case 'b':
+                g_traceBufferSizeKB = atoi(optarg);
+            break;
+
+            case 'c':
+                g_traceOverwrite = true;
+            break;
+
+            case 'l':
+                g_traceGovernorLoad = true;
+            break;
+
+            case 'f':
+                g_traceCpuFrequency = true;
+            break;
+
+            case 's':
+                g_traceSchedSwitch = true;
+            break;
+
+            case 't':
+                g_traceDurationSeconds = atoi(optarg);
+            break;
+
+            case 'w':
+                g_traceWorkqueue = true;
+            break;
+
+            case 'z':
+                g_compress = true;
+            break;
+
+            default:
+                fprintf(stderr, "\n");
+                showHelp(argv[0]);
+                exit(-1);
+            break;
+        }
+    }
+
+    registerSigHandler();
+
+    bool ok = startTrace();
+
+    if (ok) {
+        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
+        // contain entries from only one CPU can cause "begin" entries without a
+        // matching "end" entry to show up if a task gets migrated from one CPU to
+        // another.
+        ok = clearTrace();
+
+        if (ok) {
+            // Sleep to allow the trace to be captured.
+            struct timespec timeLeft;
+            timeLeft.tv_sec = g_traceDurationSeconds;
+            timeLeft.tv_nsec = 0;
+            do {
+                if (g_traceAborted) {
+                    break;
+                }
+            } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR);
+        }
+    }
+
+    // Stop the trace and restore the default settings.
+    stopTrace();
+
+    if (ok) {
+        if (!g_traceAborted) {
+            printf(" done\nTRACE:\n");
+            fflush(stdout);
+            dumpTrace();
+        } else {
+            printf("\ntrace aborted.\n");
+            fflush(stdout);
+        }
+        clearTrace();
+    } else {
+        fprintf(stderr, "unable to start tracing\n");
+    }
+
+    // Reset the trace buffer size to 1.
+    setTraceBufferSizeKB(1);
+
+    return g_traceAborted ? 1 : 0;
+}
diff --git a/bugmailer/Android.mk b/bugmailer/Android.mk
index 9ae4fd8..1bb3099 100644
--- a/bugmailer/Android.mk
+++ b/bugmailer/Android.mk
@@ -1,9 +1,12 @@
 # Copyright 2011 The Android Open Source Project
 #
 LOCAL_PATH:= $(call my-dir)
+
+ifneq ($(TARGET_BUILD_PDK), true)
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_MODULE := send_bug
 LOCAL_MODULE_TAGS := optional
 include $(BUILD_JAVA_LIBRARY)
+endif
diff --git a/bugmailer/src/com/android/commands/sendbug/SendBug.java b/bugmailer/src/com/android/commands/sendbug/SendBug.java
index 41a550a..da8788e 100644
--- a/bugmailer/src/com/android/commands/sendbug/SendBug.java
+++ b/bugmailer/src/com/android/commands/sendbug/SendBug.java
@@ -71,8 +71,8 @@
             }
             final IActivityManager mAm = ActivityManagerNative.getDefault();
             try {
-                mAm.startActivity(null, intent, intent.getType(), null, 0, null, null, 0, false,
-                        false, null, null, false);
+                mAm.startActivity(null, intent, intent.getType(), null, null, 0, 0,
+                        null, null, null);
             } catch (RemoteException e) {
                 // ignore
             }
@@ -87,7 +87,7 @@
         if (mPm != null) {
             final List<ResolveInfo> results;
             try {
-                results = mPm.queryIntentActivities(intent, null, 0);
+                results = mPm.queryIntentActivities(intent, null, 0, 0);
             } catch (RemoteException e) {
                 return null;
             }
diff --git a/cpustats/Android.mk b/cpustats/Android.mk
new file mode 100644
index 0000000..2789989
--- /dev/null
+++ b/cpustats/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := cpustats.c
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_MODULE_TAGS := debug
+LOCAL_MODULE := cpustats
+
+include $(BUILD_EXECUTABLE)
diff --git a/cpustats/cpustats.c b/cpustats/cpustats.c
new file mode 100644
index 0000000..d720f5e
--- /dev/null
+++ b/cpustats/cpustats.c
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2012, The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name of Google, Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define MAX_BUF_SIZE 64
+
+struct freq_info {
+    unsigned freq;
+    long unsigned time;
+};
+
+struct cpu_info {
+    long unsigned utime, ntime, stime, itime, iowtime, irqtime, sirqtime;
+    struct freq_info *freqs;
+    int freq_count;
+};
+
+#define die(...) { fprintf(stderr, __VA_ARGS__); exit(EXIT_FAILURE); }
+
+static struct cpu_info old_total_cpu, new_total_cpu, *old_cpus, *new_cpus;
+static int cpu_count, delay, iterations;
+static char minimal, aggregate_freq_stats;
+
+static int get_cpu_count();
+static int get_cpu_count_from_file(char *filename);
+static long unsigned get_cpu_total_time(struct cpu_info *cpu);
+static int get_freq_scales_count(int cpu);
+static void print_stats();
+static void print_cpu_stats(char *label, struct cpu_info *new_cpu, struct cpu_info *old_cpu,
+        char print_freq);
+static void print_freq_stats(struct cpu_info *new_cpu, struct cpu_info *old_cpu);
+static void read_stats();
+static void read_freq_stats(int cpu);
+static char should_aggregate_freq_stats();
+static char should_print_freq_stats();
+static void usage(char *cmd);
+
+int main(int argc, char *argv[]) {
+    struct cpu_info *tmp_cpus, tmp_total_cpu;
+    int i, freq_count;
+
+    delay = 3;
+    iterations = -1;
+    minimal = 0;
+    aggregate_freq_stats = 0;
+
+    for (i = 0; i < argc; i++) {
+        if (!strcmp(argv[i], "-n")) {
+            if (i + 1 >= argc) {
+                fprintf(stderr, "Option -n expects an argument.\n");
+                usage(argv[0]);
+                exit(EXIT_FAILURE);
+            }
+            iterations = atoi(argv[++i]);
+            continue;
+        }
+        if (!strcmp(argv[i], "-d")) {
+            if (i + 1 >= argc) {
+                fprintf(stderr, "Option -d expects an argument.\n");
+                usage(argv[0]);
+                exit(EXIT_FAILURE);
+            }
+            delay = atoi(argv[++i]);
+            continue;
+        }
+        if (!strcmp(argv[i], "-m")) {
+            minimal = 1;
+        }
+        if (!strcmp(argv[i], "-h")) {
+            usage(argv[0]);
+            exit(EXIT_SUCCESS);
+        }
+    }
+
+    cpu_count = get_cpu_count();
+
+    old_cpus = malloc(sizeof(struct cpu_info) * cpu_count);
+    if (!old_cpus) die("Could not allocate struct cpu_info\n");
+    new_cpus = malloc(sizeof(struct cpu_info) * cpu_count);
+    if (!new_cpus) die("Could not allocate struct cpu_info\n");
+
+    for (i = 0; i < cpu_count; i++) {
+        old_cpus[i].freq_count = new_cpus[i].freq_count = get_freq_scales_count(i);
+        new_cpus[i].freqs = malloc(sizeof(struct freq_info) * new_cpus[i].freq_count);
+        if (!new_cpus[i].freqs) die("Could not allocate struct freq_info\n");
+        old_cpus[i].freqs = malloc(sizeof(struct freq_info) * old_cpus[i].freq_count);
+        if (!old_cpus[i].freqs) die("Could not allocate struct freq_info\n");
+    }
+
+    // Read stats without aggregating freq stats in the total cpu
+    read_stats();
+
+    aggregate_freq_stats = should_aggregate_freq_stats();
+    if (aggregate_freq_stats) {
+        old_total_cpu.freq_count = new_total_cpu.freq_count = new_cpus[0].freq_count;
+        new_total_cpu.freqs = malloc(sizeof(struct freq_info) * new_total_cpu.freq_count);
+        if (!new_total_cpu.freqs) die("Could not allocate struct freq_info\n");
+        old_total_cpu.freqs = malloc(sizeof(struct freq_info) * old_total_cpu.freq_count);
+        if (!old_total_cpu.freqs) die("Could not allocate struct freq_info\n");
+
+        // Read stats again with aggregating freq stats in the total cpu
+        read_stats();
+    }
+
+    while ((iterations == -1) || (iterations-- > 0)) {
+        // Swap new and old cpu buffers;
+        tmp_total_cpu = old_total_cpu;
+        old_total_cpu = new_total_cpu;
+        new_total_cpu = tmp_total_cpu;
+
+        tmp_cpus = old_cpus;
+        old_cpus = new_cpus;
+        new_cpus = tmp_cpus;
+
+        sleep(delay);
+        read_stats();
+        print_stats();
+    }
+
+    // Clean up
+    if (aggregate_freq_stats) {
+        free(new_total_cpu.freqs);
+        free(old_total_cpu.freqs);
+    }
+    for (i = 0; i < cpu_count; i++) {
+        free(new_cpus[i].freqs);
+        free(old_cpus[i].freqs);
+    }
+    free(new_cpus);
+    free(old_cpus);
+
+    return 0;
+}
+
+/*
+ * Get the number of CPUs of the system.
+ *
+ * Uses the two files /sys/devices/system/cpu/present and
+ * /sys/devices/system/cpu/online to determine the number of CPUs. Expects the
+ * format of both files to be either 0 or 0-N where N+1 is the number of CPUs.
+ *
+ * Exits if the present CPUs is not equal to the online CPUs
+ */
+static int get_cpu_count() {
+    int cpu_count = get_cpu_count_from_file("/sys/devices/system/cpu/present");
+    if (cpu_count != get_cpu_count_from_file("/sys/devices/system/cpu/online")) {
+        die("present cpus != online cpus\n");
+    }
+    return cpu_count;
+}
+
+/*
+ * Get the number of CPUs from a given filename.
+ */
+static int get_cpu_count_from_file(char *filename) {
+    FILE *file;
+    char line[MAX_BUF_SIZE];
+    int cpu_count;
+
+    file = fopen(filename, "r");
+    if (!file) die("Could not open %s\n", filename);
+    if (!fgets(line, MAX_BUF_SIZE, file)) die("Could not get %s contents\n", filename);
+    fclose(file);
+
+    if (strcmp(line, "0\n") == 0) {
+        return 1;
+    }
+
+    if (1 == sscanf(line, "0-%d\n", &cpu_count)) {
+        return cpu_count + 1;
+    }
+
+    die("Unexpected input in file %s (%s).\n", filename, line);
+    return -1;
+}
+
+/*
+ * Get the number of frequency states a given CPU can be scaled to.
+ */
+static int get_freq_scales_count(int cpu) {
+    FILE *file;
+    char filename[MAX_BUF_SIZE];
+    long unsigned freq;
+    int count = 0;
+
+    sprintf(filename, "/sys/devices/system/cpu/cpu%d/cpufreq/stats/time_in_state", cpu);
+    file = fopen(filename, "r");
+    if (!file) die("Could not open %s\n", filename);
+    do {
+        freq = 0;
+        fscanf(file, "%lu %*d\n", &freq);
+        if (freq) count++;
+    } while(freq);
+    fclose(file);
+
+    return count;
+}
+
+/*
+ * Read the CPU and frequency stats for all cpus.
+ */
+static void read_stats() {
+    FILE *file;
+    char scanline[MAX_BUF_SIZE];
+    int i;
+
+    file = fopen("/proc/stat", "r");
+    if (!file) die("Could not open /proc/stat.\n");
+    fscanf(file, "cpu  %lu %lu %lu %lu %lu %lu %lu %*d %*d %*d\n",
+           &new_total_cpu.utime, &new_total_cpu.ntime, &new_total_cpu.stime, &new_total_cpu.itime,
+           &new_total_cpu.iowtime, &new_total_cpu.irqtime, &new_total_cpu.sirqtime);
+    if (aggregate_freq_stats) {
+        for (i = 0; i < new_total_cpu.freq_count; i++) {
+            new_total_cpu.freqs[i].time = 0;
+        }
+    }
+
+    for (i = 0; i < cpu_count; i++) {
+        sprintf(scanline, "cpu%d %%lu %%lu %%lu %%lu %%lu %%lu %%lu %%*d %%*d %%*d\n", i);
+        fscanf(file, scanline, &new_cpus[i].utime, &new_cpus[i].ntime, &new_cpus[i].stime,
+               &new_cpus[i].itime, &new_cpus[i].iowtime, &new_cpus[i].irqtime,
+               &new_cpus[i].sirqtime);
+        read_freq_stats(i);
+    }
+    fclose(file);
+}
+
+/*
+ * Read the frequency stats for a given cpu.
+ */
+static void read_freq_stats(int cpu) {
+    FILE *file;
+    char filename[MAX_BUF_SIZE];
+    int i;
+
+    sprintf(filename, "/sys/devices/system/cpu/cpu%d/cpufreq/stats/time_in_state", cpu);
+    file = fopen(filename, "r");
+    if (!file) die("Could not open %s\n", filename);
+    for (i = 0; i < new_cpus[cpu].freq_count; i++) {
+        fscanf(file, "%u %lu\n", &new_cpus[cpu].freqs[i].freq,
+               &new_cpus[cpu].freqs[i].time);
+        if (aggregate_freq_stats) {
+            new_total_cpu.freqs[i].freq = new_cpus[cpu].freqs[i].freq;
+            new_total_cpu.freqs[i].time += new_cpus[cpu].freqs[i].time;
+        }
+    }
+    fclose(file);
+}
+
+/*
+ * Get the sum of the cpu time from all categories.
+ */
+static long unsigned get_cpu_total_time(struct cpu_info *cpu) {
+    return (cpu->utime + cpu->ntime + cpu->stime + cpu->itime + cpu->iowtime + cpu->irqtime +
+            cpu->sirqtime);
+}
+
+/*
+ * Print the stats for all CPUs.
+ */
+static void print_stats() {
+    char label[8];
+    int i, j;
+    char print_freq;
+
+    print_freq = should_print_freq_stats();
+
+    print_cpu_stats("Total", &new_total_cpu, &old_total_cpu, 1);
+    for (i = 0; i < cpu_count; i++) {
+        sprintf(label, "cpu%d", i);
+        print_cpu_stats(label, &new_cpus[i], &old_cpus[i], print_freq);
+    }
+    printf("\n");
+}
+
+/*
+ * Print the stats for a single CPU.
+ */
+static void print_cpu_stats(char *label, struct cpu_info *new_cpu, struct cpu_info *old_cpu,
+        char print_freq) {
+    long int total_delta_time;
+
+    if (!minimal) {
+        total_delta_time = get_cpu_total_time(new_cpu) - get_cpu_total_time(old_cpu);
+        printf("%s: User %ld + Nice %ld + Sys %ld + Idle %ld + IOW %ld + IRQ %ld + SIRQ %ld = "
+                "%ld\n", label,
+                new_cpu->utime - old_cpu->utime,
+                new_cpu->ntime - old_cpu->ntime,
+                new_cpu->stime - old_cpu->stime,
+                new_cpu->itime - old_cpu->itime,
+                new_cpu->iowtime - old_cpu->iowtime,
+                new_cpu->irqtime - old_cpu->irqtime,
+                new_cpu->sirqtime - old_cpu->sirqtime,
+                total_delta_time);
+        if (print_freq) {
+            print_freq_stats(new_cpu, old_cpu);
+        }
+    } else {
+        printf("%s,%ld,%ld,%ld,%ld,%ld,%ld,%ld", label,
+                new_cpu->utime - old_cpu->utime,
+                new_cpu->ntime - old_cpu->ntime,
+                new_cpu->stime - old_cpu->stime,
+                new_cpu->itime - old_cpu->itime,
+                new_cpu->iowtime - old_cpu->iowtime,
+                new_cpu->irqtime - old_cpu->irqtime,
+                new_cpu->sirqtime - old_cpu->sirqtime);
+        print_freq_stats(new_cpu, old_cpu);
+        printf("\n");
+    }
+}
+
+/*
+ * Print the CPU stats for a single CPU.
+ */
+static void print_freq_stats(struct cpu_info *new_cpu, struct cpu_info *old_cpu) {
+    long int delta_time, total_delta_time;
+    int i;
+
+    if (new_cpu->freq_count > 0) {
+        if (!minimal) {
+            total_delta_time = 0;
+            printf("  ");
+            for (i = 0; i < new_cpu->freq_count; i++) {
+                delta_time = new_cpu->freqs[i].time - old_cpu->freqs[i].time;
+                total_delta_time += delta_time;
+                printf("%ukHz %ld", new_cpu->freqs[i].freq, delta_time);
+                if (i + 1 != new_cpu->freq_count) {
+                    printf(" + \n  ");
+                } else {
+                    printf(" = ");
+                }
+            }
+            printf("%ld\n", total_delta_time);
+        } else {
+            for (i = 0; i < new_cpu->freq_count; i++) {
+                printf(",%u,%ld", new_cpu->freqs[i].freq,
+                        new_cpu->freqs[i].time - old_cpu->freqs[i].time);
+            }
+        }
+    }
+}
+
+/*
+ * Determine if frequency stats should be printed.
+ *
+ * If the frequency stats are different between CPUs, the stats should be
+ * printed for each CPU, else only the aggregate frequency stats should be
+ * printed.
+ */
+static char should_print_freq_stats() {
+    int i, j;
+
+    for (i = 1; i < cpu_count; i++) {
+        for (j = 0; j < new_cpus[i].freq_count; j++) {
+            if (new_cpus[i].freqs[j].time - old_cpus[i].freqs[j].time !=
+                    new_cpus[0].freqs[j].time - old_cpus[0].freqs[j].time) {
+                return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+/*
+ * Determine if the frequency stats should be aggregated.
+ *
+ * Only aggregate the frequency stats in the total cpu stats if the frequencies
+ * reported by all CPUs are identical.  Must be called after read_stats() has
+ * been called once.
+ */
+static char should_aggregate_freq_stats() {
+    int i, j;
+
+    for (i = 1; i < cpu_count; i++) {
+        if (new_cpus[i].freq_count != new_cpus[0].freq_count) {
+            return 0;
+        }
+        for (j = 0; j < new_cpus[i].freq_count; j++) {
+            if (new_cpus[i].freqs[j].freq != new_cpus[0].freqs[j].freq) {
+                return 0;
+            }
+        }
+    }
+
+    return 1;
+}
+
+/*
+ * Print the usage message.
+ */
+static void usage(char *cmd) {
+    fprintf(stderr, "Usage %s [ -n iterations ] [ -d delay ] [ -c cpu ] [ -m ] [ -h ]\n"
+            "    -n num  Updates to show before exiting.\n"
+            "    -d num  Seconds to wait between updates.\n"
+            "    -m      Display minimal output.\n"
+            "    -h      Display this help screen.\n",
+            cmd);
+}
diff --git a/ext4_utils/Android.mk b/ext4_utils/Android.mk
index 10b6285..5dae31f 100644
--- a/ext4_utils/Android.mk
+++ b/ext4_utils/Android.mk
@@ -4,7 +4,7 @@
 include $(CLEAR_VARS)
 
 libext4_utils_src_files := \
-	make_ext4fs.c \
+        make_ext4fs.c \
         ext4fixup.c \
         ext4_utils.c \
         allocate.c \
@@ -15,8 +15,44 @@
         indirect.c \
         uuid.c \
         sha1.c \
-	sparse_crc32.c \
-	wipe.c
+        sparse_crc32.c \
+        wipe.c
+
+# -- All host/targets including windows
+
+LOCAL_SRC_FILES := $(libext4_utils_src_files)
+LOCAL_MODULE := libext4_utils
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES += external/zlib
+
+ifeq ($(HAVE_SELINUX), true)
+LOCAL_C_INCLUDES += external/libselinux/include
+LOCAL_STATIC_LIBRARIES += libselinux
+LOCAL_CFLAGS += -DHAVE_SELINUX
+endif # HAVE_SELINUX
+
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := make_ext4fs_main.c
+LOCAL_MODULE := make_ext4fs
+LOCAL_STATIC_LIBRARIES += libext4_utils libz
+ifeq ($(HOST_OS),windows)
+LOCAL_LDLIBS += -lws2_32
+else
+ifeq ($(HAVE_SELINUX), true)
+LOCAL_STATIC_LIBRARIES += libselinux
+endif # HAVE_SELINUX
+endif
+
+include $(BUILD_HOST_EXECUTABLE)
+
+include $(CLEAR_VARS)
+
+# -- All host/targets excluding windows
+
+ifneq ($(HOST_OS),windows)
 
 LOCAL_SRC_FILES := $(libext4_utils_src_files)
 LOCAL_MODULE := libext4_utils
@@ -38,7 +74,6 @@
 LOCAL_MODULE := libext4_utils
 LOCAL_MODULE_TAGS := optional
 LOCAL_C_INCLUDES += external/zlib
-LOCAL_STATIC_LIBRARIES := libz
 
 ifeq ($(HAVE_SELINUX), true)
 LOCAL_C_INCLUDES += external/libselinux/include
@@ -50,21 +85,6 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := $(libext4_utils_src_files)
-LOCAL_MODULE := libext4_utils
-LOCAL_MODULE_TAGS := optional
-LOCAL_SHARED_LIBRARIES := libz
-
-ifeq ($(HAVE_SELINUX), true)
-LOCAL_C_INCLUDES += external/libselinux/include
-LOCAL_SHARED_LIBRARIES += libselinux
-LOCAL_CFLAGS += -DHAVE_SELINUX
-endif # HAVE_SELINUX
-
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-
 LOCAL_SRC_FILES := make_ext4fs_main.c
 LOCAL_MODULE := make_ext4fs
 LOCAL_MODULE_TAGS := optional
@@ -80,20 +100,6 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := make_ext4fs_main.c
-LOCAL_MODULE := make_ext4fs
-LOCAL_STATIC_LIBRARIES += libext4_utils libz
-
-ifeq ($(HAVE_SELINUX), true)
-LOCAL_C_INCLUDES += external/libselinux/include
-LOCAL_STATIC_LIBRARIES += libselinux
-LOCAL_CFLAGS += -DHAVE_SELINUX
-endif # HAVE_SELINUX
-
-include $(BUILD_HOST_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
 LOCAL_SRC_FILES := ext2simg.c
 LOCAL_MODULE := ext2simg
 LOCAL_MODULE_TAGS := optional
@@ -127,6 +133,7 @@
 LOCAL_SRC_FILES := simg2img.c \
 	sparse_crc32.c
 LOCAL_MODULE := simg2img
+LOCAL_MODULE_TAGS := debug
 
 include $(BUILD_HOST_EXECUTABLE)
 
@@ -135,6 +142,23 @@
 LOCAL_SRC_FILES := simg2img.c \
 	sparse_crc32.c
 LOCAL_MODULE := simg2img
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := img2simg.c
+LOCAL_MODULE := img2simg
+LOCAL_MODULE_TAGS := debug
+
+include $(BUILD_HOST_EXECUTABLE)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := img2simg.c
+LOCAL_MODULE := img2simg
+LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_EXECUTABLE)
 
@@ -174,3 +198,15 @@
 LOCAL_IS_HOST_MODULE := true
 
 include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := simg_dump.py
+LOCAL_MODULE_TAGS := debug
+LOCAL_SRC_FILES := simg_dump.py
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_IS_HOST_MODULE := true
+
+include $(BUILD_PREBUILT)
+
+endif
diff --git a/ext4_utils/backed_block.c b/ext4_utils/backed_block.c
index f8399ef..c0070f1 100644
--- a/ext4_utils/backed_block.c
+++ b/ext4_utils/backed_block.c
@@ -150,7 +150,7 @@
 /* Frees the memory used by the linked list of data blocks */
 void free_data_blocks()
 {
-        if (!data_blocks) return;
+	if (!data_blocks) return;
 	struct data_block *db = data_blocks;
 	while (db) {
 		struct data_block *next = db->next;
@@ -167,6 +167,6 @@
 		free(db);
 		db = next;
 	}
-        data_blocks = NULL;
-        last_used = NULL;
+	data_blocks = NULL;
+	last_used = NULL;
 }
diff --git a/ext4_utils/contents.c b/ext4_utils/contents.c
index 71143bc..de38bb0 100644
--- a/ext4_utils/contents.c
+++ b/ext4_utils/contents.c
@@ -27,6 +27,10 @@
 #include "indirect.h"
 #include "xattr.h"
 
+#ifdef USE_MINGW
+#define S_IFLNK 0  /* used by make_link, not needed under mingw */
+#endif
+
 static u32 dentry_size(u32 entries, struct dentry *dentries)
 {
 	u32 len = 24;
diff --git a/ext4_utils/ext2simg.c b/ext4_utils/ext2simg.c
index 9332bad..1fe085a 100644
--- a/ext4_utils/ext2simg.c
+++ b/ext4_utils/ext2simg.c
@@ -28,6 +28,10 @@
 #include <libgen.h>
 #include <unistd.h>
 
+#ifndef USE_MINGW /* O_BINARY is windows-specific flag */
+#define O_BINARY 0
+#endif
+
 extern struct fs_info info;
 
 static int verbose = 0;
@@ -169,7 +173,7 @@
 	const char *out = NULL;
 	int gzip = 0;
 	int sparse = 1;
-	int fd;
+	int infd, outfd;
 	int crc = 0;
 
 	while ((opt = getopt(argc, argv, "cvzS")) != -1) {
@@ -211,18 +215,29 @@
 		exit(EXIT_FAILURE);
 	}
 
-	fd = open(in, O_RDONLY);
+	infd = open(in, O_RDONLY);
 
-	if (fd < 0)
+	if (infd < 0)
 		critical_error_errno("failed to open input image");
 
-	read_ext(fd);
+	read_ext(infd);
 
-	build_sparse_ext(fd, in);
+	build_sparse_ext(infd, in);
 
-	close(fd);
+	close(infd);
 
-	write_ext4_image(out, gzip, sparse, crc, 0);
+	if (strcmp(out, "-")) {
+		outfd = open(out, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+		if (outfd < 0) {
+			error_errno("open");
+			return EXIT_FAILURE;
+		}
+	} else {
+		outfd = STDOUT_FILENO;
+	}
+
+	write_ext4_image(outfd, gzip, sparse, crc, 0);
+	close(outfd);
 
 	return 0;
 }
diff --git a/ext4_utils/ext4_utils.c b/ext4_utils/ext4_utils.c
index 3d5895e..7f226c8 100644
--- a/ext4_utils/ext4_utils.c
+++ b/ext4_utils/ext4_utils.c
@@ -23,12 +23,17 @@
 #include "extent.h"
 
 #include <fcntl.h>
-#include <arpa/inet.h>
-#include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <string.h>
 
+#ifdef USE_MINGW
+#include <winsock2.h>
+#else
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#endif
+
 #if defined(__linux__)
 #include <linux/fs.h>
 #elif defined(__APPLE__) && defined(__MACH__)
@@ -137,11 +142,11 @@
 }
 
 /* Write the filesystem image to a file */
-void write_ext4_image(const char *filename, int gz, int sparse, int crc,
-		int wipe)
+void write_ext4_image(int fd, int gz, int sparse, int crc, int wipe)
 {
 	int ret = 0;
-	struct output_file *out = open_output_file(filename, gz, sparse,
+
+	struct output_file *out = open_output_fd(fd, gz, sparse,
 	        count_sparse_chunks(), crc, wipe);
 
 	if (!out)
@@ -446,15 +451,11 @@
 	}
 }
 
-static u64 get_block_device_size(const char *filename)
+static u64 get_block_device_size(int fd)
 {
-	int fd = open(filename, O_RDONLY);
 	u64 size = 0;
 	int ret;
 
-	if (fd < 0)
-		return 0;
-
 #if defined(__linux__)
 	ret = ioctl(fd, BLKGETSIZE64, &size);
 #elif defined(__APPLE__) && defined(__MACH__)
@@ -464,22 +465,20 @@
 	return 0;
 #endif
 
-	close(fd);
-
 	if (ret)
 		return 0;
 
 	return size;
 }
 
-u64 get_file_size(const char *filename)
+u64 get_file_size(int fd)
 {
 	struct stat buf;
 	int ret;
 	u64 reserve_len = 0;
 	s64 computed_size;
 
-	ret = stat(filename, &buf);
+	ret = fstat(fd, &buf);
 	if (ret)
 		return 0;
 
@@ -489,7 +488,7 @@
 	if (S_ISREG(buf.st_mode))
 		computed_size = buf.st_size - reserve_len;
 	else if (S_ISBLK(buf.st_mode))
-		computed_size = get_block_device_size(filename) - reserve_len;
+		computed_size = get_block_device_size(fd) - reserve_len;
 	else
 		computed_size = 0;
 
@@ -514,4 +513,3 @@
 
 	return num;
 }
-
diff --git a/ext4_utils/ext4_utils.h b/ext4_utils/ext4_utils.h
index 94f4bc9..1d701d0 100644
--- a/ext4_utils/ext4_utils.h
+++ b/ext4_utils/ext4_utils.h
@@ -17,7 +17,13 @@
 #ifndef _EXT4_UTILS_H_
 #define _EXT4_UTILS_H_
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 #define _FILE_OFFSET_BITS 64
 #define _LARGEFILE64_SOURCE
 #include <sys/types.h>
@@ -58,7 +64,9 @@
 #define EXT4_SUPER_MAGIC 0xEF53
 #define EXT4_JNL_BACKUP_BLOCKS 1
 
+#ifndef min /* already defined by windows.h */
 #define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
 
 #define DIV_ROUND_UP(x, y) (((x) + (y) - 1)/(y))
 #define ALIGN(x, y) ((y) * DIV_ROUND_UP((x), (y)))
@@ -145,7 +153,7 @@
 }
 
 int ext4_bg_has_super_block(int bg);
-void write_ext4_image(const char *filename, int gz, int sparse, int crc,
+void write_ext4_image(int fd, int gz, int sparse, int crc,
 		int wipe);
 void ext4_create_fs_aux_info(void);
 void ext4_free_fs_aux_info(void);
@@ -154,8 +162,12 @@
 void ext4_create_journal_inode(void);
 void ext4_update_free(void);
 void ext4_queue_sb(void);
-u64 get_file_size(const char *filename);
+u64 get_file_size(int fd);
 u64 parse_num(const char *arg);
 void ext4_parse_sb(struct ext4_super_block *sb);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/ext4_utils/ext4fixup.c b/ext4_utils/ext4fixup.c
index 5e04602..c664ac3 100644
--- a/ext4_utils/ext4fixup.c
+++ b/ext4_utils/ext4fixup.c
@@ -24,10 +24,13 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <sys/mman.h>
 #include <fcntl.h>
 #include <unistd.h>
 
+#ifndef USE_MINGW
+#include <sys/mman.h>
+#endif
+
 #if defined(__APPLE__) && defined(__MACH__)
 #define lseek64 lseek
 #define off64_t off_t
diff --git a/ext4_utils/img2simg.c b/ext4_utils/img2simg.c
new file mode 100644
index 0000000..3b46613
--- /dev/null
+++ b/ext4_utils/img2simg.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2010-2012 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.
+ */
+
+#define DEFAULT_BLOCK_SIZE	"4K"
+#define DEFAULT_CHUNK_SIZE	"64M"
+#define DEFAULT_SUFFIX		"%03d"
+
+#include "ext4_utils.h"
+#include "sparse_format.h"
+#if 0 /* endian.h is not on all platforms */
+# include <endian.h>
+#else
+  /* For now, just assume we're going to run on little-endian. */
+# define my_htole32(h) (h)
+# define my_htole16(h) (h)
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#define COPY_BUF_SIZE (1024*1024)
+static char *copy_buf;
+
+static const char *progname(const char *argv0)
+{
+    const char *prog_name;
+    if ((prog_name = strrchr(argv0, '/')))
+	return(prog_name + 1);	/* Advance beyond '/'. */
+    return(argv0);		/* No '/' in argv0, use it as is. */
+}
+
+static void error_exit(const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    fputc('\n', stderr);
+    va_end(ap);
+
+    exit(EXIT_FAILURE);
+}
+
+static void usage(const char *argv0, const char *error_fmt, ...)
+{
+    fprintf(stderr,
+	    "Usage: %s [OPTIONS] <raw_image_file>\n",
+	    progname(argv0));
+    fprintf(stderr, "The <raw_image_file> will be split into as many sparse\n");
+    fprintf(stderr, "files as needed.  Each sparse file will contain a single\n");
+    fprintf(stderr, "DONT CARE chunk to offset to the correct block and then\n");
+    fprintf(stderr, "a single RAW chunk containing a portion of the data from\n");
+    fprintf(stderr, "the raw image file.  The sparse files will be named by\n");
+    fprintf(stderr, "appending a number to the name of the raw image file.\n");
+    fprintf(stderr, "\n");
+    fprintf(stderr, "OPTIONS (Defaults are enclosed by square brackets):\n");
+    fprintf(stderr, "  -s SUFFIX      Format appended number with SUFFIX [%s]\n",
+	    DEFAULT_SUFFIX);
+    fprintf(stderr, "  -B SIZE        Use a block size of SIZE [%s]\n",
+	    DEFAULT_BLOCK_SIZE);
+    fprintf(stderr, "  -C SIZE        Use a chunk size of SIZE [%s]\n",
+	    DEFAULT_CHUNK_SIZE);
+    fprintf(stderr, "SIZE is a decimal integer that may optionally be\n");
+    fprintf(stderr, "followed by a suffix that specifies a multiplier for\n");
+    fprintf(stderr, "the integer:\n");
+    fprintf(stderr, "       c         1 byte (the default when omitted)\n");
+    fprintf(stderr, "       w         2 bytes\n");
+    fprintf(stderr, "       b         512 bytes\n");
+    fprintf(stderr, "       kB        1000 bytes\n");
+    fprintf(stderr, "       K         1024 bytes\n");
+    fprintf(stderr, "       MB        1000*1000 bytes\n");
+    fprintf(stderr, "       M         1024*1024 bytes\n");
+    fprintf(stderr, "       GB        1000*1000*1000 bytes\n");
+    fprintf(stderr, "       G         1024*1024*1024 bytes\n");
+
+    if (error_fmt && *error_fmt)
+    {
+	fprintf(stderr, "\n");
+	va_list ap;
+	va_start(ap, error_fmt);
+	vfprintf(stderr, error_fmt, ap);
+	va_end(ap);
+	fprintf(stderr, "\n");
+    }
+
+    exit(EXIT_FAILURE);
+}
+
+static void cpy_file(int out_fd, char *out_path, int in_fd, char *in_path,
+		     size_t len)
+{
+    ssize_t s, cpy_len = COPY_BUF_SIZE;
+
+    while (len) {
+	if (len < COPY_BUF_SIZE)
+	    cpy_len = len;
+
+	s = read(in_fd, copy_buf, cpy_len);
+	if (s < 0)
+	    error_exit("\"%s\": %s", in_path, strerror(errno));
+	if (!s)
+	    error_exit("\"%s\": Unexpected EOF", in_path);
+
+	cpy_len = s;
+
+	s = write(out_fd, copy_buf, cpy_len);
+	if (s < 0)
+	    error_exit("\"%s\": %s", out_path, strerror(errno));
+	if (s != cpy_len)
+	    error_exit("\"%s\": Short data write (%lu)", out_path,
+		       (unsigned long)s);
+
+	len -= cpy_len;
+    }
+}
+
+static int parse_size(const char *size_str, size_t *size)
+{
+    static const size_t MAX_SIZE_T = ~(size_t)0;
+    size_t mult;
+    unsigned long long int value;
+    const char *end;
+    errno = 0;
+    value = strtoull(size_str, (char **)&end, 10);
+    if (errno != 0 || end == size_str || value > MAX_SIZE_T)
+	return -1;
+    if (*end == '\0') {
+	*size = value;
+	return 0;
+    }
+    if (!strcmp(end, "c"))
+	mult = 1;
+    else if (!strcmp(end, "w"))
+	mult = 2;
+    else if (!strcmp(end, "b"))
+	mult = 512;
+    else if (!strcmp(end, "kB"))
+	mult = 1000;
+    else if (!strcmp(end, "K"))
+	mult = 1024;
+    else if (!strcmp(end, "MB"))
+	mult = (size_t)1000*1000;
+    else if (!strcmp(end, "M"))
+	mult = (size_t)1024*1024;
+    else if (!strcmp(end, "GB"))
+	mult = (size_t)1000*1000*1000;
+    else if (!strcmp(end, "G"))
+	mult = (size_t)1024*1024*1024;
+    else
+	return -1;
+
+    if (value > MAX_SIZE_T / mult)
+	return -1;
+    *size = value * mult;
+    return 0;
+}
+
+int main(int argc, char *argv[])
+{
+    char *suffix = DEFAULT_SUFFIX;
+    char *block_size_str = DEFAULT_BLOCK_SIZE;
+    char *chunk_size_str = DEFAULT_CHUNK_SIZE;
+    size_t block_size, chunk_size, blocks_per_chunk, to_write;
+    char *in_path, *out_path, *out_fmt;
+    int in_fd, out_fd;
+    struct stat in_st;
+    off_t left_to_write;
+    struct {
+	sparse_header_t sparse_hdr;
+	chunk_header_t dont_care_hdr;
+	chunk_header_t raw_hdr;
+    } file_hdr;
+    unsigned int file_count;
+    ssize_t s;
+    int i;
+
+    /* Parse the command line. */
+    while ((i = getopt(argc, argv, "s:B:C:")) != -1)
+    {
+	switch (i) {
+	case 's':
+	    suffix = optarg;
+	    break;
+	case 'B':
+	    block_size_str = optarg;
+	    break;
+	case 'C':
+	    chunk_size_str = optarg;
+	    break;
+	default:
+	    usage(argv[0], NULL);
+	    break;
+	}
+    }
+
+    if (parse_size(block_size_str, &block_size))
+	usage(argv[0], "Can not parse \"%s\" as a block size.",
+	      block_size_str);
+    if (block_size % 4096)
+	usage(argv[0], "Block size is not a multiple of 4096.");
+
+    if (parse_size(chunk_size_str, &chunk_size))
+	usage(argv[0], "Can not parse \"%s\" as a chunk size.",
+	      chunk_size_str);
+    if (chunk_size % block_size)
+	usage(argv[0], "Chunk size is not a multiple of the block size.");
+    blocks_per_chunk = chunk_size / block_size;
+
+    if ((argc - optind) != 1)
+	usage(argv[0], "Missing or extra arguments.");
+    in_path = argv[optind];
+
+    /* Open the input file and validate it. */
+    if ((in_fd = open(in_path, O_RDONLY)) < 0)
+	error_exit("open \"%s\": %s", in_path, strerror(errno));
+    if (fstat(in_fd, &in_st))
+	error_exit("fstat \"%s\": %s", in_path, strerror(errno));
+    left_to_write = in_st.st_size;
+    if (left_to_write % block_size)
+	error_exit(
+	    "\"%s\" size (%llu) is not a multiple of the block size (%llu).\n",
+	    in_path,
+	    (unsigned long long)left_to_write, (unsigned long long)block_size);
+
+    /* Get a buffer for copying the chunks. */
+    if ((copy_buf = malloc(COPY_BUF_SIZE)) == 0)
+	error_exit("malloc copy buffer: %s", strerror(errno));
+
+    /* Get a buffer for a sprintf format to form output paths. */
+    if ((out_fmt = malloc(sizeof("%s") + strlen(suffix))) == 0)
+	error_exit("malloc format buffer: %s", strerror(errno));
+    out_fmt[0] = '%';
+    out_fmt[1] = 's';
+    strcpy(out_fmt + 2, suffix);
+
+    /* Get a buffer for an output path. */
+    i = snprintf(copy_buf, COPY_BUF_SIZE, out_fmt, in_path, UINT_MAX);
+    if (i >= COPY_BUF_SIZE)
+	error_exit("Ridulously long suffix: %s", suffix);
+    if ((out_path = malloc(i + 1)) == 0)
+	error_exit("malloc output path buffer: %s", strerror(errno));
+
+    /*
+     * Each file gets a sparse_header, a Don't Care chunk to offset to
+     * where the data belongs and then a Raw chunk with the actual data.
+     */
+    memset((void *)&file_hdr.sparse_hdr, 0, sizeof(file_hdr.sparse_hdr));
+    file_hdr.sparse_hdr.magic = my_htole32(SPARSE_HEADER_MAGIC);
+    file_hdr.sparse_hdr.major_version = my_htole16(1);
+    file_hdr.sparse_hdr.minor_version = my_htole16(0);
+    file_hdr.sparse_hdr.file_hdr_sz = my_htole16(sizeof(sparse_header_t));
+    file_hdr.sparse_hdr.chunk_hdr_sz = my_htole16(sizeof(chunk_header_t));
+    file_hdr.sparse_hdr.blk_sz = my_htole32(block_size);
+    /* The total_blks will be set in the file loop below. */
+    file_hdr.sparse_hdr.total_chunks = my_htole32(2);
+    file_hdr.sparse_hdr.image_checksum = my_htole32(0); /* Typically unused. */
+
+    memset((void *)&file_hdr.dont_care_hdr, 0, sizeof(file_hdr.dont_care_hdr));
+    file_hdr.dont_care_hdr.chunk_type = my_htole16(CHUNK_TYPE_DONT_CARE);
+    /* The Don't Care's chunk_sz will be set in the file loop below. */
+    file_hdr.dont_care_hdr.total_sz = my_htole32(sizeof(chunk_header_t));
+
+    memset((void *)&file_hdr.raw_hdr, 0, sizeof(file_hdr.raw_hdr));
+    file_hdr.raw_hdr.chunk_type = my_htole16(CHUNK_TYPE_RAW);
+    file_hdr.raw_hdr.chunk_sz = my_htole32(blocks_per_chunk);
+    file_hdr.raw_hdr.total_sz = my_htole32(chunk_size + sizeof(chunk_header_t));
+
+    /* Loop through writing chunk_size to each of the output files. */
+    to_write = chunk_size;
+    for (file_count = 1; left_to_write ; file_count++) {
+	/* Fix up the headers on the last block. */
+	if (left_to_write < (off_t)chunk_size) {
+	    to_write = left_to_write;
+	    file_hdr.raw_hdr.chunk_sz = my_htole32(left_to_write / block_size);
+	    file_hdr.raw_hdr.total_sz = my_htole32(left_to_write
+						+ sizeof(chunk_header_t));
+	}
+
+	/* Form the pathname for this output file and open it. */
+	sprintf(out_path, out_fmt, in_path, file_count);
+	if ((out_fd = creat(out_path, 0666)) < 0)
+	    error_exit("\"%s\": %s", out_path, strerror(errno));
+
+	/* Update and write the headers to this output file. */
+	s = (file_count-1) * blocks_per_chunk;
+	file_hdr.dont_care_hdr.chunk_sz = my_htole32(s);
+	file_hdr.sparse_hdr.total_blks = my_htole32(s
+						+ (to_write / block_size));
+	s = write(out_fd, (void *)&file_hdr, sizeof(file_hdr));
+	if (s < 0)
+	    error_exit("\"%s\": %s", out_path, strerror(errno));
+	if (s != sizeof(file_hdr))
+	    error_exit("\"%s\": Short write (%lu)", out_path, (unsigned long)s);
+
+	/* Copy this chunk from the input file to the output file. */
+	cpy_file(out_fd, out_path, in_fd, in_path, to_write);
+
+	/* Close this output file and update the amount left to write. */
+	if (close(out_fd))
+	    error_exit("close \"%s\": %s", out_path, strerror(errno));
+	left_to_write -= to_write;
+    }
+
+    if (close(in_fd))
+	error_exit("close \"%s\": %s", in_path, strerror(errno));
+
+    exit(EXIT_SUCCESS);
+}
diff --git a/ext4_utils/make_ext4fs.c b/ext4_utils/make_ext4fs.c
index af05eb3..6cd5ade 100644
--- a/ext4_utils/make_ext4fs.c
+++ b/ext4_utils/make_ext4fs.c
@@ -22,7 +22,9 @@
 #include "uuid.h"
 #include "backed_block.h"
 
+#include <assert.h>
 #include <dirent.h>
+#include <fcntl.h>
 #include <libgen.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -31,8 +33,33 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
-#ifdef ANDROID
-#include <private/android_filesystem_config.h>
+#ifdef USE_MINGW
+
+#include <winsock2.h>
+
+/* These match the Linux definitions of these flags.
+   L_xx is defined to avoid conflicting with the win32 versions.
+*/
+#define L_S_IRUSR 00400
+#define L_S_IWUSR 00200
+#define L_S_IXUSR 00100
+#define S_IRWXU (L_S_IRUSR | L_S_IWUSR | L_S_IXUSR)
+#define S_IRGRP 00040
+#define S_IWGRP 00020
+#define S_IXGRP 00010
+#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
+#define S_IROTH 00004
+#define S_IWOTH 00002
+#define S_IXOTH 00001
+#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
+#define S_ISUID 0004000
+#define S_ISGID 0002000
+#define S_ISVTX 0001000
+
+#else
+
+#define O_BINARY 0
+
 #endif
 
 /* TODO: Not implemented:
@@ -67,10 +94,12 @@
 	return root_inode;
 }
 
+#ifndef USE_MINGW
 /* Read a local directory and create the same tree in the generated filesystem.
    Calls itself recursively with each directory in the given directory */
 static u32 build_directory_structure(const char *full_path, const char *dir_path,
-		     u32 dir_inode, int android, struct selabel_handle *sehnd)
+		u32 dir_inode, fs_config_func_t fs_config_func,
+		struct selabel_handle *sehnd)
 {
 	int entries = 0;
 	struct dentry *dentries;
@@ -113,13 +142,13 @@
 		dentries[i].size = stat.st_size;
 		dentries[i].mode = stat.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
 		dentries[i].mtime = stat.st_mtime;
-		if (android) {
+		if (fs_config_func != NULL) {
 #ifdef ANDROID
 			unsigned int mode = 0;
 			unsigned int uid = 0;
 			unsigned int gid = 0;
 			int dir = S_ISDIR(stat.st_mode);
-			fs_config(dentries[i].path, dir, &uid, &gid, &mode);
+			fs_config_func(dentries[i].path, dir, &uid, &gid, &mode);
 			dentries[i].mode = mode;
 			dentries[i].uid = uid;
 			dentries[i].gid = gid;
@@ -172,7 +201,7 @@
 			entry_inode = make_file(dentries[i].full_path, dentries[i].size);
 		} else if (dentries[i].file_type == EXT4_FT_DIR) {
 			entry_inode = build_directory_structure(dentries[i].full_path,
-					dentries[i].path, inode, android, sehnd);
+					dentries[i].path, inode, fs_config_func, sehnd);
 		} else if (dentries[i].file_type == EXT4_FT_SYMLINK) {
 			entry_inode = make_link(dentries[i].full_path, dentries[i].link);
 		} else {
@@ -200,6 +229,7 @@
 	free(dentries);
 	return inode;
 }
+#endif
 
 static u32 compute_block_size()
 {
@@ -269,29 +299,40 @@
 int make_ext4fs(const char *filename, s64 len,
                 const char *mountpoint, struct selabel_handle *sehnd)
 {
-    reset_ext4fs_info();
-    info.len = len;
-    return make_ext4fs_internal(filename, NULL, mountpoint, 0, 0, 0, 0, 1, 0, sehnd);
+	int fd;
+	int status;
+
+	reset_ext4fs_info();
+	info.len = len;
+
+	fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+	if (fd < 0) {
+		error_errno("open");
+		return EXIT_FAILURE;
+	}
+
+	status = make_ext4fs_internal(fd, NULL, mountpoint, NULL, 0, 0, 0, 1, 0, sehnd);
+	close(fd);
+
+	return status;
 }
 
-int make_ext4fs_internal(const char *filename, const char *directory,
-                         const char *mountpoint,
-                         int android, int gzip, int sparse,
-                         int crc, int wipe, int init_itabs,
-                         struct selabel_handle *sehnd)
+int make_ext4fs_internal(int fd, const char *directory,
+                         char *mountpoint, fs_config_func_t fs_config_func, int gzip, int sparse,
+                         int crc, int wipe, int init_itabs, struct selabel_handle *sehnd)
 {
-        u32 root_inode_num;
-        u16 root_mode;
+	u32 root_inode_num;
+	u16 root_mode;
 
 	if (setjmp(setjmp_env))
 		return EXIT_FAILURE; /* Handle a call to longjmp() */
 
 	if (info.len <= 0)
-		info.len = get_file_size(filename);
+		info.len = get_file_size(fd);
 
 	if (info.len <= 0) {
 		fprintf(stderr, "Need size of filesystem\n");
-                return EXIT_FAILURE;
+		return EXIT_FAILURE;
 	}
 
 	if (info.block_size <= 0)
@@ -364,10 +405,17 @@
 	if (info.feat_compat & EXT4_FEATURE_COMPAT_RESIZE_INODE)
 		ext4_create_resize_inode();
 
+#ifdef USE_MINGW
+	// Windows needs only 'create an empty fs image' functionality
+	assert(!directory);
+	root_inode_num = build_default_directory_structure();
+#else
 	if (directory)
-		root_inode_num = build_directory_structure(directory, mountpoint, 0, android, sehnd);
+		root_inode_num = build_directory_structure(directory, mountpoint, 0,
+                        fs_config_func, sehnd);
 	else
 		root_inode_num = build_default_directory_structure();
+#endif
 
 	root_mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
 	inode_set_permissions(root_inode_num, root_mode, 0, 0, 0);
@@ -408,7 +456,7 @@
 			aux_info.sb->s_blocks_count_lo - aux_info.sb->s_free_blocks_count_lo,
 			aux_info.sb->s_blocks_count_lo);
 
-	write_ext4_image(filename, gzip, sparse, crc, wipe);
+	write_ext4_image(fd, gzip, sparse, crc, wipe);
 
 	return 0;
 }
diff --git a/ext4_utils/make_ext4fs.h b/ext4_utils/make_ext4fs.h
index 53ff840..c217c3d 100644
--- a/ext4_utils/make_ext4fs.h
+++ b/ext4_utils/make_ext4fs.h
@@ -20,6 +20,10 @@
 #include "ext4_utils.h"
 #include "ext4.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #ifdef HAVE_SELINUX
 #include <selinux/selinux.h>
 #include <selinux/label.h>
@@ -27,13 +31,18 @@
 struct selabel_handle;
 #endif
 
+typedef void (*fs_config_func_t)(const char *path, int dir, unsigned *uid, unsigned *gid,
+        unsigned *mode);
+
 void reset_ext4fs_info();
 int make_ext4fs(const char *filename, s64 len,
                 const char *mountpoint, struct selabel_handle *sehnd);
-int make_ext4fs_internal(const char *filename, const char *directory,
-                         const char *mountpoint,
-                         int android, int gzip, int sparse,
-                         int crc, int wipe, int init_itabs,
-                         struct selabel_handle *sehnd);
+int make_ext4fs_internal(int fd, const char *directory,
+                         char *mountpoint, fs_config_func_t fs_config_func, int gzip, int sparse,
+                         int crc, int wipe, int init_itabs, struct selabel_handle *sehnd);
+
+#ifdef __cplusplus
+}
+#endif
 
 #endif
diff --git a/ext4_utils/make_ext4fs_main.c b/ext4_utils/make_ext4fs_main.c
index 6a885d2..d545423 100644
--- a/ext4_utils/make_ext4fs_main.c
+++ b/ext4_utils/make_ext4fs_main.c
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#include <unistd.h>
+#include <fcntl.h>
 #include <libgen.h>
+#include <unistd.h>
 
 #if defined(__linux__)
 #include <linux/fs.h>
@@ -23,137 +24,166 @@
 #include <sys/disk.h>
 #endif
 
+#ifdef ANDROID
+#include <private/android_filesystem_config.h>
+#endif
+
 #include "make_ext4fs.h"
 
+#ifndef USE_MINGW /* O_BINARY is windows-specific flag */
+#define O_BINARY 0
+#endif
+
 extern struct fs_info info;
 
 
 static void usage(char *path)
 {
-        fprintf(stderr, "%s [ -l <len> ] [ -j <journal size> ] [ -b <block_size> ]\n", basename(path));
-        fprintf(stderr, "    [ -g <blocks per group> ] [ -i <inodes> ] [ -I <inode size> ]\n");
-        fprintf(stderr, "    [ -L <label> ] [ -f ] [ -a <android mountpoint> ]\n");
-        fprintf(stderr, "    [ -S file_contexts ]\n");
-        fprintf(stderr, "    [ -z | -s ] [ -t ] [ -w ] [ -c ] [ -J ]\n");
-        fprintf(stderr, "    <filename> [<directory>]\n");
+	fprintf(stderr, "%s [ -l <len> ] [ -j <journal size> ] [ -b <block_size> ]\n", basename(path));
+	fprintf(stderr, "    [ -g <blocks per group> ] [ -i <inodes> ] [ -I <inode size> ]\n");
+	fprintf(stderr, "    [ -L <label> ] [ -f ] [ -a <android mountpoint> ]\n");
+	fprintf(stderr, "    [ -S file_contexts ]\n");
+	fprintf(stderr, "    [ -z | -s ] [ -t ] [ -w ] [ -c ] [ -J ]\n");
+	fprintf(stderr, "    <filename> [<directory>]\n");
 }
 
 int main(int argc, char **argv)
 {
-        int opt;
-        const char *filename = NULL;
-        const char *directory = NULL;
-        char *mountpoint = "";
-        int android = 0;
-        int gzip = 0;
-        int sparse = 0;
-        int crc = 0;
-        int wipe = 0;
-        int init_itabs = 0;
-        struct selabel_handle *sehnd = NULL;
+	int opt;
+	const char *filename = NULL;
+	const char *directory = NULL;
+	char *mountpoint = "";
+	fs_config_func_t fs_config_func = NULL;
+	int gzip = 0;
+	int sparse = 0;
+	int crc = 0;
+	int wipe = 0;
+	int init_itabs = 0;
+	int fd;
+	int exitcode;
+	struct selabel_handle *sehnd = NULL;
 #ifdef HAVE_SELINUX
-        struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "" } };
+	struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "" } };
 #endif
 
-        while ((opt = getopt(argc, argv, "l:j:b:g:i:I:L:a:fwzJsctS:")) != -1) {
-                switch (opt) {
-                case 'l':
-                        info.len = parse_num(optarg);
-                        break;
-                case 'j':
-                        info.journal_blocks = parse_num(optarg);
-                        break;
-                case 'b':
-                        info.block_size = parse_num(optarg);
-                        break;
-                case 'g':
-                        info.blocks_per_group = parse_num(optarg);
-                        break;
-                case 'i':
-                        info.inodes = parse_num(optarg);
-                        break;
-                case 'I':
-                        info.inode_size = parse_num(optarg);
-                        break;
-                case 'L':
-                        info.label = optarg;
-                        break;
-                case 'f':
-                        force = 1;
-                        break;
-                case 'a':
-                        android = 1;
-                        mountpoint = optarg;
-                        break;
-                case 'w':
-                        wipe = 1;
-                        break;
-                case 'z':
-                        gzip = 1;
-                        break;
+	while ((opt = getopt(argc, argv, "l:j:b:g:i:I:L:a:fwzJsctS:")) != -1) {
+		switch (opt) {
+		case 'l':
+			info.len = parse_num(optarg);
+			break;
+		case 'j':
+			info.journal_blocks = parse_num(optarg);
+			break;
+		case 'b':
+			info.block_size = parse_num(optarg);
+			break;
+		case 'g':
+			info.blocks_per_group = parse_num(optarg);
+			break;
+		case 'i':
+			info.inodes = parse_num(optarg);
+			break;
+		case 'I':
+			info.inode_size = parse_num(optarg);
+			break;
+		case 'L':
+			info.label = optarg;
+			break;
+		case 'f':
+			force = 1;
+			break;
+		case 'a':
+#ifdef ANDROID
+			fs_config_func = fs_config;
+			mountpoint = optarg;
+#else
+			fprintf(stderr, "can't set android permissions - built without android support\n");
+			usage(argv[0]);
+			exit(EXIT_FAILURE);
+#endif
+			break;
+		case 'w':
+			wipe = 1;
+			break;
+		case 'z':
+			gzip = 1;
+			break;
 		case 'J':
 			info.no_journal = 1;
 			break;
 		case 'c':
 			crc = 1;
 			break;
-                case 's':
-                        sparse = 1;
-                        break;
-                case 't':
-                        init_itabs = 1;
-                        break;
-                case 'S':
+		case 's':
+			sparse = 1;
+			break;
+		case 't':
+			init_itabs = 1;
+			break;
+		case 'S':
 #ifdef HAVE_SELINUX
-                        seopts[0].value = optarg;
-                        sehnd = selabel_open(SELABEL_CTX_FILE, seopts, 1);
-                        if (!sehnd) {
-                            perror(optarg);
-                            exit(EXIT_FAILURE);
-                        }
+			seopts[0].value = optarg;
+			sehnd = selabel_open(SELABEL_CTX_FILE, seopts, 1);
+			if (!sehnd) {
+				perror(optarg);
+				exit(EXIT_FAILURE);
+			}
 #endif
-                        break;
-                default: /* '?' */
-                        usage(argv[0]);
-                        exit(EXIT_FAILURE);
-                }
-        }
-
-	if (gzip && sparse) {
-                fprintf(stderr, "Cannot specify both gzip and sparse\n");
-                usage(argv[0]);
-                exit(EXIT_FAILURE);
+			   break;
+		default: /* '?' */
+			usage(argv[0]);
+			exit(EXIT_FAILURE);
+		}
 	}
 
-        if (wipe && sparse) {
-                fprintf(stderr, "Cannot specifiy both wipe and sparse\n");
-                usage(argv[0]);
-                exit(EXIT_FAILURE);
-        }
+	if (gzip && sparse) {
+		fprintf(stderr, "Cannot specify both gzip and sparse\n");
+		usage(argv[0]);
+		exit(EXIT_FAILURE);
+	}
 
-        if (wipe && gzip) {
-                fprintf(stderr, "Cannot specifiy both wipe and gzip\n");
-                usage(argv[0]);
-                exit(EXIT_FAILURE);
-        }
+	if (wipe && sparse) {
+		fprintf(stderr, "Cannot specifiy both wipe and sparse\n");
+		usage(argv[0]);
+		exit(EXIT_FAILURE);
+	}
 
-        if (optind >= argc) {
-                fprintf(stderr, "Expected filename after options\n");
-                usage(argv[0]);
-                exit(EXIT_FAILURE);
-        }
+	if (wipe && gzip) {
+		fprintf(stderr, "Cannot specifiy both wipe and gzip\n");
+		usage(argv[0]);
+		exit(EXIT_FAILURE);
+	}
 
-        filename = argv[optind++];
+	if (optind >= argc) {
+		fprintf(stderr, "Expected filename after options\n");
+		usage(argv[0]);
+		exit(EXIT_FAILURE);
+	}
 
-        if (optind < argc)
-                directory = argv[optind++];
+	filename = argv[optind++];
 
-        if (optind < argc) {
-                fprintf(stderr, "Unexpected argument: %s\n", argv[optind]);
-                usage(argv[0]);
-                exit(EXIT_FAILURE);
-        }
+	if (optind < argc)
+		directory = argv[optind++];
 
-        return make_ext4fs_internal(filename, directory, mountpoint, android, gzip,
-                       sparse, crc, wipe, init_itabs, sehnd);
+	if (optind < argc) {
+		fprintf(stderr, "Unexpected argument: %s\n", argv[optind]);
+		usage(argv[0]);
+		exit(EXIT_FAILURE);
+	}
+
+	if (strcmp(filename, "-")) {
+		fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+		if (fd < 0) {
+			error_errno("open");
+			return EXIT_FAILURE;
+		}
+	} else {
+		fd = STDOUT_FILENO;
+	}
+
+	exitcode = make_ext4fs_internal(fd, directory, mountpoint, fs_config_func, gzip,
+			sparse, crc, wipe, init_itabs, sehnd);
+	close(fd);
+
+	return exitcode;
 }
diff --git a/ext4_utils/output_file.c b/ext4_utils/output_file.c
index d7cf91b..40655a9 100644
--- a/ext4_utils/output_file.c
+++ b/ext4_utils/output_file.c
@@ -20,15 +20,20 @@
 #include "sparse_crc32.h"
 #include "wipe.h"
 
+#include <fcntl.h>
+#include <stdbool.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <sys/mman.h>
 #include <unistd.h>
-#include <fcntl.h>
-
 #include <zlib.h>
 
+#ifndef USE_MINGW
+#include <sys/mman.h>
+#define O_BINARY 0
+#endif
+
+
 #if defined(__APPLE__) && defined(__MACH__)
 #define lseek64 lseek
 #define off64_t off_t
@@ -48,6 +53,7 @@
 struct output_file {
 	int fd;
 	gzFile gz_fd;
+	bool close_fd;
 	int sparse;
 	u64 cur_out_ptr;
 	u32 chunk_cnt;
@@ -85,7 +91,9 @@
 
 static void file_close(struct output_file *out)
 {
-	close(out->fd);
+	if (out->close_fd) {
+		close(out->fd);
+	}
 }
 
 
@@ -343,7 +351,7 @@
 	out->ops->close(out);
 }
 
-struct output_file *open_output_file(const char *filename, int gz, int sparse,
+struct output_file *open_output_fd(int fd, int gz, int sparse,
         int chunks, int crc, int wipe)
 {
 	int ret;
@@ -362,25 +370,17 @@
 
 	if (gz) {
 		out->ops = &gz_file_ops;
-		out->gz_fd = gzopen(filename, "wb9");
+		out->gz_fd = gzdopen(fd, "wb9");
 		if (!out->gz_fd) {
 			error_errno("gzopen");
 			free(out);
 			return NULL;
 		}
 	} else {
-		if (strcmp(filename, "-")) {
-			out->fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
-			if (out->fd < 0) {
-				error_errno("open");
-				free(out);
-				return NULL;
-			}
-		} else {
-			out->fd = STDOUT_FILENO;
-		}
+		out->fd = fd;
 		out->ops = &file_ops;
 	}
+	out->close_fd = false;
 	out->sparse = sparse;
 	out->cur_out_ptr = 0ll;
 	out->chunk_cnt = 0;
@@ -407,6 +407,33 @@
 	return out;
 }
 
+struct output_file *open_output_file(const char *filename, int gz, int sparse,
+        int chunks, int crc, int wipe) {
+
+	int fd;
+	struct output_file *file;
+
+	if (strcmp(filename, "-")) {
+		fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+		if (fd < 0) {
+			error_errno("open");
+			return NULL;
+		}
+	} else {
+		fd = STDOUT_FILENO;
+	}
+
+	file = open_output_fd(fd, gz, sparse, chunks, crc, wipe);
+	if (!file) {
+		close(fd);
+		return NULL;
+	}
+
+	file->close_fd = true; // we opened descriptor thus we responsible for closing it
+
+	return file;
+}
+
 void pad_output_file(struct output_file *out, u64 len)
 {
 	int ret;
@@ -447,7 +474,7 @@
 void write_data_block(struct output_file *out, u64 off, u8 *data, int len)
 {
 	int ret;
-	
+
 	if (off + len > (u64) info.len) {
 		error("attempted to write block %llu past end of filesystem",
 				off + len - info.len);
@@ -512,6 +539,7 @@
 	int ret;
 	off64_t aligned_offset;
 	int aligned_diff;
+	int buffer_size;
 
 	if (off + len >= (u64) info.len) {
 		error("attempted to write block %llu past end of filesystem",
@@ -519,7 +547,7 @@
 		return;
 	}
 
-	int file_fd = open(file, O_RDONLY);
+	int file_fd = open(file, O_RDONLY | O_BINARY);
 	if (file_fd < 0) {
 		error_errno("open");
 		return;
@@ -527,14 +555,25 @@
 
 	aligned_offset = offset & ~(4096 - 1);
 	aligned_diff = offset - aligned_offset;
+	buffer_size = len + aligned_diff;
 
-	u8 *data = mmap64(NULL, len + aligned_diff, PROT_READ, MAP_SHARED, file_fd,
+#ifndef USE_MINGW
+	u8 *data = mmap64(NULL, buffer_size, PROT_READ, MAP_SHARED, file_fd,
 			aligned_offset);
 	if (data == MAP_FAILED) {
 		error_errno("mmap64");
 		close(file_fd);
 		return;
 	}
+#else
+	u8 *data = malloc(buffer_size);
+	if (!data) {
+		error_errno("malloc");
+		close(file_fd);
+		return;
+	}
+	memset(data, 0, buffer_size);
+#endif
 
 	if (out->sparse) {
 		write_chunk_raw(out, off, data + aligned_diff, len);
@@ -549,6 +588,11 @@
 	}
 
 err:
-	munmap(data, len);
+#ifndef USE_MINGW
+	munmap(data, buffer_size);
+#else
+	write(file_fd, data, buffer_size);
+	free(data);
+#endif
 	close(file_fd);
 }
diff --git a/ext4_utils/output_file.h b/ext4_utils/output_file.h
index b448706..a578c80 100644
--- a/ext4_utils/output_file.h
+++ b/ext4_utils/output_file.h
@@ -21,6 +21,8 @@
 
 struct output_file *open_output_file(const char *filename, int gz, int sparse,
         int chunks, int crc, int wipe);
+struct output_file *open_output_fd(int fd, int gz, int sparse,
+        int chunks, int crc, int wipe);
 void write_data_block(struct output_file *out, u64 off, u8 *data, int len);
 void write_fill_block(struct output_file *out, u64 off, u32 fill_val, int len);
 void write_data_file(struct output_file *out, u64 off, const char *file,
diff --git a/ext4_utils/sha1.c b/ext4_utils/sha1.c
index 1db9134..463ec38 100644
--- a/ext4_utils/sha1.c
+++ b/ext4_utils/sha1.c
@@ -17,7 +17,9 @@
 
 #define SHA1HANDSOFF		/* Copies data before messing with it. */
 
+#ifndef USE_MINGW
 #include <sys/cdefs.h>
+#endif
 #include <sys/types.h>
 #include <assert.h>
 #include <string.h>
diff --git a/ext4_utils/sha1.h b/ext4_utils/sha1.h
index 71334c8..9a8f7e3 100644
--- a/ext4_utils/sha1.h
+++ b/ext4_utils/sha1.h
@@ -9,10 +9,21 @@
 #ifndef _SYS_SHA1_H_
 #define	_SYS_SHA1_H_
 
-#include <sys/cdefs.h>
 #include <sys/types.h>
 #include <stdint.h>
 
+#ifdef USE_MINGW
+typedef unsigned char u_char;
+typedef unsigned int uint32_t;
+typedef unsigned int u_int32_t;
+typedef unsigned int u_int;
+
+#define __BEGIN_DECLS
+#define __END_DECLS
+#else
+#include <sys/cdefs.h>
+#endif
+
 #define SHA1_DIGEST_LENGTH		20
 #define SHA1_DIGEST_STRING_LENGTH	41
 
diff --git a/ext4_utils/simg2img.c b/ext4_utils/simg2img.c
index 228d289..12b92eb 100644
--- a/ext4_utils/simg2img.c
+++ b/ext4_utils/simg2img.c
@@ -247,7 +247,7 @@
 			fprintf(stderr, "Error reading chunk header\n");
 			exit(-1);
 		}
- 
+
 		if (sparse_header.chunk_hdr_sz > CHUNK_HEADER_LEN) {
 			/* Skip the remaining bytes in a header that is longer than
 			 * we expected.
diff --git a/ext4_utils/simg_dump.py b/ext4_utils/simg_dump.py
new file mode 100755
index 0000000..6ece31d
--- /dev/null
+++ b/ext4_utils/simg_dump.py
@@ -0,0 +1,169 @@
+#! /usr/bin/env python
+
+# Copyright (C) 2012 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.
+
+from __future__ import print_function
+import getopt, posixpath, signal, struct, sys
+
+def usage(argv0):
+  print("""
+Usage: %s [-v] sparse_image_file ...
+ -v             verbose output
+""" % ( argv0 ))
+  sys.exit(2)
+
+def main():
+
+  signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+
+  me = posixpath.basename(sys.argv[0])
+
+  # Parse the command line
+  verbose = 0			# -v
+  try:
+    opts, args = getopt.getopt(sys.argv[1:],
+                               "v",
+                               ["verbose"])
+  except getopt.GetoptError, e:
+    print(e)
+    usage(me)
+  for o, a in opts:
+    if o in ("-v", "--verbose"):
+      verbose += 1
+    else:
+      print("Unrecognized option \"%s\"" % (o))
+      usage(me)
+
+  if len(args) == 0:
+    print("No sparse_image_file specified")
+    usage(me)
+
+  for path in args:
+    FH = open(path, 'rb')
+    header_bin = FH.read(28)
+    header = struct.unpack("<I4H4I", header_bin)
+
+    magic = header[0]
+    major_version = header[1]
+    minor_version = header[2]
+    file_hdr_sz = header[3]
+    chunk_hdr_sz = header[4]
+    blk_sz = header[5]
+    total_blks = header[6]
+    total_chunks = header[7]
+    image_checksum = header[8]
+
+    if magic != 0xED26FF3A:
+      print("%s: %s: Magic should be 0xED26FF3A but is 0x%08X"
+            % (me, path, magic))
+      continue
+    if major_version != 1 or minor_version != 0:
+      print("%s: %s: I only know about version 1.0, but this is version %u.%u"
+            % (me, path, major_version, minor_version))
+      continue
+    if file_hdr_sz != 28:
+      print("%s: %s: The file header size was expected to be 28, but is %u."
+            % (me, path, file_hdr_sz))
+      continue
+    if chunk_hdr_sz != 12:
+      print("%s: %s: The chunk header size was expected to be 12, but is %u."
+            % (me, path, chunk_hdr_sz))
+      continue
+
+    print("%s: Total of %u %u-byte output blocks in %u input chunks."
+          % (path, total_blks, blk_sz, total_chunks))
+
+    if image_checksum != 0:
+      print("checksum=0x%08X" % (image_checksum))
+
+    if not verbose:
+      continue
+    print("            input_bytes      output_blocks")
+    print("chunk    offset     number  offset  number")
+    offset = 0
+    for i in xrange(1,total_chunks+1):
+      header_bin = FH.read(12)
+      header = struct.unpack("<2H2I", header_bin)
+      chunk_type = header[0]
+      reserved1 = header[1]
+      chunk_sz = header[2]
+      total_sz = header[3]
+      data_sz = total_sz - 12
+
+      print("%4u %10u %10u %7u %7u" % (i, FH.tell(), data_sz, offset, chunk_sz),
+            end=" ")
+
+      if chunk_type == 0xCAC1:
+        if data_sz != (chunk_sz * blk_sz):
+          print("Raw chunk input size (%u) does not match output size (%u)"
+                % (data_sz, chunk_sz * blk_sz))
+          break;
+        else:
+          print("Raw data", end="")
+          FH.read(data_sz)
+      elif chunk_type == 0xCAC2:
+        if data_sz != 4:
+          print("Fill chunk should have 4 bytes of fill, but this has %u"
+                % (data_sz), end="")
+          break;
+        else:
+          fill_bin = FH.read(4)
+          fill = struct.unpack("<I", fill_bin)
+          print("Fill with 0x%08X" % (fill))
+      elif chunk_type == 0xCAC3:
+        if data_sz != 0:
+          print("Don't care chunk input size is non-zero (%u)" % (data_sz))
+          break;
+        else:
+          print("Don't care", end="")
+      elif chunk_type == 0xCAC4:
+        if data_sz != 4:
+          print("CRC32 chunk should have 4 bytes of CRC, but this has %u"
+                % (data_sz), end="")
+          break;
+        else:
+          crc_bin = FH.read(4)
+          crc = struct.unpack("<I", crc)
+          print("Unverified CRC32 0x%08X" % (crc))
+      else:
+          print("Unknown chunk type 0x%04X" % (chunk_type), end="")
+          break;
+
+      if verbose > 1:
+        header = struct.unpack("<12B", header_bin)
+        print(" (%02X%02X %02X%02X %02X%02X%02X%02X %02X%02X%02X%02X)"
+              % (header[0], header[1], header[2], header[3],
+                 header[4], header[5], header[6], header[7],
+                 header[8], header[9], header[10], header[11]))
+      else:
+        print()
+
+      offset += chunk_sz
+
+    print("     %10u            %7u         End" % (FH.tell(), offset))
+
+    if total_blks != offset:
+      print("The header said we should have %u output blocks, but we saw %u"
+            % (total_blks, offset))
+
+    junk_len = len(FH.read())
+    if junk_len:
+      print("There were %u bytes of extra data at the end of the file."
+            % (junk_len))
+
+  sys.exit(0)
+
+if __name__ == "__main__":
+  main()
diff --git a/ext4_utils/uuid.c b/ext4_utils/uuid.c
index d518476..33d2494 100644
--- a/ext4_utils/uuid.c
+++ b/ext4_utils/uuid.c
@@ -15,7 +15,12 @@
  */
 
 #include <string.h>
+
+#ifdef USE_MINGW
+#include <winsock2.h>
+#else
 #include <arpa/inet.h>
+#endif
 
 #include "ext4_utils.h"
 #include "sha1.h"
diff --git a/libpagemap/include/pagemap/pagemap.h b/libpagemap/include/pagemap/pagemap.h
index 09ff29d..25c6161 100644
--- a/libpagemap/include/pagemap/pagemap.h
+++ b/libpagemap/include/pagemap/pagemap.h
@@ -129,10 +129,10 @@
                              unsigned long low, unsigned long hi,
                              uint64_t **range_out, size_t *len);
 
-#define _BITS(x, offset, bits) (((x) >> offset) & ((1LL << ((bits) + 1)) - 1))
+#define _BITS(x, offset, bits) (((x) >> offset) & ((1LL << (bits)) - 1))
 
 #define PM_PAGEMAP_PRESENT(x)     (_BITS(x, 63, 1))
-#define PM_PAGEMAP_SWAPPED(x)     (!_BITS(x, 62, 1))
+#define PM_PAGEMAP_SWAPPED(x)     (_BITS(x, 62, 1))
 #define PM_PAGEMAP_SHIFT(x)       (_BITS(x, 55, 6))
 #define PM_PAGEMAP_PFN(x)         (_BITS(x, 0, 55))
 #define PM_PAGEMAP_SWAP_OFFSET(x) (_BITS(x, 5, 50))
diff --git a/libpagemap/pm_map.c b/libpagemap/pm_map.c
index f683ba6..2d5c2f9 100644
--- a/libpagemap/pm_map.c
+++ b/libpagemap/pm_map.c
@@ -83,10 +83,6 @@
     pm_memusage_zero(&ws);
     
     for (i = 0; i < len; i++) {
-        if (!PM_PAGEMAP_PRESENT(pagemap[i]) ||
-            PM_PAGEMAP_SWAPPED(pagemap[i]))
-            continue;
-
         error = pm_kernel_flags(map->proc->ker, PM_PAGEMAP_PFN(pagemap[i]),
                                 &flags);
         if (error) goto out;
@@ -99,6 +95,7 @@
         if (error) goto out;
 
         ws.vss += map->proc->ker->pagesize;
+        if( PM_PAGEMAP_SWAPPED(pagemap[i]) ) continue;
         ws.rss += (count >= 1) ? (map->proc->ker->pagesize) : (0);
         ws.pss += (count >= 1) ? (map->proc->ker->pagesize / count) : (0);
         ws.uss += (count == 1) ? (map->proc->ker->pagesize) : (0);
diff --git a/libpagemap/pm_process.c b/libpagemap/pm_process.c
index b3c077e..dddff01 100644
--- a/libpagemap/pm_process.c
+++ b/libpagemap/pm_process.c
@@ -122,7 +122,7 @@
         free(range);
         *range_out = NULL;
         return 0;
-    } else if (error < 0 || (error > 0 && error < numpages * sizeof(uint64_t))) {
+    } else if (error < 0 || (error > 0 && error < (int)(numpages * sizeof(uint64_t)))) {
         error = (error < 0) ? errno : -1;
         free(range);
         return error;
@@ -210,7 +210,7 @@
 }
 
 #define INITIAL_MAPS 10
-#define MAX_LINE 256
+#define MAX_LINE 1024
 #define MAX_PERMS 5
 
 /* 
diff --git a/showmap/showmap.c b/showmap/showmap.c
index 5c4a26f..bb359f6 100644
--- a/showmap/showmap.c
+++ b/showmap/showmap.c
@@ -56,9 +56,7 @@
     if (line[name_pos]) {
         strlcpy(name, line + name_pos, sizeof(name));
     } else {
-        if ((start >= 0x10000000) && (start < 0x40000000)) {
-            strlcpy(name, "[stack]", sizeof(name));
-        } else if (prev && start == prev->end && is_library(prev->name)) {
+        if (prev && start == prev->end && is_library(prev->name)) {
             // anonymous mappings immediately adjacent to shared libraries
             // usually correspond to the library BSS segment, so we use the
             // library's own name
diff --git a/su/su.c b/su/su.c
index b87cece..f87f073 100644
--- a/su/su.c
+++ b/su/su.c
@@ -44,6 +44,13 @@
     struct passwd *pw;
     int uid, gid, myuid;
 
+    /* Until we have something better, only root and the shell can use su. */
+    myuid = getuid();
+    if (myuid != AID_ROOT && myuid != AID_SHELL) {
+        fprintf(stderr,"su: uid %d not allowed to su\n", myuid);
+        return 1;
+    }
+
     if(argc < 2) {
         uid = gid = 0;
     } else {
@@ -57,13 +64,6 @@
         }
     }
 
-    /* Until we have something better, only root and the shell can use su. */
-    myuid = getuid();
-    if (myuid != AID_ROOT && myuid != AID_SHELL) {
-        fprintf(stderr,"su: uid %d not allowed to su\n", myuid);
-        return 1;
-    }
-    
     if(setgid(gid) || setuid(uid)) {
         fprintf(stderr,"su: permission denied\n");
         return 1;
diff --git a/tests/bionic/libc/Android.mk b/tests/bionic/libc/Android.mk
index 5dcf130..52ef01e 100644
--- a/tests/bionic/libc/Android.mk
+++ b/tests/bionic/libc/Android.mk
@@ -61,6 +61,7 @@
 # First, the tests in 'common'
 
 sources := \
+    common/bench_stdio.c \
     common/test_clock.c \
     common/test_cpu_set.c \
     common/test_drand48.c \
@@ -252,4 +253,31 @@
 EXTRA_CFLAGS := -mandroid
 #$(call device-test, $(sources))
 
+# NOTE: We build both a shared and static version of bench_pthread.
+# the shared version will use the target device's C library, while
+# the static one will use the current build product implementation.
+# This is ideal to quantify pthread optimizations.
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := common/bench_pthread.c
+LOCAL_MODULE := bench_pthread_shared
+LOCAL_MODULE_TAGS := tests
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := common/bench_pthread.c
+LOCAL_MODULE := bench_pthread_static
+LOCAL_MODULE_TAGS := tests
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_STATIC_LIBRARIES := libc
+include $(BUILD_EXECUTABLE)
+
+ifeq ($(HOST_OS),linux)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := common/bench_pthread.c
+LOCAL_MODULE := bench_pthread
+LOCAL_LDLIBS += -lpthread -lrt
+LOCAL_MODULE_TAGS := tests
+include $(BUILD_HOST_EXECUTABLE)
+endif
+
 endif  # BIONIC_TESTS
diff --git a/tests/bionic/libc/common/bench_pthread.c b/tests/bionic/libc/common/bench_pthread.c
new file mode 100644
index 0000000..4e46f61
--- /dev/null
+++ b/tests/bionic/libc/common/bench_pthread.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* This program is used to benchmark various pthread operations
+ * Note that we want to be able to build it with GLibc, both on
+ *  a Linux host and an Android device. For example, on ARM, one
+ * can build it manually with:
+ *
+ *     arm-linux-none-gnueabi-gcc -static -o bench_pthread_gnueabi \
+ *           bench_pthread.c -O2 -lpthread -lrt
+ */
+#define _GNU_SOURCE 1
+#include <time.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <limits.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define S(x)  S_(x)
+#define S_(x) #x
+
+#define C(x,y)  C_(x,y)
+#define C_(x,y) x ## y
+
+#ifndef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER  PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
+#endif
+
+#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER  PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+#endif
+
+static int64_t now_ns(void)
+{
+    struct timespec ts;
+    /* NOTE: get thread-specific CPU-time clock to ensure
+     *       we don't measure stuff like kernel thread preemptions
+     *       that might happen during the benchmark
+     */
+    clock_gettime(CLOCK_THREAD_CPUTIME_ID,&ts);
+    return ts.tv_sec*1000000000LL + ts.tv_nsec;
+}
+
+#define SUBCOUNT   10000
+#define MAX_STATS  1000000
+
+/* Maximum time we'll wait for a single bench run */
+#define MAX_WAIT_MS  1000
+
+static int64_t  stats[MAX_STATS];
+
+static int
+compare_stats(const void* a, const void* b)
+{
+    uint64_t sa = *(const uint64_t*)a;
+    uint64_t sb = *(const uint64_t*)b;
+    if (sa < sb)
+        return -1;
+    if (sa > sb)
+        return +1;
+    else
+        return 0;
+}
+
+static void
+filter_stats(int count, const char* statement)
+{
+    int64_t  min, max, avg, median;
+
+    /* sort the array in increasing order */
+    qsort(stats, count, sizeof(stats[0]), compare_stats);
+
+    /* trim 10% to remove outliers */
+    int min_index = count*0.05;
+    int max_index = count - min_index;
+    if (max_index >= count)
+        max_index = count-1;
+
+    count = (max_index - min_index)+1;
+
+    /* the median is the center item */
+    median = stats[(min_index+max_index)/2];
+
+    /* the minimum is the first, the max the last */
+    min = stats[min_index];
+    max = stats[max_index];
+
+    /* compute the average */
+    int nn;
+    int64_t  total = 0;
+    for (nn = min_index; nn <= max_index; nn++) {
+        total += stats[nn];
+    }
+
+    printf("BENCH: %5.1f %5.1f %5.1f, %s\n",
+           min*1./SUBCOUNT,
+           max*1./SUBCOUNT,
+           median*1./SUBCOUNT,
+           statement);
+    if (0) {
+        for (nn = min_index; nn <= max_index; nn++) {
+            printf(" %lld", (long long)stats[nn]);
+        }
+        printf("\n");
+    }
+}
+
+#define BENCH_COUNT(stmnt,total) do { \
+        int64_t  count = total; \
+        int      num_stats = 0; \
+        int64_t  bench_start = now_ns(); \
+        while (num_stats < MAX_STATS && count >= SUBCOUNT) { \
+            int      tries = SUBCOUNT; \
+            int64_t  sub_start = now_ns(); \
+            count -= tries; \
+            for ( ; tries > 0; tries-- ) {\
+                stmnt;\
+            }\
+            int64_t  sub_end = now_ns(); \
+            stats[num_stats++] = sub_end - sub_start; \
+            if (sub_end - bench_start >= MAX_WAIT_MS*1e6) \
+                break; \
+        } \
+        filter_stats(num_stats, #stmnt); \
+    } while (0)
+
+#define DEFAULT_COUNT 10000000
+
+#define BENCH(stmnt) BENCH_COUNT(stmnt,DEFAULT_COUNT)
+
+/* Will be called by pthread_once() for benchmarking */
+static void _dummy_init(void)
+{
+    /* nothing */
+}
+
+/* Used when creating the key */
+static void key_destroy(void* param)
+{
+    /* nothing */
+}
+
+int main(void)
+{
+    pthread_once_t  once = PTHREAD_ONCE_INIT;
+    pthread_once(&once, _dummy_init);
+
+    pthread_key_t   key;
+    pthread_key_create(&key, key_destroy);
+    pthread_setspecific(key, (void*)(int)100);
+
+    BENCH(getpid());
+    BENCH(pthread_self());
+    BENCH(pthread_getspecific(key));
+    BENCH(pthread_once(&once, _dummy_init));
+
+    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+    BENCH(pthread_mutex_lock(&mutex); pthread_mutex_unlock(&mutex));
+
+    pthread_mutex_t errorcheck_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER;
+    BENCH(pthread_mutex_lock(&errorcheck_mutex); pthread_mutex_unlock(&errorcheck_mutex));
+
+    pthread_mutex_t recursive_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
+    BENCH(pthread_mutex_lock(&recursive_mutex); pthread_mutex_unlock(&recursive_mutex));
+
+	/* TODO: Benchmark pshared mutexes */
+
+    sem_t semaphore;
+    int dummy;
+    sem_init(&semaphore, 1, 1);
+    BENCH(sem_getvalue(&semaphore,&dummy));
+    BENCH(sem_wait(&semaphore); sem_post(&semaphore));
+    return 0;
+}
diff --git a/tests/bionic/libc/common/bench_stdio.c b/tests/bionic/libc/common/bench_stdio.c
new file mode 100644
index 0000000..4c19bf1
--- /dev/null
+++ b/tests/bionic/libc/common/bench_stdio.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* This program tries to benchmark stdio operations like fread() and
+ * fwrite() with various chunk sizes. We always read/write from /dev/zero
+ * to ensure that disk speed and caching don't change our results.
+ *
+ * We really do this to measure improvements in the low-level stdio
+ * features.
+ */
+ 
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <errno.h>
+
+static char buffer[1024*1024];
+
+/* Return current time in milli-seconds, as a double */
+static double
+now_ms(void)
+{
+    struct timespec  ts;
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+    return ts.tv_sec*1000. + ts.tv_nsec*1e-6;
+}
+
+void read_file(FILE* fp, int chunkSize)
+{
+    int totalSize = sizeof(buffer);
+    for ( ; totalSize > 0; totalSize -= chunkSize) {
+        fread(buffer, 1, chunkSize, fp);
+    }
+}
+
+void write_file(FILE* fp, int chunkSize)
+{
+    int totalSize = sizeof(buffer);
+    for ( ; totalSize > 0; totalSize -= chunkSize) {
+        fwrite(buffer, 1, chunkSize, fp);
+    }
+}
+
+#define  BENCH(op,...) \
+    do { \
+	double  time_ms = now_ms(); \
+	op ; \
+	time_ms = now_ms() - time_ms; \
+	double  bandwidth = sizeof(buffer)*1000./1024./time_ms; \
+	printf("bench %-30s %8.2f ms  (%.1f KB/s) \n", #op, time_ms, bandwidth ); \
+    } while (0)
+
+int main(void)
+{
+    FILE* fp = fopen("/dev/zero", "rw");
+
+    if (fp == NULL) {
+	fprintf(stderr,"Could not open /dev/zero: %s\n", strerror(errno));
+	return 1;
+    }
+
+    BENCH(read_file(fp,1));
+    BENCH(read_file(fp,2));
+    BENCH(read_file(fp,3));
+    BENCH(read_file(fp,4));
+    BENCH(read_file(fp,8));
+    BENCH(read_file(fp,16));
+    BENCH(read_file(fp,32));
+    BENCH(read_file(fp,64));
+    BENCH(read_file(fp,256));
+    BENCH(read_file(fp,1024));
+    BENCH(read_file(fp,4096));
+    BENCH(read_file(fp,16384));
+    BENCH(read_file(fp,65536));
+
+    BENCH(write_file(fp,1));
+    BENCH(write_file(fp,2));
+    BENCH(write_file(fp,3));
+    BENCH(write_file(fp,4));
+    BENCH(write_file(fp,8));
+    BENCH(write_file(fp,16));
+    BENCH(write_file(fp,32));
+    BENCH(write_file(fp,64));
+    BENCH(write_file(fp,256));
+    BENCH(write_file(fp,1024));
+    BENCH(write_file(fp,4096));
+    BENCH(write_file(fp,16384));
+    BENCH(write_file(fp,65536));
+
+    fclose(fp);
+    return 0;
+}
diff --git a/tests/framebuffer/refresh.c b/tests/framebuffer/refresh.c
index 43dc7cf..38e7871 100644
--- a/tests/framebuffer/refresh.c
+++ b/tests/framebuffer/refresh.c
@@ -67,12 +67,10 @@
     if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
         return -errno;    
     
-    int refreshRate = 1000000000000000LLU / 
-            (
-          (uint64_t)( info.upper_margin + info.lower_margin + info.yres ) 
-                  * ( info.left_margin  + info.right_margin + info.xres )
-                  * info.pixclock
-            );
+    uint64_t denominator = (uint64_t)( info.upper_margin + info.lower_margin + info.yres )
+                         * ( info.left_margin  + info.right_margin + info.xres )
+                         * info.pixclock;
+    int refreshRate = denominator ? (1000000000000000LLU / denominator) : 0;
     
     float xdpi = (info.xres * 25.4f) / info.width; 
     float ydpi = (info.yres * 25.4f) / info.height;
diff --git a/tests/fstest/perm_checker.conf b/tests/fstest/perm_checker.conf
index 25f1b5f..580eb85 100644
--- a/tests/fstest/perm_checker.conf
+++ b/tests/fstest/perm_checker.conf
@@ -16,8 +16,8 @@
 /data/dalvik-cache/... 400 744 root 19999 root 19999
 /data/data 701 771 system system system system
 /data/data/... 000 775 system 19999 system 19999
-/data/local/ 771 771 shell shell shell shell
-/data/local/tmp/ 771 1771 shell shell shell shell
+/data/local/ 751 751 root root root root
+/data/local/tmp/ 771 771 shell shell shell shell
 /data/lost+found/ 700 770 root root root root
 /data/misc/ 1711 1771 root system root misc
 /data/misc/akmd_set.txt 600 640 root compass compass compass
diff --git a/tests/iptables/qtaguid/Android.mk b/tests/iptables/qtaguid/Android.mk
index 5eba34f..cf0a2ba 100644
--- a/tests/iptables/qtaguid/Android.mk
+++ b/tests/iptables/qtaguid/Android.mk
@@ -19,7 +19,6 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE_TAGS := tests
 LOCAL_MODULE := socketTag
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativestresstest
 LOCAL_SRC_FILES := socketTag.cpp
 LOCAL_SHARED_LIBRARIES += libcutils libutils
 LOCAL_STATIC_LIBRARIES += libtestUtil
diff --git a/tests/iptables/qtaguid/socketTag.cpp b/tests/iptables/qtaguid/socketTag.cpp
index 68d9257..fb7ecdc 100644
--- a/tests/iptables/qtaguid/socketTag.cpp
+++ b/tests/iptables/qtaguid/socketTag.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  *
  */
+
 /*
  * This socket tagging test is to ensure that the
  * netfilter/xt_qtaguid kernel module somewhat behaves as expected
@@ -24,6 +25,7 @@
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <gtest/gtest.h>
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <string>
@@ -32,15 +34,15 @@
 #include <utils/Log.h>
 #include <testUtil.h>
 
+namespace android {
 
 class SockInfo {
 public:
-        SockInfo()
-                : fd(-1), addr(NULL) {};
-        int setup(uint64_t tag);
-        bool checkTag(uint64_t tag, uid_t uid);
-        int fd;
-        void *addr;
+    SockInfo() : fd(-1), addr(NULL) {};
+    int setup(uint64_t tag);
+    bool checkTag(uint64_t tag, uid_t uid);
+    int fd;
+    void *addr;
 };
 
 
@@ -90,6 +92,7 @@
     close(param_fd);
     return res;
 }
+
 /*----------------------------------------------------------------*/
 int SockInfo::setup(uint64_t tag) {
     fd = socket(AF_INET, SOCK_STREAM, 0);
@@ -180,528 +183,217 @@
     return pos != NULL;
 }
 
-/*----------------------------------------------------------------*/
-int testSocketTagging(void) {
-    SockInfo sock0;
-    SockInfo sock1;
-    int res;
-    int total_errors = 0;
-    int ctrl_fd = -1;
-    int dev_fd = -1;
-    const uint64_t invalid_tag1 = 0x0000000100000001llu;
-    uint64_t valid_tag1;
-    uint64_t valid_tag2;
-    uint64_t max_uint_tag = 0xffffffff00000000llu;
-    uid_t fake_uid;
-    uid_t fake_uid2;
-    const char *test_name;
-    uid_t my_uid = getuid();
-    pid_t my_pid = getpid();
 
-    srand48(my_pid * my_uid);
-    /* Adjust fake UIDs and tags so that multiple instances can run in parallel. */
-    fake_uid = testRand();
-    fake_uid2 = testRand();
-    valid_tag1 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
-    valid_tag2 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
-    max_uint_tag = 1llu << 63 | (((uint64_t)my_pid << 48) ^ max_uint_tag);
-    testSetLogCatTag(LOG_TAG);
+class SocketTaggingTest : public ::testing::Test {
+protected:
+    virtual void SetUp() {
+        ctrl_fd = -1;
+        dev_fd = -1;
+        my_uid = getuid();
+        my_pid = getpid();
+        srand48(my_pid * my_uid);
+        // Adjust fake UIDs and tags so that multiple instances can run in parallel.
+        fake_uid = testRand();
+        fake_uid2 = testRand();
+        valid_tag1 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
+        valid_tag2 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
+        valid_tag2 &= 0xffffff00ffffffffllu;  // Leave some room to make counts visible.
+        testPrintI("* start: pid=%lu uid=%lu uid1=0x%lx/%lu uid2=0x%lx/%lu"
+                   " tag1=0x%llx/%llu tag2=0x%llx/%llu",
+                   my_pid, my_uid, fake_uid, fake_uid, fake_uid2, fake_uid2,
+                   valid_tag1, valid_tag1, valid_tag2, valid_tag2);
+        max_uint_tag = 0xffffffff00000000llu;
+        max_uint_tag = 1llu << 63 | (((uint64_t)my_pid << 48) ^ max_uint_tag);
 
-    testPrintI("** %s ** ============================", __FUNCTION__);
-    testPrintI("* start: pid=%lu uid=%lu uid1=0x%lx/%lu uid2=0x%lx/%lu"
-               " tag1=0x%llx/%llu tag2=0x%llx/%llu",
-               my_pid, my_uid, fake_uid, fake_uid, fake_uid2, fake_uid2,
-               valid_tag1, valid_tag1, valid_tag2, valid_tag2);
-
-    // ---------------
-    test_name = "kernel has qtaguid";
-    testPrintI("* test: %s ", test_name);
-    ctrl_fd = openCtrl();
-    if (ctrl_fd < 0) {
-        testPrintE("qtaguid ctrl open failed: %s", strerror(errno));
-        total_errors++;
-        goto done;
-    }
-    close(ctrl_fd);
-    dev_fd = open("/dev/xt_qtaguid", O_RDONLY);
-    if (dev_fd < 0) {
-        testPrintE("qtaguid dev open failed: %s", strerror(errno));
-        total_errors++;
-    }
-    // ---------------
-    test_name = "delete command doesn't fail";
-    testPrintI("* test: %s", test_name);
-    res = doCtrlCommand("d 0 %u", fake_uid);
-    if (res < 0) {
-            testPrintE("! %s: Unexpected results", test_name);
-            total_errors++;
-    }
-
-    res = doCtrlCommand("d 0 %u", fake_uid2);
-    if (res < 0) {
-            testPrintE("! %s: Unexpected results", test_name);
-            total_errors++;
-    }
-
-    res = doCtrlCommand("d 0 %u", my_uid);
-    if (res < 0) {
-            testPrintE("! %s: Unexpected results", test_name);
-            total_errors++;
-    }
-    // ---------------
-    test_name = "setup sock0 and addr via tag";
-    testPrintI("* test: %s", test_name);
-    if (sock0.setup(valid_tag1) < 0) {
-        testPrintE("socket setup failed: %s", strerror(errno));
-        total_errors++;
-        goto done;
-
-    }
-    // ---------------
-    test_name = "setup sock1 and addr via tag";
-    testPrintI("* test: %s", test_name);
-    if (sock1.setup(valid_tag1) < 0) {
-        testPrintE("socket setup failed: %s", strerror(errno));
-        total_errors++;
-        goto done;
-    }
-    // ---------------
-    test_name = "insufficient args. Expected failure";
-    testPrintI("* test: %s", test_name);
-    res = doCtrlCommand("t");
-    if (res > 0) {
-        testPrintE("! %s: Unexpected results", test_name);
-        total_errors++;
-    }
-
-    // ---------------
-    test_name = "bad command. Expected failure";
-    testPrintI("* test: %s", test_name);
-    res = doCtrlCommand("?");
-    if (res > 0) {
-            testPrintE("! %s: Unexpected results", test_name);
-        total_errors++;
-    }
-
-    // ---------------
-    test_name = "no tag, no uid";
-    testPrintI("* test: %s", test_name);
-    res = doCtrlCommand("t %d", sock0.fd);
-    if (res < 0) {
-        testPrintE("! %s: Unexpected results", test_name);
-        total_errors++;
-    }
-    if (!sock0.checkTag(0, my_uid)) {
-        testPrintE("! %s: Unexpected results: tag not found", test_name);
-        total_errors++;
-    }
-
-    // ---------------
-    test_name = "invalid tag. Expected failure";
-    testPrintI("* test: %s", test_name);
-    res = doCtrlCommand("t %d %llu", sock0.fd, invalid_tag1);
-    if (res > 0) {
-        testPrintE("! %s: Unexpected results", test_name);
-        total_errors++;
-    }
-    if (sock0.checkTag(invalid_tag1, my_uid)) {
-        testPrintE("! %s: Unexpected results: tag should not be there", test_name);
-        total_errors++;
-    }
-
-    // ---------------
-    test_name = "valid tag with no uid";
-    testPrintI("* test: %s", test_name);
-    res = doCtrlCommand("t %d %llu", sock0.fd, valid_tag1);
-    if (res < 0) {
-        testPrintE("! %s: Unexpected results", test_name);
-        total_errors++;
-    }
-    if (!sock0.checkTag(valid_tag1, my_uid)) {
-        testPrintE("! %s: Unexpected results: tag not found", test_name);
-        total_errors++;
-    }
-    // ---------------
-    test_name = "valid untag";
-    testPrintI("* test: %s", test_name);
-    res = doCtrlCommand("u %d", sock0.fd);
-    if (res < 0) {
-        testPrintE("! %s: Unexpected results", test_name);
-        total_errors++;
-    }
-    if (sock0.checkTag(valid_tag1, my_uid)) {
-        testPrintE("! %s: Unexpected results: tag not removed", test_name);
-        total_errors++;
-    }
-
-    // ---------------
-    test_name = "valid 1st tag";
-    testPrintI("* test: %s", test_name);
-    res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid);
-    if (res < 0) {
-        testPrintE("! %s: Unexpected results", test_name);
-        total_errors++;
-    }
-    if (!sock0.checkTag(valid_tag2, fake_uid)) {
-        testPrintE("! %s: Unexpected results: tag not found", test_name);
-        total_errors++;
-    }
-
-    // ---------------
-    test_name = "valid re-tag";
-    testPrintI("* test: %s", test_name);
-    res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid);
-    if (res < 0) {
-        testPrintE("! %s: Unexpected results", test_name);
-        total_errors++;
-    }
-    if (!sock0.checkTag(valid_tag2, fake_uid)) {
-        testPrintE("! %s: Unexpected results: tag not found", test_name);
-        total_errors++;
-    }
-
-    // ---------------
-    test_name = "valid re-tag with acct_tag change";
-    testPrintI("* test: %s", test_name);
-    res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag1, fake_uid);
-    if (res < 0) {
-        testPrintE("! %s: Unexpected results", test_name);
-        total_errors++;
-    }
-    if (!sock0.checkTag(valid_tag1, fake_uid)) {
-        testPrintE("! %s: Unexpected results: tag not found", test_name);
-        total_errors++;
-    }
-
-    // ---------------
-    test_name = "re-tag with uid change";
-    testPrintI("* test: %s", test_name);
-    res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid2);
-    if (res < 0) {
-        testPrintE("! %s: Unexpected results", test_name);
-        total_errors++;
-    }
-    if (!sock0.checkTag(valid_tag2, fake_uid2)) {
-        testPrintE("! %s: Unexpected results: tag not found", test_name);
-        total_errors++;
-    }
-
-    // ---------------
-    test_name = "valid 64bit acct tag";
-    testPrintI("* test: %s", test_name);
-    res = doCtrlCommand("t %d %llu", sock0.fd, max_uint_tag);
-    if (res < 0) {
-        testPrintE("! %s: Unexpected results", test_name);
-        total_errors++;
-    }
-    if (!sock0.checkTag(max_uint_tag, my_uid)) {
-        testPrintE("! %s: Unexpected results: tag not found", test_name);
-        total_errors++;
-    }
-
-    // ---------------
-    test_name = "tag another socket";
-    testPrintI("* test: %s", test_name);
-    res = doCtrlCommand("t %d %llu %u", sock1.fd, valid_tag1, fake_uid2);
-    if (res < 0) {
-        testPrintE("! %s: Unexpected results", test_name);
-        total_errors++;
-    }
-    if (!sock1.checkTag(valid_tag1, fake_uid2)) {
-        testPrintE("! %s: Unexpected results: tag not found", test_name);
-        total_errors++;
-    }
-
-    // ---------------
-    test_name = "valid untag";
-    testPrintI("* test: %s", test_name);
-    res = doCtrlCommand("u %d", sock0.fd);
-    if (res < 0) {
-        testPrintE("! %s: Unexpected results", test_name);
-        total_errors++;
-    }
-    if (sock0.checkTag(max_uint_tag, fake_uid)) {
-        testPrintE("! %s: Unexpected results: tag should not be there", test_name);
-        total_errors++;
-    }
-    if (!sock1.checkTag(valid_tag1, fake_uid2)) {
-        testPrintE("! %s: Unexpected results: tag not found", test_name);
-        total_errors++;
-    }
-    res = doCtrlCommand("u %d", sock1.fd);
-    if (res < 0) {
-        testPrintE("! %s: Unexpected results", test_name);
-        total_errors++;
-    }
-    if (sock1.checkTag(valid_tag1, fake_uid2)) {
-        testPrintE("! %s: Unexpected results: tag should not be there", test_name);
-        total_errors++;
-    }
-
-    // ---------------
-    test_name = "invalid sock0.fd. Expected failure";
-    testPrintI("* test: %s", test_name);
-    close(sock0.fd);
-    res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag1, my_uid);
-    if (res > 0) {
-            testPrintE("! %s: Unexpected results", test_name);
-        total_errors++;
-    }
-    if (sock0.checkTag(valid_tag1, my_uid)) {
-        testPrintE("! %s: Unexpected results: tag should not be there", test_name);
-        total_errors++;
-    }
-
-    // ---------------
-    test_name = "invalid untag. Expected failure";
-    testPrintI("* test: %s", test_name);
-    close(sock1.fd);
-    res = doCtrlCommand("u %d", sock1.fd);
-    if (res > 0) {
-        testPrintE("! %s: Unexpected results", test_name);
-        total_errors++;
-    }
-
-    if (total_errors) {
-        testPrintE("! Errors found");
-    } else {
-        testPrintI("No Errors found");
-    }
-
-done:
-    if (dev_fd >= 0) {
-        close(dev_fd);
-    }
-    if (ctrl_fd >= 0) {
+        testPrintI("kernel has qtaguid");
+        ctrl_fd = openCtrl();
+        ASSERT_GE(ctrl_fd, 0) << "qtaguid ctrl open failed";
         close(ctrl_fd);
-    }
-    return total_errors;
-}
+        dev_fd = open("/dev/xt_qtaguid", O_RDONLY);
+        EXPECT_GE(dev_fd, 0) << "qtaguid dev open failed";
 
-int testTagData(void) {
-    SockInfo sock0;
-    SockInfo sock1;
-    int res;
-    int total_errors = 0;
-    int ctrl_fd = -1;
-    int dev_fd = -1;
-    const uint64_t invalid_tag1 = 0x0000000100000001llu;
-    uint64_t valid_tag1;
-    uint64_t valid_tag2;
-    uint64_t max_uint_tag = 0xffffffff00000000llu;
-    uid_t fake_uid;
-    uid_t fake_uid2;
-    const char *test_name;
-    uid_t my_uid = getuid();
-    pid_t my_pid = getpid();
-    const int max_tags = 5;
+        // We want to clean up any previous faulty test runs.
+        testPrintI("delete command does not fail");
+        EXPECT_GE(doCtrlCommand("d 0 %u", fake_uid), 0) << "Failed to delete fake_uid";
+        EXPECT_GE(doCtrlCommand("d 0 %u", fake_uid2), 0) << "Failed to delete fake_uid2";
+        EXPECT_GE(doCtrlCommand("d 0 %u", my_uid), 0) << "Failed to delete my_uid";
 
-    srand48(my_pid * my_uid);
-    /* Adjust fake UIDs and tags so that multiple instances can run in parallel. */
-    fake_uid = testRand();
-    fake_uid2 = testRand();
-    valid_tag1 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
-    valid_tag2 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
-    valid_tag2 &= 0xffffff00ffffffffllu;  // Leave some room to make counts visible.
-    testSetLogCatTag(LOG_TAG);
-
-    testPrintI("** %s ** ============================", __FUNCTION__);
-    testPrintI("* start: pid=%lu uid=%lu uid1=0x%lx/%lu uid2=0x%lx/%lu"
-               " tag1=0x%llx/%llu tag2=0x%llx/%llu",
-               my_pid, my_uid, fake_uid, fake_uid, fake_uid2, fake_uid2,
-               valid_tag1, valid_tag1, valid_tag2, valid_tag2);
-
-    // ---------------
-    test_name = "kernel has qtaguid";
-    testPrintI("* test: %s ", test_name);
-    ctrl_fd = openCtrl();
-    if (ctrl_fd < 0) {
-        testPrintE("qtaguid ctrl open failed: %s", strerror(errno));
-        return 1;
-    }
-    close(ctrl_fd);
-    dev_fd = open("/dev/xt_qtaguid", O_RDONLY);
-    if (dev_fd < 0) {
-        testPrintE("! %s: qtaguid dev open failed: %s", test_name, strerror(errno));
-        total_errors++;
-    }
-    // ---------------
-    test_name = "delete command doesn't fail";
-    testPrintI("* test: %s", test_name);
-    res = doCtrlCommand("d 0 %u", fake_uid);
-    if (res < 0) {
-            testPrintE("! %s: Unexpected results", test_name);
-            total_errors++;
+        testPrintI("setup sock0 and addr via tag");
+        ASSERT_FALSE(sock0.setup(valid_tag1))  << "socket0 setup failed";
+        testPrintI("setup sock1 and addr via tag");
+        ASSERT_FALSE(sock1.setup(valid_tag1))  << "socket1 setup failed";
     }
 
-    res = doCtrlCommand("d 0 %u", fake_uid2);
-    if (res < 0) {
-            testPrintE("! %s: Unexpected results", test_name);
-            total_errors++;
-    }
+   virtual void TearDown() {
+       if (dev_fd >= 0) {
+           close(dev_fd);
+       }
+       if (ctrl_fd >= 0) {
+           close(ctrl_fd);
+       }
+   }
 
-    res = doCtrlCommand("d 0 %u", my_uid);
-    if (res < 0) {
-            testPrintE("! %s: Unexpected results", test_name);
-            total_errors++;
-    }
+   SockInfo sock0;
+   SockInfo sock1;
+   int ctrl_fd;
+   int dev_fd;
+   uid_t fake_uid;
+   uid_t fake_uid2;
+   uid_t my_uid;
+   pid_t my_pid;
+   uint64_t valid_tag1;
+   uint64_t valid_tag2;
+   uint64_t max_uint_tag;
+   static const uint64_t invalid_tag1 = 0x0000000100000001llu;
+   static const int max_tags = 5;
+};
 
-    // ---------------
-    test_name = "setup sock0 and addr via tag";
-    testPrintI("* test: %s", test_name);
-    if (sock0.setup(valid_tag1)) {
-        testPrintE("socket setup failed: %s", strerror(errno));
-        return 1;
-    }
-    // ---------------
-    test_name = "setup sock1 and addr via tag";
-    testPrintI("* test: %s", test_name);
-    if (sock1.setup(valid_tag1)) {
-        testPrintE("socket setup failed: %s", strerror(errno));
-        return 1;
-    }
-    // ---------------
-    test_name = "setup tag limit";
-    testPrintI("* test: %s ", test_name);
+TEST_F(SocketTaggingTest, TagData) {
+    max_uint_tag = 0xffffffff00000000llu;
     char *max_tags_str;
+
+    testPrintI("setup tag limit");
     asprintf(&max_tags_str, "%d", max_tags);
-    res = writeModuleParam("max_sock_tags", max_tags_str);
-    if (res < 0) {
-        testPrintE("! %s: Unexpected results", test_name);
-        free(max_tags_str);
-        return 1;
-    }
+    ASSERT_GE(writeModuleParam("max_sock_tags", max_tags_str), 0) << "Failed to setup tag limit";
 
-    // ---------------
-    test_name = "tag quota reach limit";
-    testPrintI("* test: %s", test_name);
+    testPrintI("tag quota reach limit");
     for (int cnt = 0; cnt < max_tags; cnt++ ) {
-        uint64_t new_tag = valid_tag2 + ((uint64_t)cnt << 32);
-        res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
-        if (res < 0) {
-                testPrintE("! %s: Unexpected results", test_name);
-                total_errors++;
-        }
-        if (!sock0.checkTag(new_tag, fake_uid2)) {
-                testPrintE("! %s: Unexpected results: tag not found", test_name);
-                total_errors++;
-        }
-    }
-    test_name = "tag quota go over limit";
-    testPrintI("* test: %s", test_name);
-    {
-        uint64_t new_tag = valid_tag2 + ((uint64_t)max_tags << 32);
-        res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
-        if (res > 0) {
-                testPrintE("! %s: Unexpected results", test_name);
-                total_errors++;
-        }
-        if (!sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32), fake_uid2)) {
-                testPrintE("! %s: Unexpected results: tag not found", test_name);
-                total_errors++;
-        }
+        uint64_t tag = valid_tag2 + ((uint64_t)cnt << 32);
+        EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, tag , fake_uid2), 0)
+            << "Tagging within limit failed";
+        EXPECT_TRUE(sock0.checkTag(tag, fake_uid2))<<  "Unexpected results: tag not found";
     }
 
-    // ---------------
-    test_name = "valid untag";
-    testPrintI("* test: %s", test_name);
-    res = doCtrlCommand("u %d", sock0.fd);
-    if (res < 0) {
-        testPrintE("! %s: Unexpected results", test_name);
-        total_errors++;
-    }
-    if (sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32), fake_uid2)) {
-        testPrintE("! %s: Unexpected results: tag should not be there", test_name);
-        total_errors++;
-    }
+    testPrintI("tag quota go over limit");
+    uint64_t new_tag = valid_tag2 + ((uint64_t)max_tags << 32);
+    EXPECT_LT(doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2), 0);
+    EXPECT_TRUE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32),
+                               fake_uid2)) << "Unexpected results: tag not found";
 
-    // ---------------
-    test_name = "tag after untag shouldn't free up max tags";
-    testPrintI("* test: %s", test_name);
-    {
-        uint64_t new_tag = valid_tag2 + ((uint64_t)max_tags << 32);
-        res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
-        if (res > 0) {
-                testPrintE("! %s: Unexpected results", test_name);
-                total_errors++;
-        }
-        if (sock0.checkTag(valid_tag2 + ((uint64_t)max_tags << 32), fake_uid2)) {
-            testPrintE("! %s: Unexpected results: tag should not be there", test_name);
-            total_errors++;
-        }
-    }
+    testPrintI("valid untag");
+    EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
+    EXPECT_FALSE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32), fake_uid2))
+        << "Untagged tag should not be there";
 
-    // ---------------
-    test_name = "delete one tag";
-    testPrintI("* test: %s", test_name);
-    {
-            uint64_t new_tag = valid_tag2 + (((uint64_t)max_tags / 2) << 32);
-            res = doCtrlCommand("d %llu %u", new_tag, fake_uid2);
-            if (res < 0) {
-                    testPrintE("! %s: Unexpected results", test_name);
-                    total_errors++;
-            }
-    }
+    testPrintI("tag after untag should not free up max tags");
+    uint64_t new_tag2 = valid_tag2 + ((uint64_t)max_tags << 32);
+    EXPECT_LT(doCtrlCommand("t %d %llu %u", sock0.fd, new_tag2 , fake_uid2), 0);
+    EXPECT_FALSE(sock0.checkTag(valid_tag2 + ((uint64_t)max_tags << 32), fake_uid2))
+        << "Tag should not be there";
 
-    // ---------------
-    test_name = "2 tags after 1 delete pass/fail";
-    testPrintI("* test: %s", test_name);
-    {
-        uint64_t new_tag;
-        new_tag = valid_tag2 + (((uint64_t)max_tags + 1 ) << 32);
-        res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
-        if (res < 0) {
-                testPrintE("! %s: Unexpected results", test_name);
-                total_errors++;
-        }
-        if (!sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 1) << 32), fake_uid2)) {
-            testPrintE("! %s: Unexpected results: tag not found", test_name);
-            total_errors++;
-        }
+    testPrintI("delete one tag");
+    uint64_t new_tag3 = valid_tag2 + (((uint64_t)max_tags / 2) << 32);
+    EXPECT_GE(doCtrlCommand("d %llu %u", new_tag3, fake_uid2), 0);
 
-        new_tag = valid_tag2 + (((uint64_t)max_tags + 2 ) << 32);
-        res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
-        if (res > 0) {
-                testPrintE("! %s: Unexpected results", test_name);
-                total_errors++;
-        }
-        if (sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 2) << 32), fake_uid2)) {
-            testPrintE("! %s: Unexpected results: tag should not be there", test_name);
-            total_errors++;
-        }
-    }
+    testPrintI("2 tags after 1 delete pass/fail");
+    uint64_t new_tag4;
+    new_tag4 = valid_tag2 + (((uint64_t)max_tags + 1 ) << 32);
+    EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, new_tag4 , fake_uid2), 0);
+    EXPECT_TRUE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 1) << 32), fake_uid2))
+        << "Tag not found";
+    new_tag4 = valid_tag2 + (((uint64_t)max_tags + 2 ) << 32);
+    EXPECT_LT(doCtrlCommand("t %d %llu %u", sock0.fd, new_tag4 , fake_uid2), 0);
+    EXPECT_FALSE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 2) << 32), fake_uid2))
+        << "Tag should not be there";
 
     /* TODO(jpa): test tagging two different sockets with same tags and
      * check refcounts  the tag_node should be +2
      */
-
-    // ---------------
-    if (total_errors) {
-        testPrintE("! Errors found");
-    } else {
-        testPrintI("No Errors found");
-    }
-
-done:
-    if (dev_fd >= 0) {
-        close(dev_fd);
-    }
-    if (ctrl_fd >= 0) {
-        close(ctrl_fd);
-    }
-    return total_errors;
 }
 
-/*----------------------------------------------------------------*/
-
-int main(int argc, char *argv[]) {
-    int res = 0;
-    res += testTagData();
-    res += testSocketTagging();
-    if (res) {
-        testPrintE("!! %d Errors found", res);
-    } else {
-        testPrintE("No Errors found");
-    }
-    return res;
+TEST_F(SocketTaggingTest, InsufficientArgsFails) {
+    // Insufficient args. Expected failure
+    EXPECT_LE(doCtrlCommand("t"), 0) << "Insufficient args, should fail.";
 }
+
+TEST_F(SocketTaggingTest, BadCommandFails) {
+    // Bad command. Expected failure";
+    EXPECT_LE(doCtrlCommand("?"), 0) << "Bad command, should fail";
+}
+
+TEST_F(SocketTaggingTest, NoTagNoUid) {
+    // no tag, no uid
+    EXPECT_GE(doCtrlCommand("t %d", sock0.fd), 0);
+    ASSERT_TRUE(sock0.checkTag(0, my_uid))  << "Tag not found";
+}
+
+TEST_F(SocketTaggingTest, InvalidTagFail) {
+    // Invalid tag. Expected failure
+    EXPECT_LE(doCtrlCommand("t %d %llu", sock0.fd, invalid_tag1), 0);
+    ASSERT_FALSE(sock0.checkTag(invalid_tag1, my_uid)) << "Tag should not be there";
+}
+
+TEST_F(SocketTaggingTest, ValidTagWithNoUid) {
+    // Valid tag with no uid
+    EXPECT_GE(doCtrlCommand("t %d %llu", sock0.fd, valid_tag1), 0);
+    EXPECT_TRUE(sock0.checkTag(valid_tag1, my_uid)) << "Tag not found";
+}
+
+TEST_F(SocketTaggingTest, ValidUntag) {
+    // Valid untag
+    EXPECT_GE(doCtrlCommand("t %d %llu", sock0.fd, valid_tag1), 0);
+    EXPECT_TRUE(sock0.checkTag(valid_tag1, my_uid)) << "Tag not found";
+    EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
+    EXPECT_FALSE(sock0.checkTag(valid_tag1, my_uid)) << "Tag should be removed";
+}
+
+TEST_F(SocketTaggingTest, ValidFirsttag) {
+    // Valid 1st tag
+    EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid), 0);
+    EXPECT_TRUE(sock0.checkTag(valid_tag2, fake_uid)) << "Tag not found.";
+}
+
+TEST_F(SocketTaggingTest, ValidReTag) {
+    // Valid re-tag
+    EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid), 0);
+    EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid), 0);
+    EXPECT_TRUE(sock0.checkTag(valid_tag2, fake_uid)) << "Tag not found.";
+}
+
+TEST_F(SocketTaggingTest, ValidReTagWithAcctTagChange) {
+    // Valid re-tag with acct_tag change
+    EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid), 0);
+    EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag1, fake_uid), 0);
+    EXPECT_TRUE(sock0.checkTag(valid_tag1, fake_uid)) << "Tag not found.";
+}
+
+TEST_F(SocketTaggingTest, ReTagWithUidChange) {
+    // Re-tag with uid change
+    EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag1, fake_uid), 0);
+    EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid2), 0);
+}
+
+TEST_F(SocketTaggingTest, Valid64BitAcctTag) {
+    // Valid 64bit acct tag
+    EXPECT_GE(doCtrlCommand("t %d %llu", sock0.fd, max_uint_tag), 0);
+    EXPECT_TRUE(sock0.checkTag(max_uint_tag, my_uid)) << "Tag not found.";
+}
+
+TEST_F(SocketTaggingTest, TagAnotherSocket) {
+    testPrintI("Tag two sockets");
+    EXPECT_GE(doCtrlCommand("t %d %llu", sock0.fd, max_uint_tag), 0);
+    EXPECT_GE(doCtrlCommand("t %d %llu %u", sock1.fd, valid_tag1, fake_uid2), 0);
+    EXPECT_TRUE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag not found.";
+    testPrintI("Untag socket0 of them only.");
+    EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
+    EXPECT_FALSE(sock0.checkTag(max_uint_tag, fake_uid)) << "Tag should not be there";
+    EXPECT_TRUE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag not found";
+    testPrintI("Now untag socket1 as well.");
+    EXPECT_GE(doCtrlCommand("u %d", sock1.fd), 0);
+    EXPECT_FALSE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag should not be there";
+}
+
+TEST_F(SocketTaggingTest, TagInvalidSocketFail) {
+    // Invalid tag. Expected failure
+    close(sock0.fd);
+    EXPECT_LE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag1, my_uid), 0);
+    EXPECT_FALSE(sock0.checkTag(valid_tag1, my_uid)) << "Tag should not be there";
+}
+
+TEST_F(SocketTaggingTest, UntagInvalidSocketFail) {
+    // Invalid untag. Expected failure";
+    close(sock1.fd);
+    EXPECT_LE(doCtrlCommand("u %d", sock1.fd), 0);
+}
+
+}  // namespace android
diff --git a/tests/lib/testUtil/testUtil.c b/tests/lib/testUtil/testUtil.c
index d63fbba..b4edbd6 100644
--- a/tests/lib/testUtil/testUtil.c
+++ b/tests/lib/testUtil/testUtil.c
@@ -150,9 +150,9 @@
     va_start(args, fmt);
     vsnprintf(line, sizeof(line), fmt, args);
     if (stream == stderr) {
-        LOG(LOG_ERROR, logCatTag, "%s", line);
+        ALOG(LOG_ERROR, logCatTag, "%s", line);
     } else {
-        LOG(LOG_INFO, logCatTag, "%s", line);
+        ALOG(LOG_INFO, logCatTag, "%s", line);
     }
     vfprintf(stream, fmt, args);
     fputc('\n', stream);
diff --git a/tests/wifi/stress/wifiLoadScanAssoc.c b/tests/wifi/stress/wifiLoadScanAssoc.c
index 62b179c..17536e4 100644
--- a/tests/wifi/stress/wifiLoadScanAssoc.c
+++ b/tests/wifi/stress/wifiLoadScanAssoc.c
@@ -285,7 +285,7 @@
 
         // Start Supplicant
         randBind(&availCPU, &cpu);
-        if ((rv = wifi_start_supplicant()) != 0) {
+        if ((rv = wifi_start_supplicant(false)) != 0) {
             testPrintE("CPU: %i wifi_start_supplicant() failed, rv: %i\n",
                 cpu, rv);
             exit(21);
@@ -341,7 +341,7 @@
         }
 
         // Start supplicant
-        if ((rv = wifi_start_supplicant()) != 0) {
+        if ((rv = wifi_start_supplicant(false)) != 0) {
             testPrintE("main start supplicant failed, rv: %i", rv);
             exit(26);
         }