Merge "Pass $TERM to the device."
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index 7a7366e..5ca88cb 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -83,5 +83,6 @@
 LOCAL_SRC_FILES := usbtest.cpp usb_linux.cpp util.cpp
 LOCAL_MODULE := usbtest
 LOCAL_CFLAGS := -Werror
+LOCAL_STATIC_LIBRARIES := libbase
 include $(BUILD_HOST_EXECUTABLE)
 endif
diff --git a/fastboot/engine.cpp b/fastboot/engine.cpp
index d4be63b..ac5a17a 100644
--- a/fastboot/engine.cpp
+++ b/fastboot/engine.cpp
@@ -75,13 +75,13 @@
 
 
 
-bool fb_getvar(usb_handle* usb, const std::string& key, std::string* value) {
+bool fb_getvar(Transport* transport, const std::string& key, std::string* value) {
     std::string cmd = "getvar:";
     cmd += key;
 
     char buf[FB_RESPONSE_SZ + 1];
     memset(buf, 0, sizeof(buf));
-    if (fb_command_response(usb, cmd.c_str(), buf)) {
+    if (fb_command_response(transport, cmd.c_str(), buf)) {
       return false;
     }
     *value = buf;
@@ -330,7 +330,7 @@
     queue_action(OP_WAIT_FOR_DISCONNECT, "");
 }
 
-int fb_execute_queue(usb_handle *usb)
+int fb_execute_queue(Transport* transport)
 {
     Action *a;
     char resp[FB_RESPONSE_SZ+1];
@@ -350,25 +350,25 @@
             fprintf(stderr,"%s...\n",a->msg);
         }
         if (a->op == OP_DOWNLOAD) {
-            status = fb_download_data(usb, a->data, a->size);
+            status = fb_download_data(transport, a->data, a->size);
             status = a->func(a, status, status ? fb_get_error() : "");
             if (status) break;
         } else if (a->op == OP_COMMAND) {
-            status = fb_command(usb, a->cmd);
+            status = fb_command(transport, a->cmd);
             status = a->func(a, status, status ? fb_get_error() : "");
             if (status) break;
         } else if (a->op == OP_QUERY) {
-            status = fb_command_response(usb, a->cmd, resp);
+            status = fb_command_response(transport, a->cmd, resp);
             status = a->func(a, status, status ? fb_get_error() : resp);
             if (status) break;
         } else if (a->op == OP_NOTICE) {
             fprintf(stderr,"%s\n",(char*)a->data);
         } else if (a->op == OP_DOWNLOAD_SPARSE) {
-            status = fb_download_data_sparse(usb, reinterpret_cast<sparse_file*>(a->data));
+            status = fb_download_data_sparse(transport, reinterpret_cast<sparse_file*>(a->data));
             status = a->func(a, status, status ? fb_get_error() : "");
             if (status) break;
         } else if (a->op == OP_WAIT_FOR_DISCONNECT) {
-            usb_wait_for_disconnect(usb);
+            transport->WaitForDisconnect();
         } else {
             die("bogus action");
         }
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 9f72c83..a16d7dd 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -55,6 +55,8 @@
 #include "bootimg_utils.h"
 #include "fastboot.h"
 #include "fs.h"
+#include "transport.h"
+#include "usb.h"
 
 #ifndef O_BINARY
 #define O_BINARY 0
@@ -222,16 +224,16 @@
     return -1;
 }
 
-static usb_handle* open_device() {
-    static usb_handle *usb = 0;
+static Transport* open_device() {
+    static Transport* transport = nullptr;
     int announce = 1;
 
-    if(usb) return usb;
+    if (transport) return transport;
 
-    for(;;) {
-        usb = usb_open(match_fastboot);
-        if(usb) return usb;
-        if(announce) {
+    for (;;) {
+        transport = usb_open(match_fastboot);
+        if (transport) return transport;
+        if (announce) {
             announce = 0;
             fprintf(stderr, "< waiting for %s >\n", serial ? serial : "any device");
         }
@@ -597,9 +599,10 @@
     return out_s;
 }
 
-static int64_t get_target_sparse_limit(usb_handle* usb) {
+static int64_t get_target_sparse_limit(Transport* transport) {
     std::string max_download_size;
-    if (!fb_getvar(usb, "max-download-size", &max_download_size) || max_download_size.empty()) {
+    if (!fb_getvar(transport, "max-download-size", &max_download_size) ||
+            max_download_size.empty()) {
         fprintf(stderr, "target didn't report max-download-size\n");
         return 0;
     }
@@ -618,7 +621,7 @@
     return limit;
 }
 
-static int64_t get_sparse_limit(usb_handle* usb, int64_t size) {
+static int64_t get_sparse_limit(Transport* transport, int64_t size) {
     int64_t limit;
 
     if (sparse_limit == 0) {
@@ -627,7 +630,7 @@
         limit = sparse_limit;
     } else {
         if (target_sparse_limit == -1) {
-            target_sparse_limit = get_target_sparse_limit(usb);
+            target_sparse_limit = get_target_sparse_limit(transport);
         }
         if (target_sparse_limit > 0) {
             limit = target_sparse_limit;
@@ -646,22 +649,22 @@
 // Until we get lazy inode table init working in make_ext4fs, we need to
 // erase partitions of type ext4 before flashing a filesystem so no stale
 // inodes are left lying around.  Otherwise, e2fsck gets very upset.
-static bool needs_erase(usb_handle* usb, const char* partition) {
+static bool needs_erase(Transport* transport, const char* partition) {
     std::string partition_type;
-    if (!fb_getvar(usb, std::string("partition-type:") + partition, &partition_type)) {
+    if (!fb_getvar(transport, std::string("partition-type:") + partition, &partition_type)) {
         return false;
     }
     return partition_type == "ext4";
 }
 
-static int load_buf_fd(usb_handle* usb, int fd, struct fastboot_buffer* buf) {
+static int load_buf_fd(Transport* transport, int fd, struct fastboot_buffer* buf) {
     int64_t sz = get_file_size(fd);
     if (sz == -1) {
         return -1;
     }
 
     lseek64(fd, 0, SEEK_SET);
-    int64_t limit = get_sparse_limit(usb, sz);
+    int64_t limit = get_sparse_limit(transport, sz);
     if (limit) {
         sparse_file** s = load_sparse_files(fd, limit);
         if (s == nullptr) {
@@ -680,8 +683,7 @@
     return 0;
 }
 
-static int load_buf(usb_handle *usb, const char *fname,
-        struct fastboot_buffer *buf)
+static int load_buf(Transport* transport, const char *fname, struct fastboot_buffer *buf)
 {
     int fd;
 
@@ -690,7 +692,7 @@
         return -1;
     }
 
-    return load_buf_fd(usb, fd, buf);
+    return load_buf_fd(transport, fd, buf);
 }
 
 static void flash_buf(const char *pname, struct fastboot_buffer *buf)
@@ -713,20 +715,20 @@
     }
 }
 
-static std::vector<std::string> get_suffixes(usb_handle* usb) {
+static std::vector<std::string> get_suffixes(Transport* transport) {
     std::vector<std::string> suffixes;
     std::string suffix_list;
-    if (!fb_getvar(usb, "slot-suffixes", &suffix_list)) {
+    if (!fb_getvar(transport, "slot-suffixes", &suffix_list)) {
         die("Could not get suffixes.\n");
     }
     return android::base::Split(suffix_list, ",");
 }
 
-static std::string verify_slot(usb_handle* usb, const char *slot) {
+static std::string verify_slot(Transport* transport, const char *slot) {
     if (strcmp(slot, "all") == 0) {
         return "all";
     }
-    std::vector<std::string> suffixes = get_suffixes(usb);
+    std::vector<std::string> suffixes = get_suffixes(transport);
     for (const std::string &suffix : suffixes) {
         if (suffix == slot)
             return slot;
@@ -738,17 +740,18 @@
     exit(1);
 }
 
-static void do_for_partition(usb_handle* usb, const char *part, const char *slot, std::function<void(const std::string&)> func, bool force_slot) {
+static void do_for_partition(Transport* transport, const char *part, const char *slot,
+                             std::function<void(const std::string&)> func, bool force_slot) {
     std::string has_slot;
     std::string current_slot;
 
-    if (!fb_getvar(usb, std::string("has-slot:")+part, &has_slot)) {
+    if (!fb_getvar(transport, std::string("has-slot:")+part, &has_slot)) {
         /* If has-slot is not supported, the answer is no. */
         has_slot = "no";
     }
     if (has_slot == "yes") {
         if (!slot || slot[0] == 0) {
-            if (!fb_getvar(usb, "current-slot", &current_slot)) {
+            if (!fb_getvar(transport, "current-slot", &current_slot)) {
                 die("Failed to identify current slot.\n");
             }
             func(std::string(part) + current_slot);
@@ -757,40 +760,43 @@
         }
     } else {
         if (force_slot && slot && slot[0]) {
-             fprintf(stderr, "Warning: %s does not support slots, and slot %s was requested.\n", part, slot);
+             fprintf(stderr, "Warning: %s does not support slots, and slot %s was requested.\n",
+                     part, slot);
         }
         func(part);
     }
 }
 
-/* This function will find the real partition name given a base name, and a slot. If slot is NULL or empty,
- * it will use the current slot. If slot is "all", it will return a list of all possible partition names.
- * If force_slot is true, it will fail if a slot is specified, and the given partition does not support slots.
+/* This function will find the real partition name given a base name, and a slot. If slot is NULL or
+ * empty, it will use the current slot. If slot is "all", it will return a list of all possible
+ * partition names. If force_slot is true, it will fail if a slot is specified, and the given
+ * partition does not support slots.
  */
-static void do_for_partitions(usb_handle* usb, const char *part, const char *slot, std::function<void(const std::string&)> func, bool force_slot) {
+static void do_for_partitions(Transport* transport, const char *part, const char *slot,
+                              std::function<void(const std::string&)> func, bool force_slot) {
     std::string has_slot;
 
     if (slot && strcmp(slot, "all") == 0) {
-        if (!fb_getvar(usb, std::string("has-slot:") + part, &has_slot)) {
+        if (!fb_getvar(transport, std::string("has-slot:") + part, &has_slot)) {
             die("Could not check if partition %s has slot.", part);
         }
         if (has_slot == "yes") {
-            std::vector<std::string> suffixes = get_suffixes(usb);
+            std::vector<std::string> suffixes = get_suffixes(transport);
             for (std::string &suffix : suffixes) {
-                do_for_partition(usb, part, suffix.c_str(), func, force_slot);
+                do_for_partition(transport, part, suffix.c_str(), func, force_slot);
             }
         } else {
-            do_for_partition(usb, part, "", func, force_slot);
+            do_for_partition(transport, part, "", func, force_slot);
         }
     } else {
-        do_for_partition(usb, part, slot, func, force_slot);
+        do_for_partition(transport, part, slot, func, force_slot);
     }
 }
 
-static void do_flash(usb_handle* usb, const char* pname, const char* fname) {
+static void do_flash(Transport* transport, const char* pname, const char* fname) {
     struct fastboot_buffer buf;
 
-    if (load_buf(usb, fname, &buf)) {
+    if (load_buf(transport, fname, &buf)) {
         die("cannot load '%s'", fname);
     }
     flash_buf(pname, &buf);
@@ -804,7 +810,7 @@
     fb_queue_command("signature", "installing signature");
 }
 
-static void do_update(usb_handle* usb, const char* filename, const char* slot_override, bool erase_first) {
+static void do_update(Transport* transport, const char* filename, const char* slot_override, bool erase_first) {
     queue_info_dump();
 
     fb_queue_query_save("product", cur_product, sizeof(cur_product));
@@ -835,12 +841,12 @@
             exit(1); // unzip_to_file already explained why.
         }
         fastboot_buffer buf;
-        int rc = load_buf_fd(usb, fd, &buf);
+        int rc = load_buf_fd(transport, fd, &buf);
         if (rc) die("cannot load %s from flash", images[i].img_name);
 
         auto update = [&](const std::string &partition) {
             do_update_signature(zip, images[i].sig_name);
-            if (erase_first && needs_erase(usb, partition.c_str())) {
+            if (erase_first && needs_erase(transport, partition.c_str())) {
                 fb_queue_erase(partition.c_str());
             }
             flash_buf(partition.c_str(), &buf);
@@ -849,7 +855,7 @@
              * program exits.
              */
         };
-        do_for_partitions(usb, images[i].part_name, slot_override, update, false);
+        do_for_partitions(transport, images[i].part_name, slot_override, update, false);
     }
 
     CloseArchive(zip);
@@ -871,7 +877,7 @@
     fb_queue_command("signature", "installing signature");
 }
 
-static void do_flashall(usb_handle* usb, const char *slot_override, int erase_first) {
+static void do_flashall(Transport* transport, const char* slot_override, int erase_first) {
     queue_info_dump();
 
     fb_queue_query_save("product", cur_product, sizeof(cur_product));
@@ -888,7 +894,7 @@
     for (size_t i = 0; i < ARRAY_SIZE(images); i++) {
         fname = find_item(images[i].part_name, product);
         fastboot_buffer buf;
-        if (load_buf(usb, fname, &buf)) {
+        if (load_buf(transport, fname, &buf)) {
             if (images[i].is_optional)
                 continue;
             die("could not load %s\n", images[i].img_name);
@@ -896,12 +902,12 @@
 
         auto flashall = [&](const std::string &partition) {
             do_send_signature(fname);
-            if (erase_first && needs_erase(usb, partition.c_str())) {
+            if (erase_first && needs_erase(transport, partition.c_str())) {
                 fb_queue_erase(partition.c_str());
             }
             flash_buf(partition.c_str(), &buf);
         };
-        do_for_partitions(usb, images[i].part_name, slot_override, flashall, false);
+        do_for_partitions(transport, images[i].part_name, slot_override, flashall, false);
     }
 }
 
@@ -986,7 +992,7 @@
     return num;
 }
 
-static void fb_perform_format(usb_handle* usb,
+static void fb_perform_format(Transport* transport,
                               const char* partition, int skip_if_not_supported,
                               const char* type_override, const char* size_override) {
     std::string partition_type, partition_size;
@@ -1004,7 +1010,7 @@
         limit = sparse_limit;
     }
 
-    if (!fb_getvar(usb, std::string("partition-type:") + partition, &partition_type)) {
+    if (!fb_getvar(transport, std::string("partition-type:") + partition, &partition_type)) {
         errMsg = "Can't determine partition type.\n";
         goto failed;
     }
@@ -1016,7 +1022,7 @@
         partition_type = type_override;
     }
 
-    if (!fb_getvar(usb, std::string("partition-size:") + partition, &partition_size)) {
+    if (!fb_getvar(transport, std::string("partition-size:") + partition, &partition_size)) {
         errMsg = "Unable to get partition size\n";
         goto failed;
     }
@@ -1058,7 +1064,7 @@
         return;
     }
 
-    if (load_buf_fd(usb, fd, &buf)) {
+    if (load_buf_fd(transport, fd, &buf)) {
         fprintf(stderr, "Cannot read image: %s\n", strerror(errno));
         close(fd);
         return;
@@ -1210,11 +1216,11 @@
         return 0;
     }
 
-    usb_handle* usb = open_device();
+    Transport* transport = open_device();
     if (slot_override != "")
-        slot_override = verify_slot(usb, slot_override.c_str());
+        slot_override = verify_slot(transport, slot_override.c_str());
     if (next_active != "")
-        next_active = verify_slot(usb, next_active.c_str());
+        next_active = verify_slot(transport, next_active.c_str());
 
     if (wants_set_active) {
         if (next_active == "") {
@@ -1235,8 +1241,8 @@
             require(2);
 
             auto erase = [&](const std::string &partition) {
-            std::string partition_type;
-                if (fb_getvar(usb, std::string("partition-type:") + argv[1], &partition_type) &&
+                std::string partition_type;
+                if (fb_getvar(transport, std::string("partition-type:") + argv[1], &partition_type) &&
                     fs_get_generator(partition_type) != nullptr) {
                     fprintf(stderr, "******** Did you mean to fastboot format this %s partition?\n",
                             partition_type.c_str());
@@ -1244,7 +1250,7 @@
 
                 fb_queue_erase(partition.c_str());
             };
-            do_for_partitions(usb, argv[1], slot_override.c_str(), erase, true);
+            do_for_partitions(transport, argv[1], slot_override.c_str(), erase, true);
             skip(2);
         } else if(!strncmp(*argv, "format", strlen("format"))) {
             char *overrides;
@@ -1274,12 +1280,12 @@
             if (size_override && !size_override[0]) size_override = nullptr;
 
             auto format = [&](const std::string &partition) {
-                if (erase_first && needs_erase(usb, partition.c_str())) {
+                if (erase_first && needs_erase(transport, partition.c_str())) {
                     fb_queue_erase(partition.c_str());
                 }
-                fb_perform_format(usb, partition.c_str(), 0, type_override, size_override);
+                fb_perform_format(transport, partition.c_str(), 0, type_override, size_override);
             };
-            do_for_partitions(usb, argv[1], slot_override.c_str(), format, true);
+            do_for_partitions(transport, argv[1], slot_override.c_str(), format, true);
             skip(2);
         } else if(!strcmp(*argv, "signature")) {
             require(2);
@@ -1341,12 +1347,12 @@
             if (fname == 0) die("cannot determine image filename for '%s'", pname);
 
             auto flash = [&](const std::string &partition) {
-                if (erase_first && needs_erase(usb, partition.c_str())) {
+                if (erase_first && needs_erase(transport, partition.c_str())) {
                     fb_queue_erase(partition.c_str());
                 }
-                do_flash(usb, partition.c_str(), fname);
+                do_flash(transport, partition.c_str(), fname);
             };
-            do_for_partitions(usb, pname, slot_override.c_str(), flash, true);
+            do_for_partitions(transport, pname, slot_override.c_str(), flash, true);
         } else if(!strcmp(*argv, "flash:raw")) {
             char *kname = argv[2];
             char *rname = 0;
@@ -1366,17 +1372,17 @@
             auto flashraw = [&](const std::string &partition) {
                 fb_queue_flash(partition.c_str(), data, sz);
             };
-            do_for_partitions(usb, argv[1], slot_override.c_str(), flashraw, true);
+            do_for_partitions(transport, argv[1], slot_override.c_str(), flashraw, true);
         } else if(!strcmp(*argv, "flashall")) {
             skip(1);
-            do_flashall(usb, slot_override.c_str(), erase_first);
+            do_flashall(transport, slot_override.c_str(), erase_first);
             wants_reboot = true;
         } else if(!strcmp(*argv, "update")) {
             if (argc > 1) {
-                do_update(usb, argv[1], slot_override.c_str(), erase_first);
+                do_update(transport, argv[1], slot_override.c_str(), erase_first);
                 skip(2);
             } else {
-                do_update(usb, "update.zip", slot_override.c_str(), erase_first);
+                do_update(transport, "update.zip", slot_override.c_str(), erase_first);
                 skip(1);
             }
             wants_reboot = true;
@@ -1407,13 +1413,13 @@
     if (wants_wipe) {
         fprintf(stderr, "wiping userdata...\n");
         fb_queue_erase("userdata");
-        fb_perform_format(usb, "userdata", 1, nullptr, nullptr);
+        fb_perform_format(transport, "userdata", 1, nullptr, nullptr);
 
         std::string cache_type;
-        if (fb_getvar(usb, "partition-type:cache", &cache_type) && !cache_type.empty()) {
+        if (fb_getvar(transport, "partition-type:cache", &cache_type) && !cache_type.empty()) {
             fprintf(stderr, "wiping cache...\n");
             fb_queue_erase("cache");
-            fb_perform_format(usb, "cache", 1, nullptr, nullptr);
+            fb_perform_format(transport, "cache", 1, nullptr, nullptr);
         }
     }
     if (wants_set_active) {
@@ -1427,5 +1433,5 @@
         fb_queue_wait_for_disconnect();
     }
 
-    return fb_execute_queue(usb) ? EXIT_FAILURE : EXIT_SUCCESS;
+    return fb_execute_queue(transport) ? EXIT_FAILURE : EXIT_SUCCESS;
 }
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index 784ec5c..acfbc13 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -34,22 +34,22 @@
 
 #include <string>
 
-#include "usb.h"
+#include "transport.h"
 
 struct sparse_file;
 
 /* protocol.c - fastboot protocol */
-int fb_command(usb_handle *usb, const char *cmd);
-int fb_command_response(usb_handle *usb, const char *cmd, char *response);
-int fb_download_data(usb_handle *usb, const void *data, uint32_t size);
-int fb_download_data_sparse(usb_handle *usb, struct sparse_file *s);
+int fb_command(Transport* transport, const char* cmd);
+int fb_command_response(Transport* transport, const char* cmd, char* response);
+int fb_download_data(Transport* transport, const void* data, uint32_t size);
+int fb_download_data_sparse(Transport* transport, struct sparse_file* s);
 char *fb_get_error(void);
 
 #define FB_COMMAND_SZ 64
 #define FB_RESPONSE_SZ 64
 
 /* engine.c - high level command queue engine */
-bool fb_getvar(usb_handle* usb, const std::string& key, std::string* value);
+bool fb_getvar(Transport* transport, const std::string& key, std::string* value);
 void fb_queue_flash(const char *ptn, void *data, uint32_t sz);
 void fb_queue_flash_sparse(const char *ptn, struct sparse_file *s, uint32_t sz);
 void fb_queue_erase(const char *ptn);
@@ -63,7 +63,7 @@
 void fb_queue_download(const char *name, void *data, uint32_t size);
 void fb_queue_notice(const char *notice);
 void fb_queue_wait_for_disconnect(void);
-int fb_execute_queue(usb_handle *usb);
+int fb_execute_queue(Transport* transport);
 void fb_set_active(const char *slot);
 
 /* util stuff */
diff --git a/fastboot/protocol.cpp b/fastboot/protocol.cpp
index cbd48e8..4850b4a 100644
--- a/fastboot/protocol.cpp
+++ b/fastboot/protocol.cpp
@@ -39,6 +39,7 @@
 #include <sparse/sparse.h>
 
 #include "fastboot.h"
+#include "transport.h"
 
 static char ERROR[128];
 
@@ -47,21 +48,21 @@
     return ERROR;
 }
 
-static int check_response(usb_handle* usb, uint32_t size, char* response) {
+static int check_response(Transport* transport, uint32_t size, char* response) {
     char status[65];
 
     while (true) {
-        int r = usb_read(usb, status, 64);
+        int r = transport->Read(status, 64);
         if (r < 0) {
             sprintf(ERROR, "status read failed (%s)", strerror(errno));
-            usb_close(usb);
+            transport->Close();
             return -1;
         }
         status[r] = 0;
 
         if (r < 4) {
             sprintf(ERROR, "status malformed (%d bytes)", r);
-            usb_close(usb);
+            transport->Close();
             return -1;
         }
 
@@ -90,21 +91,21 @@
             uint32_t dsize = strtol(status + 4, 0, 16);
             if (dsize > size) {
                 strcpy(ERROR, "data size too large");
-                usb_close(usb);
+                transport->Close();
                 return -1;
             }
             return dsize;
         }
 
         strcpy(ERROR,"unknown status code");
-        usb_close(usb);
+        transport->Close();
         break;
     }
 
     return -1;
 }
 
-static int _command_start(usb_handle* usb, const char* cmd, uint32_t size, char* response) {
+static int _command_start(Transport* transport, const char* cmd, uint32_t size, char* response) {
     size_t cmdsize = strlen(cmd);
     if (cmdsize > 64) {
         sprintf(ERROR, "command too large");
@@ -115,51 +116,51 @@
         response[0] = 0;
     }
 
-    if (usb_write(usb, cmd, cmdsize) != static_cast<int>(cmdsize)) {
+    if (transport->Write(cmd, cmdsize) != static_cast<int>(cmdsize)) {
         sprintf(ERROR, "command write failed (%s)", strerror(errno));
-        usb_close(usb);
+        transport->Close();
         return -1;
     }
 
-    return check_response(usb, size, response);
+    return check_response(transport, size, response);
 }
 
-static int _command_data(usb_handle* usb, const void* data, uint32_t size) {
-    int r = usb_write(usb, data, size);
+static int _command_data(Transport* transport, const void* data, uint32_t size) {
+    int r = transport->Write(data, size);
     if (r < 0) {
         sprintf(ERROR, "data transfer failure (%s)", strerror(errno));
-        usb_close(usb);
+        transport->Close();
         return -1;
     }
     if (r != ((int) size)) {
         sprintf(ERROR, "data transfer failure (short transfer)");
-        usb_close(usb);
+        transport->Close();
         return -1;
     }
     return r;
 }
 
-static int _command_end(usb_handle* usb) {
-    return check_response(usb, 0, 0) < 0 ? -1 : 0;
+static int _command_end(Transport* transport) {
+    return check_response(transport, 0, 0) < 0 ? -1 : 0;
 }
 
-static int _command_send(usb_handle* usb, const char* cmd, const void* data, uint32_t size,
+static int _command_send(Transport* transport, const char* cmd, const void* data, uint32_t size,
                          char* response) {
     if (size == 0) {
         return -1;
     }
 
-    int r = _command_start(usb, cmd, size, response);
+    int r = _command_start(transport, cmd, size, response);
     if (r < 0) {
         return -1;
     }
 
-    r = _command_data(usb, data, size);
+    r = _command_data(transport, data, size);
     if (r < 0) {
         return -1;
     }
 
-    r = _command_end(usb);
+    r = _command_end(transport);
     if (r < 0) {
         return -1;
     }
@@ -167,59 +168,59 @@
     return size;
 }
 
-static int _command_send_no_data(usb_handle* usb, const char* cmd, char* response) {
-    return _command_start(usb, cmd, 0, response);
+static int _command_send_no_data(Transport* transport, const char* cmd, char* response) {
+    return _command_start(transport, cmd, 0, response);
 }
 
-int fb_command(usb_handle* usb, const char* cmd) {
-    return _command_send_no_data(usb, cmd, 0);
+int fb_command(Transport* transport, const char* cmd) {
+    return _command_send_no_data(transport, cmd, 0);
 }
 
-int fb_command_response(usb_handle* usb, const char* cmd, char* response) {
-    return _command_send_no_data(usb, cmd, response);
+int fb_command_response(Transport* transport, const char* cmd, char* response) {
+    return _command_send_no_data(transport, cmd, response);
 }
 
-int fb_download_data(usb_handle* usb, const void* data, uint32_t size) {
+int fb_download_data(Transport* transport, const void* data, uint32_t size) {
     char cmd[64];
     sprintf(cmd, "download:%08x", size);
-    return _command_send(usb, cmd, data, size, 0) < 0 ? -1 : 0;
+    return _command_send(transport, cmd, data, size, 0) < 0 ? -1 : 0;
 }
 
-#define USB_BUF_SIZE 1024
-static char usb_buf[USB_BUF_SIZE];
-static int usb_buf_len;
+#define TRANSPORT_BUF_SIZE 1024
+static char transport_buf[TRANSPORT_BUF_SIZE];
+static int transport_buf_len;
 
 static int fb_download_data_sparse_write(void *priv, const void *data, int len)
 {
     int r;
-    usb_handle* usb = reinterpret_cast<usb_handle*>(priv);
+    Transport* transport = reinterpret_cast<Transport*>(priv);
     int to_write;
     const char* ptr = reinterpret_cast<const char*>(data);
 
-    if (usb_buf_len) {
-        to_write = std::min(USB_BUF_SIZE - usb_buf_len, len);
+    if (transport_buf_len) {
+        to_write = std::min(TRANSPORT_BUF_SIZE - transport_buf_len, len);
 
-        memcpy(usb_buf + usb_buf_len, ptr, to_write);
-        usb_buf_len += to_write;
+        memcpy(transport_buf + transport_buf_len, ptr, to_write);
+        transport_buf_len += to_write;
         ptr += to_write;
         len -= to_write;
     }
 
-    if (usb_buf_len == USB_BUF_SIZE) {
-        r = _command_data(usb, usb_buf, USB_BUF_SIZE);
-        if (r != USB_BUF_SIZE) {
+    if (transport_buf_len == TRANSPORT_BUF_SIZE) {
+        r = _command_data(transport, transport_buf, TRANSPORT_BUF_SIZE);
+        if (r != TRANSPORT_BUF_SIZE) {
             return -1;
         }
-        usb_buf_len = 0;
+        transport_buf_len = 0;
     }
 
-    if (len > USB_BUF_SIZE) {
-        if (usb_buf_len > 0) {
-            sprintf(ERROR, "internal error: usb_buf not empty\n");
+    if (len > TRANSPORT_BUF_SIZE) {
+        if (transport_buf_len > 0) {
+            sprintf(ERROR, "internal error: transport_buf not empty\n");
             return -1;
         }
-        to_write = round_down(len, USB_BUF_SIZE);
-        r = _command_data(usb, ptr, to_write);
+        to_write = round_down(len, TRANSPORT_BUF_SIZE);
+        r = _command_data(transport, ptr, to_write);
         if (r != to_write) {
             return -1;
         }
@@ -228,28 +229,28 @@
     }
 
     if (len > 0) {
-        if (len > USB_BUF_SIZE) {
-            sprintf(ERROR, "internal error: too much left for usb_buf\n");
+        if (len > TRANSPORT_BUF_SIZE) {
+            sprintf(ERROR, "internal error: too much left for transport_buf\n");
             return -1;
         }
-        memcpy(usb_buf, ptr, len);
-        usb_buf_len = len;
+        memcpy(transport_buf, ptr, len);
+        transport_buf_len = len;
     }
 
     return 0;
 }
 
-static int fb_download_data_sparse_flush(usb_handle* usb) {
-    if (usb_buf_len > 0) {
-        if (_command_data(usb, usb_buf, usb_buf_len) != usb_buf_len) {
+static int fb_download_data_sparse_flush(Transport* transport) {
+    if (transport_buf_len > 0) {
+        if (_command_data(transport, transport_buf, transport_buf_len) != transport_buf_len) {
             return -1;
         }
-        usb_buf_len = 0;
+        transport_buf_len = 0;
     }
     return 0;
 }
 
-int fb_download_data_sparse(usb_handle* usb, struct sparse_file* s) {
+int fb_download_data_sparse(Transport* transport, struct sparse_file* s) {
     int size = sparse_file_len(s, true, false);
     if (size <= 0) {
         return -1;
@@ -257,20 +258,20 @@
 
     char cmd[64];
     sprintf(cmd, "download:%08x", size);
-    int r = _command_start(usb, cmd, size, 0);
+    int r = _command_start(transport, cmd, size, 0);
     if (r < 0) {
         return -1;
     }
 
-    r = sparse_file_callback(s, true, false, fb_download_data_sparse_write, usb);
+    r = sparse_file_callback(s, true, false, fb_download_data_sparse_write, transport);
     if (r < 0) {
         return -1;
     }
 
-    r = fb_download_data_sparse_flush(usb);
+    r = fb_download_data_sparse_flush(transport);
     if (r < 0) {
         return -1;
     }
 
-    return _command_end(usb);
+    return _command_end(transport);
 }
diff --git a/fastboot/transport.h b/fastboot/transport.h
new file mode 100644
index 0000000..55a5abb
--- /dev/null
+++ b/fastboot/transport.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TRANSPORT_H_
+#define TRANSPORT_H_
+
+#include <base/macros.h>
+
+// General interface to allow the fastboot protocol to be used over different
+// types of transports.
+class Transport {
+  public:
+    Transport() = default;
+    virtual ~Transport() = default;
+
+    // Reads |len| bytes into |data|. Returns the number of bytes actually
+    // read or -1 on error.
+    virtual ssize_t Read(void* data, size_t len) = 0;
+
+    // Writes |len| bytes from |data|. Returns the number of bytes actually
+    // written or -1 on error.
+    virtual ssize_t Write(const void* data, size_t len) = 0;
+
+    // Closes the underlying transport. Returns 0 on success.
+    virtual int Close() = 0;
+
+    // Blocks until the transport disconnects. Transports that don't support
+    // this will return immediately. Returns 0 on success.
+    virtual int WaitForDisconnect() { return 0; }
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Transport);
+};
+
+#endif  // TRANSPORT_H_
diff --git a/fastboot/usb.h b/fastboot/usb.h
index 0fda41a..4acf12d 100644
--- a/fastboot/usb.h
+++ b/fastboot/usb.h
@@ -29,7 +29,7 @@
 #ifndef _USB_H_
 #define _USB_H_
 
-struct usb_handle;
+#include "transport.h"
 
 struct usb_ifc_info {
         /* from device descriptor */
@@ -55,10 +55,6 @@
 
 typedef int (*ifc_match_func)(usb_ifc_info *ifc);
 
-usb_handle *usb_open(ifc_match_func callback);
-int usb_close(usb_handle *h);
-int usb_read(usb_handle *h, void *_data, int len);
-int usb_write(usb_handle *h, const void *_data, int len);
-int usb_wait_for_disconnect(usb_handle *h);
+Transport* usb_open(ifc_match_func callback);
 
 #endif
diff --git a/fastboot/usb_linux.cpp b/fastboot/usb_linux.cpp
index 7b87907..02ffcd9 100644
--- a/fastboot/usb_linux.cpp
+++ b/fastboot/usb_linux.cpp
@@ -43,6 +43,8 @@
 #include <linux/version.h>
 #include <linux/usb/ch9.h>
 
+#include <memory>
+
 #include "fastboot.h"
 #include "usb.h"
 
@@ -85,6 +87,22 @@
     unsigned char ep_out;
 };
 
+class LinuxUsbTransport : public Transport {
+  public:
+    LinuxUsbTransport(std::unique_ptr<usb_handle> handle) : handle_(std::move(handle)) {}
+    ~LinuxUsbTransport() override = default;
+
+    ssize_t Read(void* data, size_t len) override;
+    ssize_t Write(const void* data, size_t len) override;
+    int Close() override;
+    int WaitForDisconnect() override;
+
+  private:
+    std::unique_ptr<usb_handle> handle_;
+
+    DISALLOW_COPY_AND_ASSIGN(LinuxUsbTransport);
+};
+
 /* True if name isn't a valid name for a USB device in /sys/bus/usb/devices.
  * Device names are made up of numbers, dots, and dashes, e.g., '7-1.5'.
  * We reject interfaces (e.g., '7-1.5:1.0') and host controllers (e.g. 'usb1').
@@ -308,9 +326,9 @@
     return 0;
 }
 
-static usb_handle *find_usb_device(const char *base, ifc_match_func callback)
+static std::unique_ptr<usb_handle> find_usb_device(const char* base, ifc_match_func callback)
 {
-    usb_handle *usb = 0;
+    std::unique_ptr<usb_handle> usb;
     char devname[64];
     char desc[1024];
     int n, in, out, ifc;
@@ -321,39 +339,37 @@
     int writable;
 
     busdir = opendir(base);
-    if(busdir == 0) return 0;
+    if (busdir == 0) return 0;
 
-    while((de = readdir(busdir)) && (usb == 0)) {
-        if(badname(de->d_name)) continue;
+    while ((de = readdir(busdir)) && (usb == nullptr)) {
+        if (badname(de->d_name)) continue;
 
-        if(!convert_to_devfs_name(de->d_name, devname, sizeof(devname))) {
+        if (!convert_to_devfs_name(de->d_name, devname, sizeof(devname))) {
 
 //            DBG("[ scanning %s ]\n", devname);
             writable = 1;
-            if((fd = open(devname, O_RDWR)) < 0) {
+            if ((fd = open(devname, O_RDWR)) < 0) {
                 // Check if we have read-only access, so we can give a helpful
                 // diagnostic like "adb devices" does.
                 writable = 0;
-                if((fd = open(devname, O_RDONLY)) < 0) {
+                if ((fd = open(devname, O_RDONLY)) < 0) {
                     continue;
                 }
             }
 
             n = read(fd, desc, sizeof(desc));
 
-            if(filter_usb_device(de->d_name, desc, n, writable, callback,
-                                 &in, &out, &ifc) == 0) {
-                usb = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
+            if (filter_usb_device(de->d_name, desc, n, writable, callback, &in, &out, &ifc) == 0) {
+                usb.reset(new usb_handle());
                 strcpy(usb->fname, devname);
                 usb->ep_in = in;
                 usb->ep_out = out;
                 usb->desc = fd;
 
                 n = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &ifc);
-                if(n != 0) {
+                if (n != 0) {
                     close(fd);
-                    free(usb);
-                    usb = 0;
+                    usb.reset();
                     continue;
                 }
             } else {
@@ -366,14 +382,14 @@
     return usb;
 }
 
-int usb_write(usb_handle *h, const void *_data, int len)
+ssize_t LinuxUsbTransport::Write(const void* _data, size_t len)
 {
     unsigned char *data = (unsigned char*) _data;
     unsigned count = 0;
     struct usbdevfs_bulktransfer bulk;
     int n;
 
-    if(h->ep_out == 0 || h->desc == -1) {
+    if (handle_->ep_out == 0 || handle_->desc == -1) {
         return -1;
     }
 
@@ -381,12 +397,12 @@
         int xfer;
         xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
 
-        bulk.ep = h->ep_out;
+        bulk.ep = handle_->ep_out;
         bulk.len = xfer;
         bulk.data = data;
         bulk.timeout = 0;
 
-        n = ioctl(h->desc, USBDEVFS_BULK, &bulk);
+        n = ioctl(handle_->desc, USBDEVFS_BULK, &bulk);
         if(n != xfer) {
             DBG("ERROR: n = %d, errno = %d (%s)\n",
                 n, errno, strerror(errno));
@@ -401,30 +417,30 @@
     return count;
 }
 
-int usb_read(usb_handle *h, void *_data, int len)
+ssize_t LinuxUsbTransport::Read(void* _data, size_t len)
 {
     unsigned char *data = (unsigned char*) _data;
     unsigned count = 0;
     struct usbdevfs_bulktransfer bulk;
     int n, retry;
 
-    if(h->ep_in == 0 || h->desc == -1) {
+    if (handle_->ep_in == 0 || handle_->desc == -1) {
         return -1;
     }
 
     while(len > 0) {
         int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
 
-        bulk.ep = h->ep_in;
+        bulk.ep = handle_->ep_in;
         bulk.len = xfer;
         bulk.data = data;
         bulk.timeout = 0;
         retry = 0;
 
         do{
-           DBG("[ usb read %d fd = %d], fname=%s\n", xfer, h->desc, h->fname);
-           n = ioctl(h->desc, USBDEVFS_BULK, &bulk);
-           DBG("[ usb read %d ] = %d, fname=%s, Retry %d \n", xfer, n, h->fname, retry);
+           DBG("[ usb read %d fd = %d], fname=%s\n", xfer, handle_->desc, handle_->fname);
+           n = ioctl(handle_->desc, USBDEVFS_BULK, &bulk);
+           DBG("[ usb read %d ] = %d, fname=%s, Retry %d \n", xfer, n, handle_->fname, retry);
 
            if( n < 0 ) {
             DBG1("ERROR: n = %d, errno = %d (%s)\n",n, errno, strerror(errno));
@@ -446,24 +462,12 @@
     return count;
 }
 
-void usb_kick(usb_handle *h)
+int LinuxUsbTransport::Close()
 {
     int fd;
 
-    fd = h->desc;
-    h->desc = -1;
-    if(fd >= 0) {
-        close(fd);
-        DBG("[ usb closed %d ]\n", fd);
-    }
-}
-
-int usb_close(usb_handle *h)
-{
-    int fd;
-
-    fd = h->desc;
-    h->desc = -1;
+    fd = handle_->desc;
+    handle_->desc = -1;
     if(fd >= 0) {
         close(fd);
         DBG("[ usb closed %d ]\n", fd);
@@ -472,20 +476,21 @@
     return 0;
 }
 
-usb_handle *usb_open(ifc_match_func callback)
+Transport* usb_open(ifc_match_func callback)
 {
-    return find_usb_device("/sys/bus/usb/devices", callback);
+    std::unique_ptr<usb_handle> handle = find_usb_device("/sys/bus/usb/devices", callback);
+    return handle ? new LinuxUsbTransport(std::move(handle)) : nullptr;
 }
 
 /* Wait for the system to notice the device is gone, so that a subsequent
  * fastboot command won't try to access the device before it's rebooted.
  * Returns 0 for success, -1 for timeout.
  */
-int usb_wait_for_disconnect(usb_handle *usb)
+int LinuxUsbTransport::WaitForDisconnect()
 {
   double deadline = now() + WAIT_FOR_DISCONNECT_TIMEOUT;
   while (now() < deadline) {
-    if (access(usb->fname, F_OK))
+    if (access(handle_->fname, F_OK))
       return 0;
     usleep(50000);
   }
diff --git a/fastboot/usb_osx.cpp b/fastboot/usb_osx.cpp
index 45ae833..ee5d575 100644
--- a/fastboot/usb_osx.cpp
+++ b/fastboot/usb_osx.cpp
@@ -35,6 +35,8 @@
 #include <IOKit/IOMessage.h>
 #include <mach/mach_port.h>
 
+#include <memory>
+
 #include "usb.h"
 
 
@@ -63,6 +65,21 @@
     unsigned int zero_mask;
 };
 
+class OsxUsbTransport : public Transport {
+  public:
+    OsxUsbTransport(std::unique_ptr<usb_handle> handle) : handle_(std::move(handle)) {}
+    ~OsxUsbTransport() override = default;
+
+    ssize_t Read(void* data, size_t len) override;
+    ssize_t Write(const void* data, size_t len) override;
+    int Close() override;
+
+  private:
+    std::unique_ptr<usb_handle> handle_;
+
+    DISALLOW_COPY_AND_ASSIGN(OsxUsbTransport);
+};
+
 /** Try out all the interfaces and see if there's a match. Returns 0 on
  * success, -1 on failure. */
 static int try_interfaces(IOUSBDeviceInterface182 **dev, usb_handle *handle) {
@@ -390,7 +407,7 @@
 
 
 /** Initializes the USB system. Returns 0 on success, -1 on error. */
-static int init_usb(ifc_match_func callback, usb_handle **handle) {
+static int init_usb(ifc_match_func callback, std::unique_ptr<usb_handle>* handle) {
     int ret = -1;
     CFMutableDictionaryRef matchingDict;
     kern_return_t result;
@@ -443,8 +460,8 @@
         }
 
         if (h.success) {
-            *handle = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
-            memcpy(*handle, &h, sizeof(usb_handle));
+            handle->reset(new usb_handle);
+            memcpy(handle->get(), &h, sizeof(usb_handle));
             ret = 0;
             break;
         }
@@ -463,28 +480,23 @@
  * Definitions of this file's public functions.
  */
 
-usb_handle *usb_open(ifc_match_func callback) {
-    usb_handle *handle = NULL;
+Transport* usb_open(ifc_match_func callback) {
+    std::unique_ptr<usb_handle> handle;
 
     if (init_usb(callback, &handle) < 0) {
         /* Something went wrong initializing USB. */
-        return NULL;
+        return nullptr;
     }
 
-    return handle;
+    return new OsxUsbTransport(std::move(handle));
 }
 
-int usb_close(usb_handle *h) {
+int OsxUsbTransport::Close() {
     /* TODO: Something better here? */
     return 0;
 }
 
-int usb_wait_for_disconnect(usb_handle *usb) {
-    /* TODO: Punt for now */
-    return 0;
-}
-
-int usb_read(usb_handle *h, void *data, int len) {
+ssize_t OsxUsbTransport::Read(void* data, size_t len) {
     IOReturn result;
     UInt32 numBytes = len;
 
@@ -492,22 +504,21 @@
         return 0;
     }
 
-    if (h == NULL) {
+    if (handle_ == nullptr) {
         return -1;
     }
 
-    if (h->interface == NULL) {
+    if (handle_->interface == nullptr) {
         ERR("usb_read interface was null\n");
         return -1;
     }
 
-    if (h->bulkIn == 0) {
+    if (handle_->bulkIn == 0) {
         ERR("bulkIn endpoint not assigned\n");
         return -1;
     }
 
-    result = (*h->interface)->ReadPipe(
-            h->interface, h->bulkIn, data, &numBytes);
+    result = (*handle_->interface)->ReadPipe(handle_->interface, handle_->bulkIn, data, &numBytes);
 
     if (result == 0) {
         return (int) numBytes;
@@ -518,30 +529,30 @@
     return -1;
 }
 
-int usb_write(usb_handle *h, const void *data, int len) {
+ssize_t OsxUsbTransport::Write(const void* data, size_t len) {
     IOReturn result;
 
     if (len == 0) {
         return 0;
     }
 
-    if (h == NULL) {
+    if (handle_ == NULL) {
         return -1;
     }
 
-    if (h->interface == NULL) {
+    if (handle_->interface == NULL) {
         ERR("usb_write interface was null\n");
         return -1;
     }
 
-    if (h->bulkOut == 0) {
+    if (handle_->bulkOut == 0) {
         ERR("bulkOut endpoint not assigned\n");
         return -1;
     }
 
 #if 0
-    result = (*h->interface)->WritePipe(
-            h->interface, h->bulkOut, (void *)data, len);
+    result = (*handle_->interface)->WritePipe(
+            handle_->interface, handle_->bulkOut, (void *)data, len);
 #else
     /* Attempt to work around crashes in the USB driver that may be caused
      * by trying to write too much data at once.  The kernel IOCopyMapper
@@ -554,8 +565,8 @@
         int lenToSend = lenRemaining > maxLenToSend
             ? maxLenToSend : lenRemaining;
 
-        result = (*h->interface)->WritePipe(
-                h->interface, h->bulkOut, (void *)data, lenToSend);
+        result = (*handle_->interface)->WritePipe(
+                handle_->interface, handle_->bulkOut, (void *)data, lenToSend);
         if (result != 0) break;
 
         lenRemaining -= lenToSend;
@@ -564,11 +575,11 @@
 #endif
 
     #if 0
-    if ((result == 0) && (h->zero_mask)) {
+    if ((result == 0) && (handle_->zero_mask)) {
         /* we need 0-markers and our transfer */
-        if(!(len & h->zero_mask)) {
-            result = (*h->interface)->WritePipe(
-                    h->interface, h->bulkOut, (void *)data, 0);
+        if(!(len & handle_->zero_mask)) {
+            result = (*handle_->interface)->WritePipe(
+                    handle_->interface, handle_->bulkOut, (void *)data, 0);
         }
     }
     #endif
diff --git a/fastboot/usb_windows.cpp b/fastboot/usb_windows.cpp
index a09610f..1cdeb32 100644
--- a/fastboot/usb_windows.cpp
+++ b/fastboot/usb_windows.cpp
@@ -34,6 +34,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include <memory>
+#include <string>
+
 #include "usb.h"
 
 //#define TRACE_USB 1
@@ -60,24 +63,32 @@
     ADBAPIHANDLE  adb_write_pipe;
 
     /// Interface name
-    char*         interface_name;
+    std::string interface_name;
+};
+
+class WindowsUsbTransport : public Transport {
+  public:
+    WindowsUsbTransport(std::unique_ptr<usb_handle> handle) : handle_(std::move(handle)) {}
+    ~WindowsUsbTransport() override = default;
+
+    ssize_t Read(void* data, size_t len) override;
+    ssize_t Write(const void* data, size_t len) override;
+    int Close() override;
+
+  private:
+    std::unique_ptr<usb_handle> handle_;
+
+    DISALLOW_COPY_AND_ASSIGN(WindowsUsbTransport);
 };
 
 /// Class ID assigned to the device by androidusb.sys
 static const GUID usb_class_id = ANDROID_USB_CLASS_ID;
 
-
 /// Checks if interface (device) matches certain criteria
 int recognized_device(usb_handle* handle, ifc_match_func callback);
 
 /// Opens usb interface (device) by interface (device) name.
-usb_handle* do_usb_open(const wchar_t* interface_name);
-
-/// Writes data to the opened usb handle
-int usb_write(usb_handle* handle, const void* data, int len);
-
-/// Reads data using the opened usb handle
-int usb_read(usb_handle *handle, void* data, int len);
+std::unique_ptr<usb_handle> do_usb_open(const wchar_t* interface_name);
 
 /// Cleans up opened usb handle
 void usb_cleanup_handle(usb_handle* handle);
@@ -85,23 +96,17 @@
 /// Cleans up (but don't close) opened usb handle
 void usb_kick(usb_handle* handle);
 
-/// Closes opened usb handle
-int usb_close(usb_handle* handle);
 
-
-usb_handle* do_usb_open(const wchar_t* interface_name) {
+std::unique_ptr<usb_handle> do_usb_open(const wchar_t* interface_name) {
     // Allocate our handle
-    usb_handle* ret = (usb_handle*)malloc(sizeof(usb_handle));
-    if (NULL == ret)
-        return NULL;
+    std::unique_ptr<usb_handle> ret(new usb_handle);
 
     // Create interface.
     ret->adb_interface = AdbCreateInterfaceByName(interface_name);
 
-    if (NULL == ret->adb_interface) {
-        free(ret);
+    if (nullptr == ret->adb_interface) {
         errno = GetLastError();
-        return NULL;
+        return nullptr;
     }
 
     // Open read pipe (endpoint)
@@ -109,35 +114,30 @@
         AdbOpenDefaultBulkReadEndpoint(ret->adb_interface,
                                    AdbOpenAccessTypeReadWrite,
                                    AdbOpenSharingModeReadWrite);
-    if (NULL != ret->adb_read_pipe) {
+    if (nullptr != ret->adb_read_pipe) {
         // Open write pipe (endpoint)
         ret->adb_write_pipe =
             AdbOpenDefaultBulkWriteEndpoint(ret->adb_interface,
                                       AdbOpenAccessTypeReadWrite,
                                       AdbOpenSharingModeReadWrite);
-        if (NULL != ret->adb_write_pipe) {
+        if (nullptr != ret->adb_write_pipe) {
             // Save interface name
             unsigned long name_len = 0;
 
             // First get expected name length
             AdbGetInterfaceName(ret->adb_interface,
-                          NULL,
+                          nullptr,
                           &name_len,
                           true);
             if (0 != name_len) {
-                ret->interface_name = (char*)malloc(name_len);
-
-                if (NULL != ret->interface_name) {
-                    // Now save the name
-                    if (AdbGetInterfaceName(ret->adb_interface,
-                                  ret->interface_name,
-                                  &name_len,
-                                  true)) {
-                        // We're done at this point
-                        return ret;
-                    }
-                } else {
-                    SetLastError(ERROR_OUTOFMEMORY);
+                // Now save the name
+                ret->interface_name.resize(name_len);
+                if (AdbGetInterfaceName(ret->adb_interface,
+                              &ret->interface_name[0],
+                              &name_len,
+                              true)) {
+                    // We're done at this point
+                    return ret;
                 }
             }
         }
@@ -145,35 +145,31 @@
 
     // Something went wrong.
     errno = GetLastError();
-    usb_cleanup_handle(ret);
-    free(ret);
+    usb_cleanup_handle(ret.get());
     SetLastError(errno);
 
-    return NULL;
+    return nullptr;
 }
 
-int usb_write(usb_handle* handle, const void* data, int len) {
+ssize_t WindowsUsbTransport::Write(const void* data, size_t len) {
     unsigned long time_out = 5000;
     unsigned long written = 0;
     unsigned count = 0;
     int ret;
 
     DBG("usb_write %d\n", len);
-    if (NULL != handle) {
+    if (nullptr != handle_) {
         // Perform write
         while(len > 0) {
             int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
-            ret = AdbWriteEndpointSync(handle->adb_write_pipe,
-                                   (void*)data,
-                                   (unsigned long)xfer,
-                                   &written,
-                                   time_out);
+            ret = AdbWriteEndpointSync(handle_->adb_write_pipe, const_cast<void*>(data), xfer,
+                                       &written, time_out);
             errno = GetLastError();
             DBG("AdbWriteEndpointSync returned %d, errno: %d\n", ret, errno);
             if (ret == 0) {
                 // assume ERROR_INVALID_HANDLE indicates we are disconnected
                 if (errno == ERROR_INVALID_HANDLE)
-                usb_kick(handle);
+                usb_kick(handle_.get());
                 return -1;
             }
 
@@ -194,21 +190,17 @@
     return -1;
 }
 
-int usb_read(usb_handle *handle, void* data, int len) {
+ssize_t WindowsUsbTransport::Read(void* data, size_t len) {
     unsigned long time_out = 0;
     unsigned long read = 0;
     int ret;
 
     DBG("usb_read %d\n", len);
-    if (NULL != handle) {
+    if (nullptr != handle_) {
         while (1) {
             int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
 
-	        ret = AdbReadEndpointSync(handle->adb_read_pipe,
-	                              (void*)data,
-	                              (unsigned long)xfer,
-	                              &read,
-	                              time_out);
+            ret = AdbReadEndpointSync(handle_->adb_read_pipe, data, xfer, &read, time_out);
             errno = GetLastError();
             DBG("usb_read got: %ld, expected: %d, errno: %d\n", read, xfer, errno);
             if (ret) {
@@ -216,7 +208,7 @@
             } else {
                 // assume ERROR_INVALID_HANDLE indicates we are disconnected
                 if (errno == ERROR_INVALID_HANDLE)
-                    usb_kick(handle);
+                    usb_kick(handle_.get());
                 break;
             }
             // else we timed out - try again
@@ -233,8 +225,6 @@
 
 void usb_cleanup_handle(usb_handle* handle) {
     if (NULL != handle) {
-        if (NULL != handle->interface_name)
-            free(handle->interface_name);
         if (NULL != handle->adb_write_pipe)
             AdbCloseHandle(handle->adb_write_pipe);
         if (NULL != handle->adb_read_pipe)
@@ -242,7 +232,7 @@
         if (NULL != handle->adb_interface)
             AdbCloseHandle(handle->adb_interface);
 
-        handle->interface_name = NULL;
+        handle->interface_name.clear();
         handle->adb_write_pipe = NULL;
         handle->adb_read_pipe = NULL;
         handle->adb_interface = NULL;
@@ -258,23 +248,18 @@
     }
 }
 
-int usb_close(usb_handle* handle) {
+int WindowsUsbTransport::Close() {
     DBG("usb_close\n");
 
-    if (NULL != handle) {
+    if (nullptr != handle_) {
         // Cleanup handle
-        usb_cleanup_handle(handle);
-        free(handle);
+        usb_cleanup_handle(handle_.get());
+        handle_.reset();
     }
 
     return 0;
 }
 
-int usb_wait_for_disconnect(usb_handle *usb) {
-    /* TODO: Punt for now */
-    return 0;
-}
-
 int recognized_device(usb_handle* handle, ifc_match_func callback) {
     struct usb_ifc_info info;
     USB_DEVICE_DESCRIPTOR device_desc;
@@ -326,8 +311,8 @@
     return 0;
 }
 
-static usb_handle *find_usb_device(ifc_match_func callback) {
-	usb_handle* handle = NULL;
+static std::unique_ptr<usb_handle> find_usb_device(ifc_match_func callback) {
+    std::unique_ptr<usb_handle> handle;
     char entry_buffer[2048];
     char interf_name[2048];
     AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]);
@@ -356,13 +341,12 @@
         handle = do_usb_open(next_interface->device_name);
         if (NULL != handle) {
             // Lets see if this interface (device) belongs to us
-            if (recognized_device(handle, callback)) {
+            if (recognized_device(handle.get(), callback)) {
                 // found it!
                 break;
             } else {
-                usb_cleanup_handle(handle);
-                free(handle);
-                handle = NULL;
+                usb_cleanup_handle(handle.get());
+                handle.reset();
             }
         }
 
@@ -373,9 +357,10 @@
     return handle;
 }
 
-usb_handle *usb_open(ifc_match_func callback)
+Transport* usb_open(ifc_match_func callback)
 {
-    return find_usb_device(callback);
+    std::unique_ptr<usb_handle> handle = find_usb_device(callback);
+    return handle ? new WindowsUsbTransport(std::move(handle)) : nullptr;
 }
 
 // called from fastboot.c
diff --git a/fastboot/usbtest.cpp b/fastboot/usbtest.cpp
index e6e2b37..9423c6d 100644
--- a/fastboot/usbtest.cpp
+++ b/fastboot/usbtest.cpp
@@ -86,7 +86,7 @@
     return 0;
 }
 
-int test_null(usb_handle *usb)
+int test_null(Transport* usb)
 {
     unsigned i;
     unsigned char buf[4096];
@@ -94,8 +94,8 @@
     long long t0, t1;
 
     t0 = NOW();
-    for(i = 0; i < arg_count; i++) {
-        if(usb_write(usb, buf, arg_size) != (int)arg_size) {
+    for (i = 0; i < arg_count; i++) {
+        if (usb->Write(buf, arg_size) != static_cast<int>(arg_size)) {
             fprintf(stderr,"write failed (%s)\n", strerror(errno));
             return -1;
         }
@@ -105,15 +105,15 @@
     return 0;
 }
 
-int test_zero(usb_handle *usb)
+int test_zero(Transport* usb)
 {
     unsigned i;
     unsigned char buf[4096];
     long long t0, t1;
 
     t0 = NOW();
-    for(i = 0; i < arg_count; i++) {
-        if(usb_read(usb, buf, arg_size) != (int)arg_size) {
+    for (i = 0; i < arg_count; i++) {
+        if (usb->Read(buf, arg_size) != static_cast<int>(arg_size)) {
             fprintf(stderr,"read failed (%s)\n", strerror(errno));
             return -1;
         }
@@ -127,7 +127,7 @@
 {
     const char *cmd;
     ifc_match_func match;
-    int (*test)(usb_handle *usb);
+    int (*test)(Transport* usb);
     const char *help;
 } tests[] = {
     { "list", printifc,   NULL,      "list interfaces" },
@@ -177,7 +177,7 @@
 
 int main(int argc, char **argv)
 {
-    usb_handle *usb;
+    Transport* usb;
     int i;
 
     if(argc < 2)
diff --git a/include/log/log.h b/include/log/log.h
index e0dc3a3..1cdf7bc 100644
--- a/include/log/log.h
+++ b/include/log/log.h
@@ -616,12 +616,7 @@
  * Use the per-tag properties "log.tag.<tagname>" to generate a runtime
  * result of non-zero to expose a log.
  */
-/* default prio ANDROID_LOG_VERBOSE to ANDROID_LOG_FATAL if no property */
-#define ANDROID_LOGGABLE_FLAG_DEFAULT_MASK      0x000F
-/* Save 2 syscalls if caller guarantees to never call within signal handler */
-#define ANDROID_LOGGABLE_FLAG_NOT_WITHIN_SIGNAL 0x8000
-
-int __android_log_is_loggable(int prio, const char *tag, int flag);
+int __android_log_is_loggable(int prio, const char *tag, int def);
 
 int __android_log_error_write(int tag, const char *subTag, int32_t uid, const char *data,
                               uint32_t dataLen);
diff --git a/liblog/fake_log_device.c b/liblog/fake_log_device.c
index fcdb6c9..8a8ece2 100644
--- a/liblog/fake_log_device.c
+++ b/liblog/fake_log_device.c
@@ -24,7 +24,6 @@
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <signal.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -98,33 +97,18 @@
  */
 static pthread_mutex_t fakeLogDeviceLock = PTHREAD_MUTEX_INITIALIZER;
 
-static void lock(sigset_t *sigflags)
+static void lock()
 {
-    /*
-     * If we trigger a signal handler in the middle of locked activity and the
-     * signal handler logs a message, we could get into a deadlock state.
-     */
-    sigset_t all;
-
-    sigfillset(&all);
-    pthread_sigmask(SIG_BLOCK, &all, sigflags);
     pthread_mutex_lock(&fakeLogDeviceLock);
 }
 
-static void unlock(sigset_t *sigflags)
+static void unlock()
 {
     pthread_mutex_unlock(&fakeLogDeviceLock);
-    pthread_sigmask(SIG_UNBLOCK, sigflags, NULL);
 }
-
-#define DECLARE_SIGSET(name) sigset_t name
-
 #else   // !defined(_WIN32)
-
-#define lock(sigflags) ((void)0)
-#define unlock(sigflags) ((void)0)
-#define DECLARE_SIGSET(name)
-
+#define lock() ((void)0)
+#define unlock() ((void)0)
 #endif  // !defined(_WIN32)
 
 
@@ -170,9 +154,8 @@
 static void deleteFakeFd(int fd)
 {
     LogState *ls;
-    DECLARE_SIGSET(sigflags);
 
-    lock(&sigflags);
+    lock();
 
     ls = fdToLogState(fd);
     if (ls != NULL) {
@@ -181,7 +164,7 @@
         free(ls);
     }
 
-    unlock(&sigflags);
+    unlock();
 }
 
 /*
@@ -565,13 +548,12 @@
 static ssize_t logWritev(int fd, const struct iovec* vector, int count)
 {
     LogState* state;
-    DECLARE_SIGSET(sigflags);
 
     /* Make sure that no-one frees the LogState while we're using it.
      * Also guarantees that only one thread is in showLog() at a given
      * time (if it matters).
      */
-    lock(&sigflags);
+    lock();
 
     state = fdToLogState(fd);
     if (state == NULL) {
@@ -616,10 +598,10 @@
     }
 
 bail:
-    unlock(&sigflags);
+    unlock();
     return vector[0].iov_len + vector[1].iov_len + vector[2].iov_len;
 error:
-    unlock(&sigflags);
+    unlock();
     return -1;
 }
 
@@ -639,9 +621,8 @@
 {
     LogState *logState;
     int fd = -1;
-    DECLARE_SIGSET(sigflags);
 
-    lock(&sigflags);
+    lock();
 
     logState = createLogState();
     if (logState != NULL) {
@@ -651,7 +632,7 @@
         errno = ENFILE;
     }
 
-    unlock(&sigflags);
+    unlock();
 
     return fd;
 }
diff --git a/liblog/log_is_loggable.c b/liblog/log_is_loggable.c
index 9d043ff..814d96d 100644
--- a/liblog/log_is_loggable.c
+++ b/liblog/log_is_loggable.c
@@ -16,39 +16,12 @@
 
 #include <ctype.h>
 #include <pthread.h>
-#include <signal.h>
 #include <stdlib.h>
 #include <string.h>
 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
 #include <sys/_system_properties.h>
 
 #include <android/log.h>
-#include <log/log.h>
-
-static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
-
-static void lock(sigset_t *sigflags)
-{
-    /*
-     * If we trigger a signal handler in the middle of locked activity and the
-     * signal handler logs a message, we could get into a deadlock state.
-     */
-    if (sigflags) {
-        sigset_t all;
-
-        sigfillset(&all);
-        pthread_sigmask(SIG_BLOCK, &all, sigflags);
-    }
-    pthread_mutex_lock(&lock_loggable);
-}
-
-static void unlock(sigset_t *sigflags)
-{
-    pthread_mutex_unlock(&lock_loggable);
-    if (sigflags) {
-        pthread_sigmask(SIG_UNBLOCK, sigflags, NULL);
-    }
-}
 
 struct cache {
     const prop_info *pinfo;
@@ -76,7 +49,9 @@
     cache->c = buf[0];
 }
 
-static int __android_log_level(const char *tag, int flag)
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+static int __android_log_level(const char *tag, int def)
 {
     /* sizeof() is used on this array below */
     static const char log_namespace[] = "persist.log.tag.";
@@ -108,11 +83,10 @@
         { NULL, -1, 0 },
         { NULL, -1, 0 }
     };
-    sigset_t sigflags;
 
     strcpy(key, log_namespace);
 
-    lock((flag & ANDROID_LOGGABLE_FLAG_NOT_WITHIN_SIGNAL) ? NULL : &sigflags);
+    pthread_mutex_lock(&lock);
 
     current_global_serial = __system_property_area_serial();
 
@@ -182,7 +156,7 @@
 
     global_serial = current_global_serial;
 
-    unlock((flag & ANDROID_LOGGABLE_FLAG_NOT_WITHIN_SIGNAL) ? NULL : &sigflags);
+    pthread_mutex_unlock(&lock);
 
     switch (toupper(c)) {
     case 'V': return ANDROID_LOG_VERBOSE;
@@ -194,46 +168,36 @@
     case 'A': return ANDROID_LOG_FATAL;
     case 'S': return -1; /* ANDROID_LOG_SUPPRESS */
     }
-    return flag & ANDROID_LOGGABLE_FLAG_DEFAULT_MASK;
+    return def;
 }
 
-int __android_log_is_loggable(int prio, const char *tag, int flag)
+int __android_log_is_loggable(int prio, const char *tag, int def)
 {
-    int logLevel = __android_log_level(tag, flag);
+    int logLevel = __android_log_level(tag, def);
     return logLevel >= 0 && prio >= logLevel;
 }
 
-/*
- * Timestamp state generally remains constant, since a change is
- * rare, we can accept a trylock failure gracefully.
- */
-static pthread_mutex_t lock_timestamp = PTHREAD_MUTEX_INITIALIZER;
-
 char android_log_timestamp()
 {
     static struct cache r_time_cache = { NULL, -1, 0 };
     static struct cache p_time_cache = { NULL, -1, 0 };
+    static uint32_t serial;
+    uint32_t current_serial;
     char retval;
 
-    if (pthread_mutex_trylock(&lock_timestamp)) {
-        /* We are willing to accept some race in this context */
-        if (!(retval = p_time_cache.c)) {
-            retval = r_time_cache.c;
-        }
-    } else {
-        static uint32_t serial;
-        uint32_t current_serial = __system_property_area_serial();
-        if (current_serial != serial) {
-            refresh_cache(&r_time_cache, "ro.logd.timestamp");
-            refresh_cache(&p_time_cache, "persist.logd.timestamp");
-            serial = current_serial;
-        }
-        if (!(retval = p_time_cache.c)) {
-            retval = r_time_cache.c;
-        }
+    pthread_mutex_lock(&lock);
 
-        pthread_mutex_unlock(&lock_timestamp);
+    current_serial = __system_property_area_serial();
+    if (current_serial != serial) {
+        refresh_cache(&r_time_cache, "ro.logd.timestamp");
+        refresh_cache(&p_time_cache, "persist.logd.timestamp");
+        serial = current_serial;
     }
+    if (!(retval = p_time_cache.c)) {
+        retval = r_time_cache.c;
+    }
+
+    pthread_mutex_unlock(&lock);
 
     return tolower(retval ?: 'r');
 }
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index a8ecc8d..a4310ae 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -20,7 +20,6 @@
 #include <fcntl.h>
 #if !defined(_WIN32)
 #include <pthread.h>
-#include <signal.h>
 #endif
 #include <stdarg.h>
 #include <stdatomic.h>
@@ -55,43 +54,14 @@
 
 static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr);
 static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;
+#if !defined(_WIN32)
+static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
+#endif
 
 #ifndef __unused
 #define __unused  __attribute__((__unused__))
 #endif
 
-#if !defined(_WIN32)
-static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
-
-static void lock(sigset_t *sigflags)
-{
-    /*
-     * If we trigger a signal handler in the middle of locked activity and the
-     * signal handler logs a message, we could get into a deadlock state.
-     */
-    sigset_t all;
-
-    sigfillset(&all);
-    pthread_sigmask(SIG_BLOCK, &all, sigflags);
-    pthread_mutex_lock(&log_init_lock);
-}
-
-static void unlock(sigset_t *sigflags)
-{
-    pthread_mutex_unlock(&log_init_lock);
-    pthread_sigmask(SIG_UNBLOCK, sigflags, NULL);
-}
-
-#define DECLARE_SIGSET(name) sigset_t name
-
-#else   /* !defined(_WIN32) */
-
-#define lock(sigflags) ((void)0)
-#define unlock(sigflags) ((void)0)
-#define DECLARE_SIGSET(name)
-
-#endif  /* !defined(_WIN32) */
-
 #if FAKE_LOG_DEVICE
 static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1 };
 #else
@@ -305,15 +275,17 @@
      */
     ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1));
     if (ret < 0) {
-        DECLARE_SIGSET(sigflags);
-
         ret = -errno;
         if (ret == -ENOTCONN) {
-            lock(&sigflags);
+#if !defined(_WIN32)
+            pthread_mutex_lock(&log_init_lock);
+#endif
             close(logd_fd);
             logd_fd = -1;
             ret = __write_to_log_initialize();
-            unlock(&sigflags);
+#if !defined(_WIN32)
+            pthread_mutex_unlock(&log_init_lock);
+#endif
 
             if (ret < 0) {
                 return ret;
@@ -357,16 +329,18 @@
 
 static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
 {
-    DECLARE_SIGSET(sigflags);
-
-    lock(&sigflags);
+#if !defined(_WIN32)
+    pthread_mutex_lock(&log_init_lock);
+#endif
 
     if (write_to_log == __write_to_log_init) {
         int ret;
 
         ret = __write_to_log_initialize();
         if (ret < 0) {
-            unlock(&sigflags);
+#if !defined(_WIN32)
+            pthread_mutex_unlock(&log_init_lock);
+#endif
 #if (FAKE_LOG_DEVICE == 0)
             if (pstore_fd >= 0) {
                 __write_to_log_daemon(log_id, vec, nr);
@@ -378,7 +352,9 @@
         write_to_log = __write_to_log_daemon;
     }
 
-    unlock(&sigflags);
+#if !defined(_WIN32)
+    pthread_mutex_unlock(&log_init_lock);
+#endif
 
     return write_to_log(log_id, vec, nr);
 }
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index c2f71d1..fd5c066 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -191,9 +191,7 @@
         prio = *msg;
         tag = msg + 1;
     }
-    if (!__android_log_is_loggable(prio, tag,
-                                   ANDROID_LOG_VERBOSE |
-                                   ANDROID_LOGGABLE_FLAG_NOT_WITHIN_SIGNAL)) {
+    if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
         // Log traffic received to total
         pthread_mutex_lock(&mLogElementsLock);
         stats.add(elem);
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index f10dccf..c4c302b 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -107,9 +107,7 @@
         LogBuffer *parent) {
     static const char tag[] = "chatty";
 
-    if (!__android_log_is_loggable(ANDROID_LOG_INFO, tag,
-                                   ANDROID_LOG_VERBOSE |
-                                   ANDROID_LOGGABLE_FLAG_NOT_WITHIN_SIGNAL)) {
+    if (!__android_log_is_loggable(ANDROID_LOG_INFO, tag, ANDROID_LOG_VERBOSE)) {
         return 0;
     }
 
diff --git a/metricsd/metrics_daemon.cc b/metricsd/metrics_daemon.cc
index b606fd0..e711660 100644
--- a/metricsd/metrics_daemon.cc
+++ b/metricsd/metrics_daemon.cc
@@ -74,11 +74,6 @@
 const char kMeminfoFileName[] = "/proc/meminfo";
 const char kVmStatFileName[] = "/proc/vmstat";
 
-// Thermal CPU throttling.
-
-const char kMetricScaledCpuFrequencyName[] =
-    "Platform.CpuFrequencyThermalScaling";
-
 }  // namespace
 
 // Zram sysfs entries.
@@ -169,8 +164,6 @@
                          bool dbus_enabled,
                          MetricsLibraryInterface* metrics_lib,
                          const string& diskstats_path,
-                         const string& scaling_max_freq_path,
-                         const string& cpuinfo_max_freq_path,
                          const base::TimeDelta& upload_interval,
                          const string& server,
                          const base::FilePath& metrics_directory) {
@@ -221,8 +214,6 @@
   weekly_cycle_.reset(new PersistentInteger("weekly.cycle"));
   version_cycle_.reset(new PersistentInteger("version.cycle"));
 
-  scaling_max_freq_path_ = scaling_max_freq_path;
-  cpuinfo_max_freq_path_ = cpuinfo_max_freq_path;
   disk_usage_collector_.reset(new DiskUsageCollector(metrics_lib_));
   averaged_stats_collector_.reset(
       new AveragedStatisticsCollector(metrics_lib_, diskstats_path,
@@ -461,63 +452,6 @@
   averaged_stats_collector_->ScheduleWait();
 }
 
-
-bool MetricsDaemon::ReadFreqToInt(const string& sysfs_file_name, int* value) {
-  const FilePath sysfs_path(sysfs_file_name);
-  string value_string;
-  if (!base::ReadFileToString(sysfs_path, &value_string)) {
-    LOG(WARNING) << "cannot read " << sysfs_path.value().c_str();
-    return false;
-  }
-  if (!base::RemoveChars(value_string, "\n", &value_string)) {
-    LOG(WARNING) << "no newline in " << value_string;
-    // Continue even though the lack of newline is suspicious.
-  }
-  if (!base::StringToInt(value_string, value)) {
-    LOG(WARNING) << "cannot convert " << value_string << " to int";
-    return false;
-  }
-  return true;
-}
-
-void MetricsDaemon::SendCpuThrottleMetrics() {
-  // |max_freq| is 0 only the first time through.
-  static int max_freq = 0;
-  if (max_freq == -1)
-    // Give up, as sysfs did not report max_freq correctly.
-    return;
-  if (max_freq == 0 || testing_) {
-    // One-time initialization of max_freq.  (Every time when testing.)
-    if (!ReadFreqToInt(cpuinfo_max_freq_path_, &max_freq)) {
-      max_freq = -1;
-      return;
-    }
-    if (max_freq == 0) {
-      LOG(WARNING) << "sysfs reports 0 max CPU frequency\n";
-      max_freq = -1;
-      return;
-    }
-    if (max_freq % 10000 == 1000) {
-      // Special case: system has turbo mode, and max non-turbo frequency is
-      // max_freq - 1000.  This relies on "normal" (non-turbo) frequencies
-      // being multiples of (at least) 10 MHz.  Although there is no guarantee
-      // of this, it seems a fairly reasonable assumption.  Otherwise we should
-      // read scaling_available_frequencies, sort the frequencies, compare the
-      // two highest ones, and check if they differ by 1000 (kHz) (and that's a
-      // hack too, no telling when it will change).
-      max_freq -= 1000;
-    }
-  }
-  int scaled_freq = 0;
-  if (!ReadFreqToInt(scaling_max_freq_path_, &scaled_freq))
-    return;
-  // Frequencies are in kHz.  If scaled_freq > max_freq, turbo is on, but
-  // scaled_freq is not the actual turbo frequency.  We indicate this situation
-  // with a 101% value.
-  int percent = scaled_freq > max_freq ? 101 : scaled_freq / (max_freq / 100);
-  SendLinearSample(kMetricScaledCpuFrequencyName, percent, 101, 102);
-}
-
 void MetricsDaemon::ScheduleMeminfoCallback(int wait) {
   if (testing_) {
     return;
diff --git a/metricsd/metrics_daemon.h b/metricsd/metrics_daemon.h
index f12b02e..54ae188 100644
--- a/metricsd/metrics_daemon.h
+++ b/metricsd/metrics_daemon.h
@@ -51,8 +51,6 @@
             bool dbus_enabled,
             MetricsLibraryInterface* metrics_lib,
             const std::string& diskstats_path,
-            const std::string& cpuinfo_max_freq_path,
-            const std::string& scaling_max_freq_path,
             const base::TimeDelta& upload_interval,
             const std::string& server,
             const base::FilePath& metrics_directory);
@@ -92,12 +90,10 @@
   FRIEND_TEST(MetricsDaemonTest, ProcessUncleanShutdown);
   FRIEND_TEST(MetricsDaemonTest, ProcessUserCrash);
   FRIEND_TEST(MetricsDaemonTest, ReportCrashesDailyFrequency);
-  FRIEND_TEST(MetricsDaemonTest, ReadFreqToInt);
   FRIEND_TEST(MetricsDaemonTest, ReportKernelCrashInterval);
   FRIEND_TEST(MetricsDaemonTest, ReportUncleanShutdownInterval);
   FRIEND_TEST(MetricsDaemonTest, ReportUserCrashInterval);
   FRIEND_TEST(MetricsDaemonTest, SendSample);
-  FRIEND_TEST(MetricsDaemonTest, SendCpuThrottleMetrics);
   FRIEND_TEST(MetricsDaemonTest, SendZramMetrics);
 
   // Type of scale to use for meminfo histograms.  For most of them we use
@@ -215,12 +211,6 @@
   // Parses meminfo data and sends it to UMA.
   bool ProcessMemuse(const std::string& meminfo_raw);
 
-  // Sends stats for thermal CPU throttling.
-  void SendCpuThrottleMetrics();
-
-  // Reads an integer CPU frequency value from sysfs.
-  bool ReadFreqToInt(const std::string& sysfs_file_name, int* value);
-
   // Reads the current OS version from /etc/lsb-release and hashes it
   // to a unsigned 32-bit int.
   uint32_t GetOsVersionHash();
@@ -301,9 +291,6 @@
   scoped_ptr<DiskUsageCollector> disk_usage_collector_;
   scoped_ptr<AveragedStatisticsCollector> averaged_stats_collector_;
 
-  std::string scaling_max_freq_path_;
-  std::string cpuinfo_max_freq_path_;
-
   base::TimeDelta upload_interval_;
   std::string server_;
 
diff --git a/metricsd/metrics_daemon_main.cc b/metricsd/metrics_daemon_main.cc
index 8573f68..9bb67e8 100644
--- a/metricsd/metrics_daemon_main.cc
+++ b/metricsd/metrics_daemon_main.cc
@@ -25,10 +25,6 @@
 #include "constants.h"
 #include "metrics_daemon.h"
 
-const char kScalingMaxFreqPath[] =
-    "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq";
-const char kCpuinfoMaxFreqPath[] =
-    "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
 
 // Returns the path to the disk stats in the sysfs.  Returns the null string if
 // it cannot find the disk stats file.
@@ -112,8 +108,6 @@
               FLAGS_withdbus,
               &metrics_lib,
               MetricsMainDiskStatsPath(),
-              kScalingMaxFreqPath,
-              kCpuinfoMaxFreqPath,
               base::TimeDelta::FromSeconds(FLAGS_upload_interval_secs),
               FLAGS_server,
               base::FilePath(FLAGS_metrics_directory));
diff --git a/metricsd/metrics_daemon_test.cc b/metricsd/metrics_daemon_test.cc
index d3c9a23..2e8a85b 100644
--- a/metricsd/metrics_daemon_test.cc
+++ b/metricsd/metrics_daemon_test.cc
@@ -45,11 +45,6 @@
   virtual void SetUp() {
     brillo::FlagHelper::Init(0, nullptr, "");
     EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
-    scaling_max_freq_path_ = temp_dir_.path().Append("scaling_max");
-    cpu_max_freq_path_ = temp_dir_.path().Append("cpu_freq_max");
-
-    CreateUint64ValueFile(cpu_max_freq_path_, 10000000);
-    CreateUint64ValueFile(scaling_max_freq_path_, 10000000);
 
     chromeos_metrics::PersistentInteger::SetMetricsDirectory(
         temp_dir_.path().value());
@@ -58,8 +53,6 @@
                  true,
                  &metrics_lib_,
                  "",
-                 scaling_max_freq_path_.value(),
-                 cpu_max_freq_path_.value(),
                  base::TimeDelta::FromMinutes(30),
                  metrics::kMetricsServer,
                  temp_dir_.path());
@@ -120,10 +113,6 @@
   // Temporary directory used for tests.
   base::ScopedTempDir temp_dir_;
 
-  // Path for the fake files.
-  base::FilePath scaling_max_freq_path_;
-  base::FilePath cpu_max_freq_path_;
-
   // Mocks. They are strict mock so that all unexpected
   // calls are marked as failures.
   StrictMock<MetricsLibraryMock> metrics_lib_;
@@ -209,33 +198,6 @@
   EXPECT_FALSE(daemon_.ProcessMeminfo(meminfo));
 }
 
-TEST_F(MetricsDaemonTest, ReadFreqToInt) {
-  const int fake_scaled_freq = 1666999;
-  const int fake_max_freq = 2000000;
-  int scaled_freq = 0;
-  int max_freq = 0;
-  CreateUint64ValueFile(scaling_max_freq_path_, fake_scaled_freq);
-  CreateUint64ValueFile(cpu_max_freq_path_, fake_max_freq);
-  EXPECT_TRUE(daemon_.testing_);
-  EXPECT_TRUE(daemon_.ReadFreqToInt(scaling_max_freq_path_.value(),
-                                    &scaled_freq));
-  EXPECT_TRUE(daemon_.ReadFreqToInt(cpu_max_freq_path_.value(), &max_freq));
-  EXPECT_EQ(fake_scaled_freq, scaled_freq);
-  EXPECT_EQ(fake_max_freq, max_freq);
-}
-
-TEST_F(MetricsDaemonTest, SendCpuThrottleMetrics) {
-  CreateUint64ValueFile(cpu_max_freq_path_, 2001000);
-  // Test the 101% and 100% cases.
-  CreateUint64ValueFile(scaling_max_freq_path_, 2001000);
-  EXPECT_TRUE(daemon_.testing_);
-  EXPECT_CALL(metrics_lib_, SendEnumToUMA(_, 101, 101));
-  daemon_.SendCpuThrottleMetrics();
-  CreateUint64ValueFile(scaling_max_freq_path_, 2000000);
-  EXPECT_CALL(metrics_lib_, SendEnumToUMA(_, 100, 101));
-  daemon_.SendCpuThrottleMetrics();
-}
-
 TEST_F(MetricsDaemonTest, SendZramMetrics) {
   EXPECT_TRUE(daemon_.testing_);