Merge the 2019-10-05 SPL branch from AOSP-Partner

* security-aosp-nyc-mr2-release:
  Fix a memory leak in gatekeeper.

Change-Id: If3760009ba30d79649abb51b2310896fda56105a
diff --git a/adb/usb_linux_client.cpp b/adb/usb_linux_client.cpp
index 0ba6b4b..c10b48c 100644
--- a/adb/usb_linux_client.cpp
+++ b/adb/usb_linux_client.cpp
@@ -400,35 +400,33 @@
     v2_descriptor.os_header = os_desc_header;
     v2_descriptor.os_desc = os_desc_compat;
 
-    if (h->control < 0) { // might have already done this before
-        D("OPENING %s", USB_FFS_ADB_EP0);
-        h->control = adb_open(USB_FFS_ADB_EP0, O_RDWR);
-        if (h->control < 0) {
-            D("[ %s: cannot open control endpoint: errno=%d]", USB_FFS_ADB_EP0, errno);
+    D("OPENING %s", USB_FFS_ADB_EP0);
+    h->control = adb_open(USB_FFS_ADB_EP0, O_RDWR);
+    if (h->control < 0) {
+        D("[ %s: cannot open control endpoint: errno=%d]", USB_FFS_ADB_EP0, errno);
+        goto err;
+    }
+
+    ret = adb_write(h->control, &v2_descriptor, sizeof(v2_descriptor));
+    if (ret < 0) {
+        v1_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC);
+        v1_descriptor.header.length = cpu_to_le32(sizeof(v1_descriptor));
+        v1_descriptor.header.fs_count = 3;
+        v1_descriptor.header.hs_count = 3;
+        v1_descriptor.fs_descs = fs_descriptors;
+        v1_descriptor.hs_descs = hs_descriptors;
+        D("[ %s: Switching to V1_descriptor format errno=%d ]", USB_FFS_ADB_EP0, errno);
+        ret = adb_write(h->control, &v1_descriptor, sizeof(v1_descriptor));
+        if (ret < 0) {
+            D("[ %s: write descriptors failed: errno=%d ]", USB_FFS_ADB_EP0, errno);
             goto err;
         }
+    }
 
-        ret = adb_write(h->control, &v2_descriptor, sizeof(v2_descriptor));
-        if (ret < 0) {
-            v1_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC);
-            v1_descriptor.header.length = cpu_to_le32(sizeof(v1_descriptor));
-            v1_descriptor.header.fs_count = 3;
-            v1_descriptor.header.hs_count = 3;
-            v1_descriptor.fs_descs = fs_descriptors;
-            v1_descriptor.hs_descs = hs_descriptors;
-            D("[ %s: Switching to V1_descriptor format errno=%d ]", USB_FFS_ADB_EP0, errno);
-            ret = adb_write(h->control, &v1_descriptor, sizeof(v1_descriptor));
-            if (ret < 0) {
-                D("[ %s: write descriptors failed: errno=%d ]", USB_FFS_ADB_EP0, errno);
-                goto err;
-            }
-        }
-
-        ret = adb_write(h->control, &strings, sizeof(strings));
-        if (ret < 0) {
-            D("[ %s: writing strings failed: errno=%d]", USB_FFS_ADB_EP0, errno);
-            goto err;
-        }
+    ret = adb_write(h->control, &strings, sizeof(strings));
+    if (ret < 0) {
+        D("[ %s: writing strings failed: errno=%d]", USB_FFS_ADB_EP0, errno);
+        goto err;
     }
 
     h->bulk_out = adb_open(USB_FFS_ADB_OUT, O_RDWR);
@@ -556,6 +554,7 @@
     h->kicked = false;
     adb_close(h->bulk_out);
     adb_close(h->bulk_in);
+    adb_close(h->control);
     // Notify usb_adb_open_thread to open a new connection.
     adb_mutex_lock(&h->lock);
     h->open_new_connection = true;
diff --git a/debuggerd/backtrace.cpp b/debuggerd/backtrace.cpp
index 8f4a53f..c5126c5 100644
--- a/debuggerd/backtrace.cpp
+++ b/debuggerd/backtrace.cpp
@@ -39,6 +39,9 @@
 
 #include "utility.h"
 
+#define MAX_FRAMES_FROM_TOP_TO_CHECK 7
+#define LIB_ART_NAME "libart"
+
 static void dump_process_header(log_t* log, pid_t pid) {
   char path[PATH_MAX];
   char procnamebuf[1024];
@@ -113,8 +116,45 @@
   dump_process_footer(&log, pid);
 }
 
+void check_coredump_criteria (std::string log, int frame_num) {
+  ALOGI("coredump_criteria: checking backtrace-frame %d in victim thread, signal = %d",
+      frame_num, coredump_signal);
+  size_t len = log.length();
+  for (size_t i = 0; i < len; i++ ) {
+    log[i] = tolower(log[i]);
+  }
+
+  size_t found = log.find(LIB_ART_NAME);
+
+  // Criterion 2: (Check tombstone.cpp for the fisrt one)
+  // Of course, if numero uno frame has libart in it, dump core without much ado
+  if ((found != std::string::npos) && (frame_num == 0)) {
+    ALOGI("coredump_criteria: found %s in first frame, coredump-criteria met", LIB_ART_NAME);
+    force_coredump_generation = true;
+    return;
+  }
+
+  // Criterion 3:
+  // If a frame(less than MAX_FRAMES_FROM_TOP_TO_CHECK) has libart in it,
+  // and the accompanying signal is a SIGABRT, dump the core
+  if ((found != std::string::npos) && (coredump_signal == SIGABRT)) {
+    ALOGI("coredump_criteria: found %s and signal=SIGABRT, coredump-criteria met", LIB_ART_NAME);
+    force_coredump_generation = true;
+    return;
+  }
+  /* Append more lame rules above this line */
+}
+
 void dump_backtrace_to_log(Backtrace* backtrace, log_t* log, const char* prefix) {
   for (size_t i = 0; i < backtrace->NumFrames(); i++) {
+    // Check for coredump-criteria only in userdebug/eng builds(if enabled), if:
+    // 1) the current thread was the thread that originally got the fatal signal
+    // 2) If no coredump_criteria has been met until now
+    // 3) the current frame number is less than a defined(and customizable) upper-limit
+    if (coredump_enabled && victim_thread &&
+       (!force_coredump_generation) && (i < MAX_FRAMES_FROM_TOP_TO_CHECK)) {
+      check_coredump_criteria(backtrace->FormatFrameData(i), i);
+    }
     _LOG(log, logtype::BACKTRACE, "%s%s\n", prefix, backtrace->FormatFrameData(i).c_str());
   }
 }
diff --git a/debuggerd/backtrace.h b/debuggerd/backtrace.h
index acd5eaa..4213363 100644
--- a/debuggerd/backtrace.h
+++ b/debuggerd/backtrace.h
@@ -35,4 +35,10 @@
 /* Dumps the backtrace in the backtrace data structure to the log. */
 void dump_backtrace_to_log(Backtrace* backtrace, log_t* log, const char* prefix);
 
+// Control-parameters for forced coredump-generation
+extern bool force_coredump_generation;
+extern bool coredump_enabled;
+extern int coredump_signal;
+extern bool victim_thread;
+
 #endif // _DEBUGGERD_BACKTRACE_H
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 7b57c20..bf3c53c 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -32,7 +32,7 @@
 #include <sys/wait.h>
 #include <sys/un.h>
 #include <time.h>
-
+#include <sys/resource.h>
 #include <memory>
 #include <set>
 #include <string>
@@ -74,6 +74,10 @@
   int32_t original_si_code;
 };
 
+bool force_coredump_generation;
+bool coredump_enabled;
+int coredump_signal;
+
 static void wait_for_user_action(const debugger_request_t& request) {
   // Explain how to attach the debugger.
   ALOGI("***********************************************************\n"
@@ -526,6 +530,7 @@
       case SIGTRAP:
         ALOGV("stopped -- fatal signal\n");
         *crash_signal = signal;
+        coredump_signal = signal;
         engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings, signal,
                           request.original_si_code, request.abort_msg_address, amfd_data);
         break;
@@ -652,14 +657,15 @@
   }
 
   bool succeeded = false;
+  force_coredump_generation = false;
 
-  // Now that we've done everything that requires privileges, we can drop them.
-  if (!drop_privileges()) {
-    ALOGE("debuggerd: failed to drop privileges, exiting");
-    _exit(1);
-  }
+  char value1[PROPERTY_VALUE_MAX], value2[PROPERTY_VALUE_MAX];
+  property_get("ro.debuggable", value1, "0");
+  property_get("persist.coredump.disable", value2, "0");
+  coredump_enabled = ((value1[0] == '1') && (value2[0] == '0'));
 
   int crash_signal = SIGKILL;
+  coredump_signal = SIGKILL;
   succeeded = perform_dump(request, fd, tombstone_fd, backtrace_map.get(), siblings,
                            &crash_signal, amfd_data.get());
   if (succeeded) {
@@ -670,6 +676,22 @@
     }
   }
 
+  if (coredump_enabled && force_coredump_generation) {
+    struct rlimit r1;
+    r1.rlim_cur = RLIM_INFINITY;
+    r1.rlim_max = RLIM_INFINITY;
+    ALOGE("debuggerd: setting resource-limit for crashing process to dump core");
+    if (prlimit(request.pid, RLIMIT_CORE, &r1, NULL) == -1) {
+      ALOGE("debuggerd: Failed to set RLIMIT_CORE for pid; %d", request.pid);
+    }
+  }
+
+  // Now that we've done everything that requires privileges, we can drop them.
+  if (!drop_privileges()) {
+    ALOGE("debuggerd: failed to drop privileges, exiting");
+    _exit(1);
+  }
+
   if (attach_gdb) {
     // Tell the signal process to send SIGSTOP to the target.
     if (!send_signal(request.pid, 0, SIGSTOP)) {
diff --git a/debuggerd/test/tombstone_test.cpp b/debuggerd/test/tombstone_test.cpp
index 58d640e..866da01 100644
--- a/debuggerd/test/tombstone_test.cpp
+++ b/debuggerd/test/tombstone_test.cpp
@@ -34,6 +34,11 @@
 // Including it, also allows us to override the ptrace function.
 #define ptrace ptrace_fake
 
+// Hack for extern variables declared in ../backtrace.h
+// This avoids a compilation error.
+bool force_coredump_generation = false;
+bool coredump_enabled = false;
+
 #include "tombstone.cpp"
 
 void dump_registers(log_t*, pid_t) {
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index dfdf29c..c69025a 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -56,6 +56,10 @@
 #define TOMBSTONE_DIR   "/data/tombstones"
 #define TOMBSTONE_TEMPLATE (TOMBSTONE_DIR"/tombstone_%02d")
 
+// victim_thread will be true only while dumping logs for
+// the thread that actually crashed.
+bool victim_thread = false;
+
 static bool signal_has_si_addr(int sig) {
   switch (sig) {
     case SIGBUS:
@@ -198,6 +202,22 @@
        signal, get_signame(signal), si.si_code, get_sigcode(signal, si.si_code), addr_desc);
 }
 
+bool is_heaptaskdaemon(char* threadname) {
+  char c[20] = "heaptaskdaemon";
+  char *target = c;
+
+  if (strlen(threadname) != strlen(target))
+    return false;
+
+  for ( ; *threadname && *target; threadname++, target++) {
+    if (tolower(*threadname) != tolower(*target)) {
+      return false;
+    }
+  }
+  ALOGI("coredump_criteria: victim-threadname is HeapTaskDaemon");
+  return true;
+}
+
 static void dump_thread_info(log_t* log, pid_t pid, pid_t tid) {
   char path[64];
   char threadnamebuf[1024];
@@ -233,6 +253,13 @@
 
   _LOG(log, logtype::HEADER, "pid: %d, tid: %d, name: %s  >>> %s <<<\n", pid, tid,
        threadname ? threadname : "UNKNOWN", procname ? procname : "UNKNOWN");
+
+  // If the thread that crashed is HeapTaskDaemon,
+  // we are in the process of garbage-collection.
+  // Force core-dump generation.
+  if (coredump_enabled && victim_thread && threadname && is_heaptaskdaemon(threadname)) {
+    force_coredump_generation = true;
+  }
 }
 
 static void dump_stack_segment(
@@ -448,6 +475,7 @@
 static void dump_thread(log_t* log, pid_t pid, pid_t tid, BacktraceMap* map, int signal,
                         int si_code, uintptr_t abort_msg_address, bool primary_thread) {
   log->current_tid = tid;
+  victim_thread = primary_thread;
   if (!primary_thread) {
     _LOG(log, logtype::THREAD, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
   }
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
old mode 100644
new mode 100755
index 387f708..86e0f7a
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -294,6 +294,49 @@
 }
 
 /*
+ * Tries to check if filesystem is clean.
+ * partition is appointed by argument data_path.
+ *
+ * property sys.crash.detect indicates filesystem is not clean(if true)
+ */
+static void check_fs_clean(char *data_path, char *fs_type)
+{
+    char super_buf[1024];
+    struct ext4_super_block *sb;
+    int fd;
+
+    if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) {
+        fd = open(data_path, O_RDONLY);
+        if (fd < 0) {
+             ERROR("open %s failed\n", data_path);
+             return;
+        }
+
+        if (TEMP_FAILURE_RETRY(lseek(fd, 1024, SEEK_SET)) < 0 ||
+             TEMP_FAILURE_RETRY(read(fd, super_buf, 1024)) != 1024) {
+             ERROR("read super block failed\n");
+        } else {
+             sb = (struct ext4_super_block *)super_buf;
+
+             if (sb->s_magic != EXT4_SUPER_MAGIC) {
+                 ERROR("from super block, it is not ext{234}\n");
+                 close(fd);
+                 return;
+             }
+
+             if (sb->s_feature_incompat & cpu_to_le32(EXT4_FEATURE_INCOMPAT_RECOVER)) {
+                 INFO("Unclean fs\n");
+                 property_set("sys.crash.detect", "true");
+             } else {
+                 property_set("sys.crash.detect", "false");
+             }
+        }
+        close(fd);
+    }
+}
+
+
+/*
  * Tries to mount any of the consecutive fstab entries that match
  * the mountpoint of the one given by fstab->recs[start_idx].
  *
@@ -333,6 +376,13 @@
                 continue;
             }
 
+            /* do filesystem clean check */
+            if (!strcmp(fstab->recs[i].mount_point, "/data") &&
+                         fstab->recs[i].fs_mgr_flags & MF_CRASHCHECK) {
+                check_fs_clean(fstab->recs[i].blk_device,
+                                          fstab->recs[i].fs_type);
+            }
+
             if (fstab->recs[i].fs_mgr_flags & MF_CHECK) {
                 check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
                          fstab->recs[i].mount_point);
@@ -484,6 +534,52 @@
     }
 }
 
+/*
+ * Reads the kernel cmdline to check if MDTP is activated.
+ * When MDTP is activated, kernel cmdline will have the word 'mdtp'.
+ */
+int fs_mgr_is_mdtp_activated()
+{
+      char cmdline[2048];
+      char *ptr;
+      int fd;
+      static int mdtp_activated = 0;
+      static int mdtp_activated_set = 0;
+
+      if (mdtp_activated_set) {
+          return mdtp_activated;
+      }
+
+      fd = open("/proc/cmdline", O_RDONLY);
+      if (fd >= 0) {
+          int n = read(fd, cmdline, sizeof(cmdline) - 1);
+          if (n < 0) n = 0;
+
+          /* get rid of trailing newline, it happens */
+          if (n > 0 && cmdline[n-1] == '\n') n--;
+
+          cmdline[n] = 0;
+          close(fd);
+      } else {
+          cmdline[0] = 0;
+      }
+
+      ptr = cmdline;
+      while (ptr && *ptr) {
+          char *x = strchr(ptr, ' ');
+          if (x != 0) *x++ = 0;
+          if (!strcmp(ptr,"mdtp")) {
+            mdtp_activated = 1;
+            break;
+          }
+          ptr = x;
+      }
+
+      mdtp_activated_set = 1;
+
+      return mdtp_activated;
+}
+
 /* When multiple fstab records share the same mount_point, it will
  * try to mount each one in turn, and ignore any duplicates after a
  * first successful mount.
@@ -497,12 +593,24 @@
     int mret = -1;
     int mount_errno = 0;
     int attempted_idx = -1;
+    char propbuf[PROPERTY_VALUE_MAX];
+    bool is_ffbm = false;
 
     if (!fstab) {
         return -1;
     }
+    /**get boot mode*/
+    property_get("ro.bootmode", propbuf, "");
+    if (strncmp(propbuf, "ffbm", 4) == 0)
+        is_ffbm = true;
 
     for (i = 0; i < fstab->num_entries; i++) {
+        /* Skip userdata partition in ffbm mode */
+        if (is_ffbm && !strcmp(fstab->recs[i].mount_point, "/data")){
+            INFO("ffbm mode,skip mount userdata");
+            continue;
+        }
+
         /* Don't mount entries that are managed by vold or not for the mount mode*/
         if ((fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) ||
              ((mount_mode == MOUNT_MODE_LATE) && !fs_mgr_is_latemount(&fstab->recs[i])) ||
@@ -549,102 +657,117 @@
                 continue;
             }
         }
-        int last_idx_inspected;
-        int top_idx = i;
 
-        mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx);
-        i = last_idx_inspected;
-        mount_errno = errno;
-
-        /* Deal with encryptability. */
-        if (!mret) {
-            int status = handle_encryptable(&fstab->recs[attempted_idx]);
-
-            if (status == FS_MGR_MNTALL_FAIL) {
-                /* Fatal error - no point continuing */
-                return status;
+        if (fs_mgr_is_mdtp_activated() && ((fstab->recs[i].fs_mgr_flags & MF_FORCECRYPT) ||
+            device_is_force_encrypted())) {
+            INFO("%s(): mdtp activated, blkdev %s for mount %s type %s expected to be encrypted)\n",
+                 __func__, fstab->recs[i].blk_device, fstab->recs[i].mount_point,
+                 fstab->recs[i].fs_type);
+            if (fs_mgr_do_tmpfs_mount(fstab->recs[i].mount_point) < 0) {
+                ++error_count;
+                continue;
             }
 
-            if (status != FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) {
-                if (encryptable != FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) {
-                    // Log and continue
-                    ERROR("Only one encryptable/encrypted partition supported\n");
+            encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED;
+
+        } else {
+            int last_idx_inspected;
+            int top_idx = i;
+
+            mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx);
+            i = last_idx_inspected;
+            mount_errno = errno;
+
+            /* Deal with encryptability. */
+            if (!mret) {
+                int status = handle_encryptable(&fstab->recs[attempted_idx]);
+
+                if (status == FS_MGR_MNTALL_FAIL) {
+                    /* Fatal error - no point continuing */
+                    return status;
                 }
-                encryptable = status;
-            }
 
-            /* Success!  Go get the next one */
-            continue;
-        }
-
-        /* mount(2) returned an error, handle the encryptable/formattable case */
-        bool wiped = partition_wiped(fstab->recs[top_idx].blk_device);
-        if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
-            fs_mgr_is_formattable(&fstab->recs[top_idx]) && wiped) {
-            /* top_idx and attempted_idx point at the same partition, but sometimes
-             * at two different lines in the fstab.  Use the top one for formatting
-             * as that is the preferred one.
-             */
-            ERROR("%s(): %s is wiped and %s %s is formattable. Format it.\n", __func__,
-                  fstab->recs[top_idx].blk_device, fstab->recs[top_idx].mount_point,
-                  fstab->recs[top_idx].fs_type);
-            if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) &&
-                strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) {
-                int fd = open(fstab->recs[top_idx].key_loc, O_WRONLY, 0644);
-                if (fd >= 0) {
-                    INFO("%s(): also wipe %s\n", __func__, fstab->recs[top_idx].key_loc);
-                    wipe_block_device(fd, get_file_size(fd));
-                    close(fd);
-                } else {
-                    ERROR("%s(): %s wouldn't open (%s)\n", __func__,
-                          fstab->recs[top_idx].key_loc, strerror(errno));
+                if (status != FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) {
+                    if (encryptable != FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) {
+                        // Log and continue
+                        ERROR("Only one encryptable/encrypted partition supported\n");
+                    }
+                    encryptable = status;
                 }
-            }
-            if (fs_mgr_do_format(&fstab->recs[top_idx]) == 0) {
-                /* Let's replay the mount actions. */
-                i = top_idx - 1;
-                continue;
-            } else {
-                ERROR("%s(): Format failed. Suggest recovery...\n", __func__);
-                encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY;
+
+                /* Success!  Go get the next one */
                 continue;
             }
-        }
-        if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
-            fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) {
-            if (wiped) {
-                ERROR("%s(): %s is wiped and %s %s is encryptable. Suggest recovery...\n", __func__,
-                      fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
-                      fstab->recs[attempted_idx].fs_type);
-                encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY;
-                continue;
-            } else {
-                /* Need to mount a tmpfs at this mountpoint for now, and set
-                 * properties that vold will query later for decrypting
+
+            /* mount(2) returned an error, handle the encryptable/formattable case */
+            bool wiped = partition_wiped(fstab->recs[top_idx].blk_device);
+            if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
+                fs_mgr_is_formattable(&fstab->recs[top_idx]) && wiped) {
+                /* top_idx and attempted_idx point at the same partition, but sometimes
+                 * at two different lines in the fstab.  Use the top one for formatting
+                 * as that is the preferred one.
                  */
-                ERROR("%s(): possibly an encryptable blkdev %s for mount %s type %s )\n", __func__,
-                      fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
-                      fstab->recs[attempted_idx].fs_type);
-                if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) {
-                    ++error_count;
+                ERROR("%s(): %s is wiped and %s %s is formattable. Format it.\n", __func__,
+                      fstab->recs[top_idx].blk_device, fstab->recs[top_idx].mount_point,
+                      fstab->recs[top_idx].fs_type);
+                if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) &&
+                    strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) {
+                    int fd = open(fstab->recs[top_idx].key_loc, O_WRONLY, 0644);
+                    if (fd >= 0) {
+                        INFO("%s(): also wipe %s\n", __func__, fstab->recs[top_idx].key_loc);
+                        wipe_block_device(fd, get_file_size(fd));
+                        close(fd);
+                    } else {
+                        ERROR("%s(): %s wouldn't open (%s)\n", __func__,
+                              fstab->recs[top_idx].key_loc, strerror(errno));
+                    }
+                }
+                if (fs_mgr_do_format(&fstab->recs[top_idx]) == 0) {
+                    /* Let's replay the mount actions. */
+                    i = top_idx - 1;
+                    continue;
+                } else {
+                    ERROR("%s(): Format failed. Suggest recovery...\n", __func__);
+                    encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY;
                     continue;
                 }
             }
-            encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED;
-        } else {
-            if (fs_mgr_is_nofail(&fstab->recs[attempted_idx])) {
-                ERROR("Ignoring failure to mount an un-encryptable or wiped partition on"
-                       "%s at %s options: %s error: %s\n",
-                       fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
-                       fstab->recs[attempted_idx].fs_options, strerror(mount_errno));
+            if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
+                fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) {
+                if (wiped) {
+                    ERROR("%s(): %s is wiped and %s %s is encryptable. Suggest recovery...\n", __func__,
+                          fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
+                          fstab->recs[attempted_idx].fs_type);
+                    encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY;
+                    continue;
+                } else {
+                    /* Need to mount a tmpfs at this mountpoint for now, and set
+                     * properties that vold will query later for decrypting
+                     */
+                    ERROR("%s(): possibly an encryptable blkdev %s for mount %s type %s )\n", __func__,
+                          fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
+                          fstab->recs[attempted_idx].fs_type);
+                    if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) {
+                        ++error_count;
+                        continue;
+                    }
+                }
+                encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED;
             } else {
-                ERROR("Failed to mount an un-encryptable or wiped partition on"
-                       "%s at %s options: %s error: %s\n",
-                       fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
-                       fstab->recs[attempted_idx].fs_options, strerror(mount_errno));
-                ++error_count;
+                if (fs_mgr_is_nofail(&fstab->recs[attempted_idx])) {
+                    ERROR("Ignoring failure to mount an un-encryptable or wiped partition on"
+                           "%s at %s options: %s error: %s\n",
+                           fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
+                           fstab->recs[attempted_idx].fs_options, strerror(mount_errno));
+                } else {
+                    ERROR("Failed to mount an un-encryptable or wiped partition on"
+                           "%s at %s options: %s error: %s\n",
+                           fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
+                           fstab->recs[attempted_idx].fs_options, strerror(mount_errno));
+                    ++error_count;
+                }
+                continue;
             }
-            continue;
         }
     }
 
@@ -693,6 +816,21 @@
             wait_for_file(n_blk_device, WAIT_TIMEOUT);
         }
 
+        char encrypt_data_partition[1024];
+
+        /* do filesystem check after crypto device created but before mount it */
+        if (!strcmp(fstab->recs[i].mount_point, "/data") &&
+                               fstab->recs[i].fs_mgr_flags & MF_CRASHCHECK) {
+            property_get("ro.crypto.fs_crypto_blkdev", encrypt_data_partition, "");
+            INFO("data_partition=%s\n", encrypt_data_partition);
+
+            if (strcmp(encrypt_data_partition, "")) {
+                check_fs_clean(encrypt_data_partition, fstab->recs[i].fs_type);
+            } else {
+                INFO("crypto device not created!\n");
+            }
+        }
+
         if (fstab->recs[i].fs_mgr_flags & MF_CHECK) {
             check_fs(n_blk_device, fstab->recs[i].fs_type,
                      fstab->recs[i].mount_point);
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index 9225d34..8a59f28 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -80,6 +80,7 @@
     { "slotselect",  MF_SLOTSELECT },
     { "nofail",      MF_NOFAIL },
     { "latemount",   MF_LATEMOUNT },
+    { "crashcheck",   MF_CRASHCHECK },
     { "defaults",    0 },
     { 0,             0 },
 };
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 120ec5a..f0d0ed7 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -86,6 +86,7 @@
 #define MF_LATEMOUNT    0x20000
 #define MF_NOFAIL       0x40000
 #define MF_VERIFYATBOOT 0x80000
+#define MF_CRASHCHECK   0x100000
 
 #define DM_BUF_SIZE 4096
 
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 7565965..95bae90 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -119,6 +119,7 @@
 int fs_mgr_is_nofail(struct fstab_rec *fstab);
 int fs_mgr_is_latemount(struct fstab_rec *fstab);
 int fs_mgr_swapon_all(struct fstab *fstab);
+int fs_mgr_is_mdtp_activated(void);
 
 int fs_mgr_do_format(struct fstab_rec *fstab);
 
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 54d45e6..719d8d2 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -166,7 +166,10 @@
             { "USB_C", ANDROID_POWER_SUPPLY_TYPE_AC },
             { "USB_PD", ANDROID_POWER_SUPPLY_TYPE_AC },
             { "USB_PD_DRP", ANDROID_POWER_SUPPLY_TYPE_USB },
+            { "USB_HVDCP", ANDROID_POWER_SUPPLY_TYPE_AC },
+            { "USB_HVDCP_3", ANDROID_POWER_SUPPLY_TYPE_AC },
             { "Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS },
+            { "Wipower", ANDROID_POWER_SUPPLY_TYPE_WIRELESS },
             { NULL, 0 },
     };
 
@@ -174,10 +177,8 @@
         return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
 
     ret = (BatteryMonitor::PowerSupplyType)mapSysfsString(buf, supplyTypeMap);
-    if (ret < 0) {
-        KLOG_WARNING(LOG_TAG, "Unknown power supply type '%s'\n", buf);
+    if (ret < 0)
         ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
-    }
 
     return ret;
 }
@@ -263,54 +264,87 @@
     unsigned int i;
     double MaxPower = 0;
 
-    for (i = 0; i < mChargerNames.size(); i++) {
-        String8 path;
-        path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
-                          mChargerNames[i].string());
+    // reinitialize the mChargerNames vector everytime there is an update
+    String8 path;
+    DIR* dir = opendir(POWER_SUPPLY_SYSFS_PATH);
+    if (dir == NULL) {
+        KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
+    } else {
+        struct dirent* entry;
+        // reconstruct the charger strings
+        mChargerNames.clear();
+        while ((entry = readdir(dir))) {
+            const char* name = entry->d_name;
 
-        if (readFromFile(path, buf, SIZE) > 0) {
-            if (buf[0] != '0') {
+            if (!strcmp(name, ".") || !strcmp(name, ".."))
+                continue;
+
+            // Look for "type" file in each subdirectory
+            path.clear();
+            path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
+            switch(readPowerSupplyType(path)) {
+            case ANDROID_POWER_SUPPLY_TYPE_AC:
+            case ANDROID_POWER_SUPPLY_TYPE_USB:
+            case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
+                // Check if any of them is online
                 path.clear();
-                path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
-                                  mChargerNames[i].string());
-                switch(readPowerSupplyType(path)) {
-                case ANDROID_POWER_SUPPLY_TYPE_AC:
-                    props.chargerAcOnline = true;
-                    break;
-                case ANDROID_POWER_SUPPLY_TYPE_USB:
-                    props.chargerUsbOnline = true;
-                    break;
-                case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
-                    props.chargerWirelessOnline = true;
-                    break;
-                default:
-                    KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
-                                 mChargerNames[i].string());
+                path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
+                if (access(path.string(), R_OK) == 0) {
+                    mChargerNames.add(String8(name));
+                    if (readFromFile(path, buf, SIZE) > 0) {
+                        if (buf[0] != '0') {
+                            path.clear();
+                            path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
+                                              name);
+                            switch(readPowerSupplyType(path)) {
+                            case ANDROID_POWER_SUPPLY_TYPE_AC:
+                                props.chargerAcOnline = true;
+                                break;
+                            case ANDROID_POWER_SUPPLY_TYPE_USB:
+                                props.chargerUsbOnline = true;
+                                break;
+                            case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
+                                props.chargerWirelessOnline = true;
+                                break;
+                            default:
+                                KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
+                                             name);
+                            }
+
+                            //If its online, read the voltage and current for power
+                            path.clear();
+                            path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
+                                            name);
+                            int ChargingCurrent =
+                                          (access(path.string(), R_OK) == 0) ? getIntField(path) : 0;
+
+                            path.clear();
+                            path.appendFormat("%s/%s/voltage_max", POWER_SUPPLY_SYSFS_PATH,
+                                            name);
+
+                            int ChargingVoltage =
+                              (access(path.string(), R_OK) == 0) ? getIntField(path) :
+                              DEFAULT_VBUS_VOLTAGE;
+
+                            double power = ((double)ChargingCurrent / MILLION) *
+                                    ((double)ChargingVoltage / MILLION);
+                            if (MaxPower < power) {
+                                props.maxChargingCurrent = ChargingCurrent;
+                                props.maxChargingVoltage = ChargingVoltage;
+                                MaxPower = power;
+                            }
+                        }
+                    }
                 }
-                path.clear();
-                path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
-                                  mChargerNames[i].string());
-                int ChargingCurrent =
-                    (access(path.string(), R_OK) == 0) ? getIntField(path) : 0;
-
-                path.clear();
-                path.appendFormat("%s/%s/voltage_max", POWER_SUPPLY_SYSFS_PATH,
-                                  mChargerNames[i].string());
-
-                int ChargingVoltage =
-                    (access(path.string(), R_OK) == 0) ? getIntField(path) :
-                    DEFAULT_VBUS_VOLTAGE;
-
-                double power = ((double)ChargingCurrent / MILLION) *
-                        ((double)ChargingVoltage / MILLION);
-                if (MaxPower < power) {
-                    props.maxChargingCurrent = ChargingCurrent;
-                    props.maxChargingVoltage = ChargingVoltage;
-                    MaxPower = power;
-                }
-            }
-        }
-    }
+                break;
+            case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
+                break;
+            default:
+                break;
+            } //switch
+        } //while
+        closedir(dir);
+    }//else
 
     logthis = !healthd_board_battery_update(&props);
 
diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp
index 1c144b3..2118423 100644
--- a/healthd/healthd.cpp
+++ b/healthd/healthd.cpp
@@ -37,7 +37,7 @@
 
 #ifndef BOARD_PERIODIC_CHORES_INTERVAL_FAST
   // Periodic chores fast interval in seconds
-  #define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 1)
+  #define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 10)
 #else
   #define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (BOARD_PERIODIC_CHORES_INTERVAL_FAST)
 #endif
@@ -373,6 +373,9 @@
         exit(2);
     }
 
+    periodic_chores();
+    healthd_mode_ops->heartbeat();
+
     healthd_mainloop();
     KLOG_ERROR("Main loop terminated, exiting\n");
     return 3;
diff --git a/healthd/healthd_board_default.cpp b/healthd/healthd_board_default.cpp
index eb55773..960f0d2 100644
--- a/healthd/healthd_board_default.cpp
+++ b/healthd/healthd_board_default.cpp
@@ -27,3 +27,23 @@
     // return 0 to log periodic polled battery status to kernel log
     return 0;
 }
+
+void healthd_board_mode_charger_draw_battery(struct android::BatteryProperties*)
+{
+
+}
+
+void healthd_board_mode_charger_battery_update(struct android::BatteryProperties*)
+{
+
+}
+
+void healthd_board_mode_charger_set_backlight(bool)
+{
+
+}
+
+void healthd_board_mode_charger_init()
+{
+
+}
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index ccf948b..cc41b2e 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -72,7 +72,7 @@
 
 #define BATTERY_UNKNOWN_TIME    (2 * MSEC_PER_SEC)
 #define POWER_ON_KEY_TIME       (2 * MSEC_PER_SEC)
-#define UNPLUGGED_SHUTDOWN_TIME (10 * MSEC_PER_SEC)
+#define UNPLUGGED_SHUTDOWN_TIME (1 * MSEC_PER_SEC)
 
 #define LAST_KMSG_PATH          "/proc/last_kmsg"
 #define LAST_KMSG_PSTORE_PATH   "/sys/fs/pstore/console-ramoops"
@@ -93,6 +93,7 @@
 struct charger {
     bool have_battery_state;
     bool charger_connected;
+    bool charger_power_key;
     int64_t next_screen_transition;
     int64_t next_key_check;
     int64_t next_pwr_check;
@@ -404,6 +405,7 @@
              anim.cur_frame, frame.min_level,
              frame.disp_time);
     }
+    healthd_board_mode_charger_draw_battery(batt_prop);
     draw_clock(anim);
     draw_percent(anim);
 }
@@ -477,6 +479,7 @@
         init_status_display(batt_anim);
 
 #ifndef CHARGER_DISABLE_INIT_BLANK
+        healthd_board_mode_charger_set_backlight(false);
         gr_fb_blank(true);
 #endif
         minui_inited = true;
@@ -486,6 +489,8 @@
     if (batt_anim->num_cycles > 0 && batt_anim->cur_cycle == batt_anim->num_cycles) {
         reset_animation(batt_anim);
         charger->next_screen_transition = -1;
+        charger->charger_power_key = false;
+        healthd_board_mode_charger_set_backlight(false);
         gr_fb_blank(true);
         LOGV("[%" PRId64 "] animation done\n", now);
         if (charger->charger_connected)
@@ -519,9 +524,12 @@
         }
     }
 
-    /* unblank the screen  on first cycle */
-    if (batt_anim->cur_cycle == 0)
+    /* unblank the screen on first cycle */
+    if (batt_anim->cur_cycle == 0) {
         gr_fb_blank(false);
+        gr_flip();
+        healthd_board_mode_charger_set_backlight(true);
+    }
 
     /* draw the new frame (@ cur_frame) */
     redraw_screen(charger);
@@ -620,11 +628,20 @@
 
 static void process_key(struct charger *charger, int code, int64_t now)
 {
+    struct animation *batt_anim = charger->batt_anim;
     struct key_state *key = &charger->keys[code];
 
     if (code == KEY_POWER) {
         if (key->down) {
             int64_t reboot_timeout = key->timestamp + POWER_ON_KEY_TIME;
+
+            /*make sure backlight turn off before fb ready for display
+             *when press the power key */
+            if (charger->charger_power_key == false) {
+                healthd_board_mode_charger_set_backlight(false);
+                gr_fb_blank(true);
+                charger->charger_power_key = true;
+                }
             if (now >= reboot_timeout) {
                 /* We do not currently support booting from charger mode on
                    all devices. Check the property and continue booting or reboot
@@ -646,17 +663,25 @@
                  * make sure we wake up at the right-ish time to check
                  */
                 set_next_key_check(charger, key, POWER_ON_KEY_TIME);
-
-               /* Turn on the display and kick animation on power-key press
-                * rather than on key release
-                */
-                kick_animation(charger->batt_anim);
-                request_suspend(false);
             }
         } else {
-            /* if the power key got released, force screen state cycle */
             if (key->pending) {
-                kick_animation(charger->batt_anim);
+                /* If key is pressed when the animation is not running, kick
+                 * the animation and quite suspend; If key is pressed when
+                 * the animation is running, turn off the animation and request
+                 * suspend.
+                 */
+                if (!batt_anim->run) {
+                    kick_animation(batt_anim);
+                    request_suspend(false);
+                } else {
+                    reset_animation(batt_anim);
+                    charger->next_screen_transition = -1;
+                    healthd_board_mode_charger_set_backlight(false);
+                    gr_fb_blank(true);
+                    if (charger->charger_connected)
+                        request_suspend(true);
+                }
             }
         }
     }
@@ -677,6 +702,8 @@
     if (!charger->have_battery_state)
         return;
 
+    healthd_board_mode_charger_battery_update(batt_prop);
+
     if (!charger->charger_connected) {
 
         /* Last cycle would have stopped at the extreme top of battery-icon
@@ -841,6 +868,8 @@
 
     LOGW("--------------- STARTING CHARGER MODE ---------------\n");
 
+    healthd_board_mode_charger_init();
+
     ret = ev_init(input_callback, charger);
     if (!ret) {
         epollfd = ev_get_epollfd();
diff --git a/healthd/include/healthd/healthd.h b/healthd/include/healthd/healthd.h
index 17efbd6..32f7521 100644
--- a/healthd/include/healthd/healthd.h
+++ b/healthd/include/healthd/healthd.h
@@ -128,4 +128,20 @@
 
 int healthd_board_battery_update(struct android::BatteryProperties *props);
 
+//This API is called to turn on/off the display backlight incase it can't be
+//handle correcty in the display driver by calling gr_fg_blank();
+void healthd_board_mode_charger_set_backlight(bool en);
+
+//This API is called to update the battery/charging status by using the user
+//noticeable method other then the animation, such as: LEDs
+void healthd_board_mode_charger_battery_update(struct android::BatteryProperties *batt_prop);
+
+//This API is used to handle some board specific charger mode initialization,
+//such as: checking the charging is enabled or not.
+void healthd_board_mode_charger_init(void);
+
+//This API is called in the draw_battery() function to draw more infomation
+//about the battery on the animation, such as the SoC (State of Charge).
+void healthd_board_mode_charger_draw_battery(struct android::BatteryProperties *batt_prop);
+
 #endif /* _HEALTHD_H_ */
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 5ccd80e..f03346e 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -103,6 +103,11 @@
 /* The range 2900-2999 is reserved for OEM, and must never be
  * used here */
 #define AID_OEM_RESERVED_START 2900
+
+#define AID_QCOM_DIAG          2950  /* access to QTI diagnostic resources */
+#define AID_RFS                2951  /* Remote Filesystem for peripheral processors */
+#define AID_RFS_SHARED         2952  /* Shared files for Remote Filesystem for peripheral processors  */
+
 #define AID_OEM_RESERVED_END   2999
 
 /* The 3000 series are intended for use as supplemental group id's only.
@@ -118,9 +123,14 @@
 #define AID_READPROC      3009  /* Allow /proc read access */
 #define AID_WAKELOCK      3010  /* Allow system wakelock read/write access */
 
+#define AID_RFS_OLD          3012  /* DEPRECATED OLD ID FOR RFS, DO NOT USE */
+#define AID_RFS_SHARED_OLD   3013  /* DEPRECATED OLD ID FOR RFS-SHARED  */
+
 /* The range 5000-5999 is also reserved for OEM, and must never be used here. */
 #define AID_OEM_RESERVED_2_START 5000
 #define AID_OEM_RESERVED_2_END   5999
+#define AID_SENSORS       3011 /* access to /dev/socket/sensor_ctl_socket & QCCI/QCSI */
+
 
 #define AID_EVERYBODY     9997  /* shared between all apps in the same profile */
 #define AID_MISC          9998  /* access to misc storage */
@@ -212,6 +222,11 @@
     { "cache",         AID_CACHE, },
     { "diag",          AID_DIAG, },
 
+    { "qcom_diag",     AID_QCOM_DIAG, },
+
+    { "rfs",           AID_RFS, },
+    { "rfs_shared",    AID_RFS_SHARED, },
+
     { "net_bt_admin",  AID_NET_BT_ADMIN, },
     { "net_bt",        AID_NET_BT, },
     { "inet",          AID_INET, },
@@ -222,6 +237,10 @@
     { "net_bt_stack",  AID_NET_BT_STACK, },
     { "readproc",      AID_READPROC, },
     { "wakelock",      AID_WAKELOCK, },
+    { "sensors",       AID_SENSORS, },
+
+    { "rfs_old",           AID_RFS_OLD, },
+    { "rfs_shared_old",    AID_RFS_SHARED_OLD, },
 
     { "everybody",     AID_EVERYBODY, },
     { "misc",          AID_MISC, },
diff --git a/include/system/camera.h b/include/system/camera.h
index 5d0873a..6de0203 100644
--- a/include/system/camera.h
+++ b/include/system/camera.h
@@ -88,9 +88,20 @@
     // Notify on autofocus start and stop. This is useful in continuous
     // autofocus - FOCUS_MODE_CONTINUOUS_VIDEO and FOCUS_MODE_CONTINUOUS_PICTURE.
     CAMERA_MSG_FOCUS_MOVE = 0x0800,       // notifyCallback
+    CAMERA_MSG_VENDOR_START = 0x1000,
+    CAMERA_MSG_STATS_DATA = CAMERA_MSG_VENDOR_START,
+    CAMERA_MSG_META_DATA = 0x2000,
+    CAMERA_MSG_VENDOR_END = 0x8000,
     CAMERA_MSG_ALL_MSGS = 0xFFFF
 };
 
+/** meta data type in CameraMetaDataCallback */
+enum {
+    CAMERA_META_DATA_ASD = 0x001,    //ASD data
+    CAMERA_META_DATA_FD = 0x002,     //FD/FP data
+    CAMERA_META_DATA_HDR = 0x003,    //Auto HDR data
+};
+
 /** cmdType in sendCommand functions */
 enum {
     CAMERA_CMD_START_SMOOTH_ZOOM = 1,
@@ -189,7 +200,25 @@
      * IMPLEMENTATION_DEFINED, then HALv3 devices will use gralloc usage flags
      * of SW_READ_OFTEN.
      */
-    CAMERA_CMD_SET_VIDEO_FORMAT = 11
+    CAMERA_CMD_SET_VIDEO_FORMAT = 11,
+
+    CAMERA_CMD_VENDOR_START = 20,
+    /**
+     * Commands to enable/disable preview histogram
+     *
+     * Based on user's input to enable/disable histogram from the camera
+     * UI, send the appropriate command to the HAL to turn on/off the histogram
+     * stats and start sending the data to the application.
+     */
+    CAMERA_CMD_HISTOGRAM_ON = CAMERA_CMD_VENDOR_START,
+    CAMERA_CMD_HISTOGRAM_OFF = CAMERA_CMD_VENDOR_START + 1,
+    CAMERA_CMD_HISTOGRAM_SEND_DATA  = CAMERA_CMD_VENDOR_START + 2,
+    CAMERA_CMD_LONGSHOT_ON = CAMERA_CMD_VENDOR_START + 3,
+    CAMERA_CMD_LONGSHOT_OFF = CAMERA_CMD_VENDOR_START + 4,
+    CAMERA_CMD_STOP_LONGSHOT = CAMERA_CMD_VENDOR_START + 5,
+    CAMERA_CMD_METADATA_ON = CAMERA_CMD_VENDOR_START + 6,
+    CAMERA_CMD_METADATA_OFF = CAMERA_CMD_VENDOR_START + 7,
+    CAMERA_CMD_VENDOR_END = 200,
 };
 
 /** camera fatal errors */
@@ -275,10 +304,32 @@
      * -2000, -2000 if this is not supported.
      */
     int32_t mouth[2];
+    int32_t smile_degree;
+    int32_t smile_score;
+    int32_t blink_detected;
+    int32_t face_recognised;
+    int32_t gaze_angle;
+    int32_t updown_dir;
+    int32_t leftright_dir;
+    int32_t roll_dir;
+    int32_t left_right_gaze;
+    int32_t top_bottom_gaze;
+    int32_t leye_blink;
+    int32_t reye_blink;
 
 } camera_face_t;
 
 /**
+ * The information of a data type received in a camera frame.
+ */
+typedef enum {
+    /** Data buffer */
+    CAMERA_FRAME_DATA_BUF = 0x000,
+    /** File descriptor */
+    CAMERA_FRAME_DATA_FD = 0x100
+} camera_frame_data_type_t;
+
+/**
  * The metadata of the frame data.
  */
 typedef struct camera_frame_metadata {
diff --git a/include/utils/Condition.h b/include/utils/Condition.h
index 5a72519..3e5141c 100644
--- a/include/utils/Condition.h
+++ b/include/utils/Condition.h
@@ -85,19 +85,22 @@
 
 #if !defined(_WIN32)
 
-inline Condition::Condition() {
-    pthread_cond_init(&mCond, NULL);
+inline Condition::Condition() : Condition(PRIVATE) {
 }
 inline Condition::Condition(int type) {
+    pthread_condattr_t attr;
+    pthread_condattr_init(&attr);
+#if defined(__linux__)
+    pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
+#endif
+
     if (type == SHARED) {
-        pthread_condattr_t attr;
-        pthread_condattr_init(&attr);
         pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
-        pthread_cond_init(&mCond, &attr);
-        pthread_condattr_destroy(&attr);
-    } else {
-        pthread_cond_init(&mCond, NULL);
     }
+
+    pthread_cond_init(&mCond, &attr);
+    pthread_condattr_destroy(&attr);
+
 }
 inline Condition::~Condition() {
     pthread_cond_destroy(&mCond);
@@ -114,7 +117,7 @@
 #else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
     struct timespec ts;
 #if defined(__linux__)
-    clock_gettime(CLOCK_REALTIME, &ts);
+    clock_gettime(CLOCK_MONOTONIC, &ts);
 #else // __APPLE__
     // we don't support the clocks here.
     struct timeval t;
diff --git a/init/Android.mk b/init/Android.mk
index 67541b8..944c8b8 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -12,6 +12,14 @@
 
 init_options += -DLOG_UEVENTS=0
 
+ifneq ($(TARGET_INIT_COLDBOOT_TIMEOUT),)
+init_options += -DCOLDBOOT_TIMEOUT_OVERRIDE=$(TARGET_INIT_COLDBOOT_TIMEOUT)
+endif
+
+ifneq ($(TARGET_INIT_CONSOLE_TIMEOUT),)
+init_options += -DCONSOLE_TIMEOUT_SEC=$(TARGET_INIT_CONSOLE_TIMEOUT)
+endif
+
 init_cflags += \
     $(init_options) \
     -Wall -Wextra \
@@ -71,6 +79,7 @@
     ueventd.cpp \
     ueventd_parser.cpp \
     watchdogd.cpp \
+    vendor_init.cpp
 
 LOCAL_MODULE:= init
 LOCAL_C_INCLUDES += \
@@ -110,6 +119,11 @@
 
 LOCAL_SANITIZE := integer
 LOCAL_CLANG := true
+
+ifneq ($(strip $(TARGET_INIT_VENDOR_LIB)),)
+LOCAL_WHOLE_STATIC_LIBRARIES += $(TARGET_INIT_VENDOR_LIB)
+endif
+
 include $(BUILD_EXECUTABLE)
 
 
diff --git a/init/NOTICE b/init/NOTICE
index c5b1efa..383d0f5 100644
--- a/init/NOTICE
+++ b/init/NOTICE
@@ -188,3 +188,29 @@
 
    END OF TERMS AND CONDITIONS
 
+Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
diff --git a/init/builtins.cpp b/init/builtins.cpp
old mode 100644
new mode 100755
index 44217f0..5294ed0
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -547,6 +547,7 @@
     return ret;
 }
 
+
 /* Queue event based on fs_mgr return code.
  *
  * code: return code of fs_mgr_mount_all
@@ -558,6 +559,13 @@
  */
 static int queue_fs_event(int code) {
     int ret = code;
+    
+    std::string bootmode = property_get("ro.bootmode");
+    if (strncmp(bootmode.c_str(), "ffbm", 4) == 0) {
+        NOTICE("ffbm mode, not start class main\n");
+        return 0;
+    }
+
     if (code == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) {
         ActionManager::GetInstance().QueueEventTrigger("encrypt");
     } else if (code == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) {
@@ -810,10 +818,92 @@
     return fs_mgr_update_verity_state(verity_update_property);
 }
 
+static const char * get_prefix(const std::vector<std::string>& args)
+{
+    uint32_t arglen = args.size();
+    const char *prefix = NULL;
+    for (uint32_t i = 0; i < arglen - 1; i++) {
+        if (args[i].compare("-p") == 0) {
+            prefix = args[++i].c_str();
+            break;
+        }
+    }
+    return prefix;
+
+}
+static int sanitize_path(const char *path, const char *prefix)
+{
+    struct stat st;
+    char buf[PATH_MAX] = {0};
+    if (!path || !prefix) {
+        goto error;
+    }
+    //Confirm the path exists
+    if (lstat(path, &st) < 0) {
+        ERROR("sanitize_path: Failed to locate path %s: %s\n",
+                path,
+                strerror(errno));
+        goto error;
+    }
+    //If this is a symlink check that the prefix matches
+    if (S_ISLNK(st.st_mode)){
+        if (readlink(path, buf, PATH_MAX - 1) < 0) {
+            ERROR("sanitize_path: Failed to resolve link for %s: %s\n",
+                    path,
+                    strerror(errno));
+            goto error;
+        }
+        if (strncmp(buf, prefix, strlen(prefix))) {
+            ERROR("sanitize_path: Match error: Path:%s Resolved:%s Prefix%s\n",
+                    path,
+                    buf,
+                    prefix);
+            goto error;
+        }
+    }
+    return 0;
+error:
+    return -1;
+}
+
 static int do_write(const std::vector<std::string>& args) {
-    const char* path = args[1].c_str();
-    const char* value = args[2].c_str();
+    const char* path = NULL;
+    const char* value = NULL;
+    const char* prefix = NULL;
+    uint32_t arglen = args.size();
+
+    prefix = get_prefix(args);
+    if (prefix && (arglen != 5)) {
+        ERROR("do_write: Incorrect number of args\n");
+        goto error;
+    }
+    for (uint32_t i = 1; i < arglen - 1; i++) {
+        if (args[i].compare("-p") != 0) {
+            path = args[i++].c_str();
+            value = args[i].c_str();
+            break;
+        } else {
+            //Value at current index is -p. The next index would
+            //be the prefix.Skip it.
+            i++;
+        }
+    }
+    if (!path || !value) {
+        ERROR("do_write: Invalid path/value\n");
+        goto error;
+    }
+    if (prefix) {
+        if (sanitize_path(path, prefix) != 0) {
+            ERROR("do_write: Faield to sanitize path: %s prefix: %s\n",
+                            path,
+                            prefix);
+            goto error;
+        }
+        return write_file_follow(path, value);
+    }
     return write_file(path, value);
+error:
+    return -EINVAL;
 }
 
 static int do_copy(const std::vector<std::string>& args) {
@@ -875,18 +965,48 @@
 }
 
 static int do_chown(const std::vector<std::string>& args) {
+    const char *prefix = get_prefix(args);
+    uint32_t num_prefix_args = (!prefix) ? 0:2;
     /* GID is optional. */
-    if (args.size() == 3) {
+    if (args.size() == 3 + num_prefix_args) {
+        if (prefix) {
+            if ((sanitize_path(args[2].c_str(), prefix) != 0)) {
+                ERROR("do_chown: failed for %s..prefix(%s) match error\n",
+                        args[2].c_str(),
+                        prefix);
+                goto error;
+            }
+            //Following of symlink allowed
+            if (chown(args[2].c_str(), decode_uid(args[1].c_str()), -1) == -1)
+                return -errno;
+            return 0;
+        }
+        //Followng of symlinks not allowed
         if (lchown(args[2].c_str(), decode_uid(args[1].c_str()), -1) == -1)
             return -errno;
-    } else if (args.size() == 4) {
+    } else if (args.size() == 4 + num_prefix_args) {
+        if (prefix) {
+            if ((sanitize_path(args[3].c_str(), prefix) != 0)) {
+                ERROR("do_chown: sanitize_path failed for path: %s prefix:%s\n",
+                        args[3].c_str(),
+                        prefix);
+                goto error;
+            }
+            //Following of symlink allowed
+            if (chown(args[3].c_str(), decode_uid(args[1].c_str()),
+                        decode_uid(args[2].c_str())) == -1)
+                return -errno;
+            return 0;
+        }
         if (lchown(args[3].c_str(), decode_uid(args[1].c_str()),
-                   decode_uid(args[2].c_str())) == -1)
+                    decode_uid(args[2].c_str())) == -1)
             return -errno;
     } else {
         return -1;
     }
     return 0;
+error:
+    return -1;
 }
 
 static mode_t get_mode(const char *s) {
@@ -903,8 +1023,19 @@
 }
 
 static int do_chmod(const std::vector<std::string>& args) {
+    const char *prefix = get_prefix(args);
+    int flags = AT_SYMLINK_NOFOLLOW;
+    if (prefix) {
+        if (sanitize_path(args[2].c_str(), prefix) != 0) {
+            ERROR("do_chmod: failed for %s..prefix(%s) match err\n",
+                    args[2].c_str(),
+                    prefix);
+            return -1;
+        }
+        flags = 0;
+    }
     mode_t mode = get_mode(args[1].c_str());
-    if (fchmodat(AT_FDCWD, args[2].c_str(), mode, AT_SYMLINK_NOFOLLOW) < 0) {
+    if (fchmodat(AT_FDCWD, args[2].c_str(), mode, flags) < 0) {
         return -errno;
     }
     return 0;
@@ -995,8 +1126,8 @@
     constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
     static const Map builtin_functions = {
         {"bootchart_init",          {0,     0,    do_bootchart_init}},
-        {"chmod",                   {2,     2,    do_chmod}},
-        {"chown",                   {2,     3,    do_chown}},
+        {"chmod",                   {2,     4,    do_chmod}},
+        {"chown",                   {2,     5,    do_chown}},
         {"class_reset",             {1,     1,    do_class_reset}},
         {"class_start",             {1,     1,    do_class_start}},
         {"class_stop",              {1,     1,    do_class_stop}},
@@ -1034,7 +1165,7 @@
         {"verity_load_state",       {0,     0,    do_verity_load_state}},
         {"verity_update_state",     {0,     0,    do_verity_update_state}},
         {"wait",                    {1,     2,    do_wait}},
-        {"write",                   {2,     2,    do_write}},
+        {"write",                   {2,     4,    do_write}},
     };
     return builtin_functions;
 }
diff --git a/init/devices.cpp b/init/devices.cpp
index cffc561..5edbe2a 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -48,6 +48,7 @@
 #include "ueventd_parser.h"
 #include "util.h"
 #include "log.h"
+#include "property_service.h"
 
 #define SYSFS_PREFIX    "/sys"
 static const char *firmware_dirs[] = { "/etc/firmware",
@@ -56,6 +57,8 @@
 
 extern struct selabel_handle *sehandle;
 
+extern std::string boot_device;
+
 static int device_fd = -1;
 
 struct uevent {
@@ -526,6 +529,11 @@
     else
         links[link_num] = NULL;
 
+    if (pdev && !boot_device.empty() && strstr(device, boot_device.c_str())) {
+        /* Create bootdevice symlink for platform boot stroage device */
+        make_link_init(link_path, "/dev/block/bootdevice");
+    }
+
     return links;
 }
 
@@ -731,8 +739,30 @@
          base = "/dev/log/";
          make_dir(base, 0755);
          name += 4;
-     } else
-         base = "/dev/";
+     } else if (!strncmp(uevent->subsystem, "dvb", 3)) {
+         /* This imitates the file system that would be created
+          * if we were using devfs instead to preserve backward compatibility
+          * for users of dvb devices
+          */
+         int adapter_id=0;
+         char dev_name[20] = {0};
+
+         sscanf(name, "dvb%d.%s", &adapter_id, dev_name);
+
+         /* build dvb directory */
+         base = "/dev/dvb";
+         mkdir(base, 0755);
+
+         /* build adapter directory */
+         snprintf(devpath, sizeof(devpath), "/dev/dvb/adapter%d", adapter_id);
+         mkdir(devpath, 0755);
+
+         /* build actual device directory */
+         snprintf(devpath, sizeof(devpath), "/dev/dvb/adapter%d/%s",
+                 adapter_id, dev_name);
+     }
+     else
+        base = "/dev/";
      links = get_character_device_symlinks(uevent);
 
      if (!devpath[0])
@@ -766,6 +796,21 @@
         return -1;
     len_to_copy = st.st_size;
 
+    if (S_ISBLK(st.st_mode)) {
+        //File points to a block device. Need to calculate it's size
+        //manually
+        len_to_copy = lseek64(fw_fd, 0, SEEK_END);
+        if (len_to_copy < 0) {
+            ERROR("Failed to get size of blk device partition: %s\n",
+                             strerror(errno));
+            return -1;
+        }
+        if (lseek64(fw_fd, 0, SEEK_SET) < 0) {
+            ERROR("Failed to set r/w offset for blk device partition: %s\n",
+                             strerror(errno));
+            return -1;
+        }
+    }
     write(loading_fd, "1", 1);  /* start transfer */
 
     while (len_to_copy > 0) {
diff --git a/init/init.cpp b/init/init.cpp
old mode 100644
new mode 100755
index cd2d2e6..164dc0f
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -18,7 +18,6 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <fstream>
 #include <libgen.h>
 #include <paths.h>
 #include <signal.h>
@@ -161,15 +160,19 @@
 
 static int wait_for_coldboot_done_action(const std::vector<std::string>& args) {
     Timer t;
-
+    int timeout = 0;
+#ifdef COLDBOOT_TIMEOUT_OVERRIDE
+    timeout = COLDBOOT_TIMEOUT_OVERRIDE;
+#else
+    timeout = 5;
+#endif
     NOTICE("Waiting for %s...\n", COLDBOOT_DONE);
     // Any longer than 1s is an unreasonable length of time to delay booting.
     // If you're hitting this timeout, check that you didn't make your
     // sepolicy regular expressions too expensive (http://b/19899875).
-    if (wait_for_file(COLDBOOT_DONE, 1)) {
+    if (wait_for_file(COLDBOOT_DONE, timeout)) {
         ERROR("Timed out waiting for %s\n", COLDBOOT_DONE);
     }
-
     NOTICE("Waiting for %s took %.2fs.\n", COLDBOOT_DONE, t.duration());
     return 0;
 }
@@ -251,100 +254,6 @@
     return result;
 }
 
-static void security_failure() {
-    ERROR("Security failure; rebooting into recovery mode...\n");
-    android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
-    while (true) { pause(); }  // never reached
-}
-
-#define MMAP_RND_PATH "/proc/sys/vm/mmap_rnd_bits"
-#define MMAP_RND_COMPAT_PATH "/proc/sys/vm/mmap_rnd_compat_bits"
-
-/* __attribute__((unused)) due to lack of mips support: see mips block
- * in set_mmap_rnd_bits_action */
-static bool __attribute__((unused)) set_mmap_rnd_bits_min(int start, int min, bool compat) {
-    std::string path;
-    if (compat) {
-        path = MMAP_RND_COMPAT_PATH;
-    } else {
-        path = MMAP_RND_PATH;
-    }
-    std::ifstream inf(path, std::fstream::in);
-    if (!inf) {
-        return false;
-    }
-    while (start >= min) {
-        // try to write out new value
-        std::string str_val = std::to_string(start);
-        std::ofstream of(path, std::fstream::out);
-        if (!of) {
-            return false;
-        }
-        of << str_val << std::endl;
-        of.close();
-
-        // check to make sure it was recorded
-        inf.seekg(0);
-        std::string str_rec;
-        inf >> str_rec;
-        if (str_val.compare(str_rec) == 0) {
-            break;
-        }
-        start--;
-    }
-    inf.close();
-    return (start >= min);
-}
-
-/*
- * Set /proc/sys/vm/mmap_rnd_bits and potentially
- * /proc/sys/vm/mmap_rnd_compat_bits to the maximum supported values.
- * Returns -1 if unable to set these to an acceptable value.  Apply
- * upstream patch-sets https://lkml.org/lkml/2015/12/21/337 and
- * https://lkml.org/lkml/2016/2/4/831 to enable this.
- */
-static int set_mmap_rnd_bits_action(const std::vector<std::string>& args)
-{
-    int ret = -1;
-
-    /* values are arch-dependent */
-#if defined(__aarch64__)
-    /* arm64 supports 18 - 33 bits depending on pagesize and VA_SIZE */
-    if (set_mmap_rnd_bits_min(33, 24, false)
-            && set_mmap_rnd_bits_min(16, 16, true)) {
-        ret = 0;
-    }
-#elif defined(__x86_64__)
-    /* x86_64 supports 28 - 32 bits */
-    if (set_mmap_rnd_bits_min(32, 32, false)
-            && set_mmap_rnd_bits_min(16, 16, true)) {
-        ret = 0;
-    }
-#elif defined(__arm__) || defined(__i386__)
-    /* check to see if we're running on 64-bit kernel */
-    bool h64 = !access(MMAP_RND_COMPAT_PATH, F_OK);
-    /* supported 32-bit architecture must have 16 bits set */
-    if (set_mmap_rnd_bits_min(16, 16, h64)) {
-        ret = 0;
-    }
-#elif defined(__mips__) || defined(__mips64__)
-    // TODO: add mips support b/27788820
-    ret = 0;
-#else
-    ERROR("Unknown architecture\n");
-#endif
-
-#ifdef __BRILLO__
-    // TODO: b/27794137
-    ret = 0;
-#endif
-    if (ret == -1) {
-        ERROR("Unable to set adequate mmap entropy value!\n");
-        security_failure();
-    }
-    return ret;
-}
-
 static int keychord_init_action(const std::vector<std::string>& args)
 {
     keychord_init();
@@ -353,15 +262,31 @@
 
 static int console_init_action(const std::vector<std::string>& args)
 {
+    int fd = -1;
     std::string console = property_get("ro.boot.console");
     if (!console.empty()) {
         console_name = "/dev/" + console;
     }
-
-    int fd = open(console_name.c_str(), O_RDWR | O_CLOEXEC);
+    fd = open(console_name.c_str(), O_RDWR | O_CLOEXEC);
+#ifdef CONSOLE_TIMEOUT_SEC
+    int num_console_retries = 0;
+    while ((fd < 0) && num_console_retries++ < CONSOLE_TIMEOUT_SEC) {
+        ERROR("Failed to open console device %s(%s)..Retrying\n",
+                       console_name.c_str(), strerror(errno));
+        sleep(1);
+        fd = open(console_name.c_str(), O_RDWR | O_CLOEXEC);
+    }
     if (fd >= 0)
+        INFO("Console device located");
+#endif
+    if (fd >= 0) {
         have_console = 1;
-    close(fd);
+        close(fd);
+    } else {
+        ERROR("console init failed. Open on Console device %s failed(%s)\n",
+                         console.c_str(), strerror(errno));
+        return 0;
+    }
 
     fd = open("/dev/tty0", O_WRONLY | O_CLOEXEC);
     if (fd >= 0) {
@@ -553,6 +478,12 @@
     return 0;
 }
 
+static void security_failure() {
+    ERROR("Security failure; rebooting into recovery mode...\n");
+    android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
+    while (true) { pause(); }  // never reached
+}
+
 static void selinux_initialize(bool in_kernel_domain) {
     Timer t;
 
@@ -701,7 +632,6 @@
     am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done");
     // ... so that we can start queuing up actions that require stuff from /dev.
     am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
-    am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");
     am.QueueBuiltinAction(keychord_init_action, "keychord_init");
     am.QueueBuiltinAction(console_init_action, "console_init");
 
@@ -716,6 +646,9 @@
     std::string bootmode = property_get("ro.bootmode");
     if (bootmode == "charger") {
         am.QueueEventTrigger("charger");
+    } else if (strncmp(bootmode.c_str(), "ffbm", 4) == 0) {
+        NOTICE("Booting into ffbm mode\n");
+        am.QueueEventTrigger("ffbm");
     } else {
         am.QueueEventTrigger("late-init");
     }
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 5c1ae79..7860748 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -41,6 +41,7 @@
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <sys/mman.h>
+#include <sys/resource.h>
 #include <private/android_filesystem_config.h>
 
 #include <selinux/selinux.h>
@@ -54,6 +55,7 @@
 #include "init.h"
 #include "util.h"
 #include "log.h"
+#include "vendor_init.h"
 
 #define PERSISTENT_PROPERTY_DIR  "/data/property"
 #define FSTAB_PREFIX "/fstab."
@@ -468,6 +470,22 @@
     }
 }
 
+static int check_rlim_action() {
+    std::string value ;
+    struct rlimit rl;
+    value = property_get("persist.debug.trace");
+    const char* pval = value.c_str();
+
+    if((strcmp(pval,"1") == 0)) {
+        rl.rlim_cur = RLIM_INFINITY;
+        rl.rlim_max = RLIM_INFINITY;
+        if (setrlimit(RLIMIT_CORE, &rl) < 0) {
+            ERROR("could not enable core file generation");
+        }
+    }
+    return 0;
+}
+
 /* When booting an encrypted system, /data is not mounted when the
  * property service is started, so any properties stored there are
  * not loaded.  Vold triggers init to load these properties once it
@@ -477,6 +495,8 @@
     load_override_properties();
     /* Read persistent properties after all default values have been loaded. */
     load_persistent_properties();
+    /*check for coredump*/
+    check_rlim_action();
 }
 
 void load_recovery_id_prop() {
@@ -521,6 +541,12 @@
     load_properties_from_file(PROP_PATH_SYSTEM_BUILD, NULL);
     load_properties_from_file(PROP_PATH_VENDOR_BUILD, NULL);
     load_properties_from_file(PROP_PATH_FACTORY, "ro.*");
+
+    /* update with vendor-specific property runtime
+     * overrides
+     */
+    vendor_load_properties();
+
     load_recovery_id_prop();
 }
 
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index 249739b..131e97f 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -33,6 +33,8 @@
 #include "ueventd_parser.h"
 #include "property_service.h"
 
+std::string boot_device;
+
 int ueventd_main(int argc, char **argv)
 {
     /*
@@ -64,6 +66,8 @@
     ueventd_parse_config_file("/ueventd.rc");
     ueventd_parse_config_file(android::base::StringPrintf("/ueventd.%s.rc", hardware.c_str()).c_str());
 
+    boot_device = property_get("ro.boot.bootdevice");
+
     device_init();
 
     pollfd ufd;
diff --git a/init/util.cpp b/init/util.cpp
old mode 100644
new mode 100755
index 89d3276..babdcbd
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -212,6 +212,21 @@
     return result;
 }
 
+int write_file_follow(const char* path, const char* content) {
+    int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY|O_CREAT|O_CLOEXEC, 0600));
+    if (fd == -1) {
+        NOTICE("write_file: Unable to open '%s': %s\n", path, strerror(errno));
+        return -1;
+    }
+    int result = android::base::WriteStringToFd(content, fd) ? 0 : -1;
+    if (result == -1) {
+        NOTICE("write_file: Unable to write to '%s': %s\n", path, strerror(errno));
+    }
+    close(fd);
+    return result;
+}
+
+
 #define MAX_MTD_PARTITIONS 16
 
 static struct {
diff --git a/init/util.h b/init/util.h
old mode 100644
new mode 100755
index af4b098..db9025d
--- a/init/util.h
+++ b/init/util.h
@@ -33,6 +33,7 @@
 
 bool read_file(const char* path, std::string* content);
 int write_file(const char* path, const char* content);
+int write_file_follow(const char* path, const char* content);
 
 time_t gettime();
 uint64_t gettime_ns();
diff --git a/init/vendor_init.cpp b/init/vendor_init.cpp
new file mode 100644
index 0000000..d3fd5ff
--- /dev/null
+++ b/init/vendor_init.cpp
@@ -0,0 +1,37 @@
+/*
+Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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 "vendor_init.h"
+
+/* init vendor override stubs */
+
+__attribute__ ((weak))
+void vendor_load_properties()
+{
+}
diff --git a/init/vendor_init.h b/init/vendor_init.h
new file mode 100644
index 0000000..9afb449
--- /dev/null
+++ b/init/vendor_init.h
@@ -0,0 +1,33 @@
+/*
+Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+ */
+
+#ifndef __INIT_VENDOR__H__
+#define __INIT_VENDOR__H__
+extern void vendor_load_properties(void);
+#endif /* __INIT_VENDOR__H__ */
diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c
index 05a2048..0df5bf3 100644
--- a/libcutils/sched_policy.c
+++ b/libcutils/sched_policy.c
@@ -66,6 +66,7 @@
 static int bg_cpuset_fd = -1;
 static int fg_cpuset_fd = -1;
 static int ta_cpuset_fd = -1; // special cpuset for top app
+static int system_bg_schedboost_fd = -1;
 #endif
 
 // File descriptors open to /dev/stune/../tasks, setup by initialize, or -1 on error
@@ -139,17 +140,21 @@
         system_bg_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC);
         filename = "/dev/cpuset/top-app/tasks";
         ta_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC);
+    }
 
 #ifdef USE_SCHEDBOOST
+    if (!access("/dev/stune/tasks", F_OK)) {
         filename = "/dev/stune/top-app/tasks";
         ta_schedboost_fd = open(filename, O_WRONLY | O_CLOEXEC);
         filename = "/dev/stune/foreground/tasks";
         fg_schedboost_fd = open(filename, O_WRONLY | O_CLOEXEC);
         filename = "/dev/stune/background/tasks";
         bg_schedboost_fd = open(filename, O_WRONLY | O_CLOEXEC);
-#endif
+        filename = "/dev/stune/system-background/tasks";
+        system_bg_schedboost_fd = open(filename, O_WRONLY | O_CLOEXEC);
     }
-#endif
+#endif /* USE_SCHEDBOOST */
+#endif /* USE_CPUSETS */
 }
 
 /*
@@ -307,6 +312,7 @@
         break;
     case SP_SYSTEM:
         fd = system_bg_cpuset_fd;
+        boost_fd = system_bg_schedboost_fd;
         break;
     default:
         boost_fd = fd = -1;
diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c
index eae32ce..f051558 100644
--- a/libnetutils/ifc_utils.c
+++ b/libnetutils/ifc_utils.c
@@ -173,8 +173,7 @@
 static void ifc_init_ifr(const char *name, struct ifreq *ifr)
 {
     memset(ifr, 0, sizeof(struct ifreq));
-    strncpy(ifr->ifr_name, name, IFNAMSIZ);
-    ifr->ifr_name[IFNAMSIZ - 1] = 0;
+    strlcpy(ifr->ifr_name, name, IFNAMSIZ);
 }
 
 int ifc_get_hwaddr(const char *name, void *ptr)
@@ -625,23 +624,26 @@
 int ifc_reset_connections(const char *ifname, const int reset_mask)
 {
 #if defined(__ANDROID__)
-    int result, success;
+    int result = 0, success;
     in_addr_t myaddr = 0;
     struct ifreq ifr;
     struct in6_ifreq ifr6;
+    int ctl_sock = -1;
 
     if (reset_mask & RESET_IPV4_ADDRESSES) {
         /* IPv4. Clear connections on the IP address. */
-        ifc_init();
-        if (!(reset_mask & RESET_IGNORE_INTERFACE_ADDRESS)) {
-            ifc_get_info(ifname, &myaddr, NULL, NULL);
+        ctl_sock = socket(AF_INET, SOCK_DGRAM, 0);
+        if (ctl_sock >= 0) {
+            if (!(reset_mask & RESET_IGNORE_INTERFACE_ADDRESS)) {
+                ifc_get_info(ifname, &myaddr, NULL, NULL);
+            }
+            ifc_init_ifr(ifname, &ifr);
+            init_sockaddr_in(&ifr.ifr_addr, myaddr);
+            result = ioctl(ctl_sock, SIOCKILLADDR,  &ifr);
+            close(ctl_sock);
+        } else {
+            result = -1;
         }
-        ifc_init_ifr(ifname, &ifr);
-        init_sockaddr_in(&ifr.ifr_addr, myaddr);
-        result = ioctl(ifc_ctl_sock, SIOCKILLADDR,  &ifr);
-        ifc_close();
-    } else {
-        result = 0;
     }
 
     if (reset_mask & RESET_IPV6_ADDRESSES) {
@@ -651,14 +653,18 @@
          * So we clear all unused IPv6 connections on the device by specifying an
          * empty IPv6 address.
          */
-        ifc_init6();
+        ctl_sock = socket(AF_INET6, SOCK_DGRAM, 0);
         // This implicitly specifies an address of ::, i.e., kill all IPv6 sockets.
         memset(&ifr6, 0, sizeof(ifr6));
-        success = ioctl(ifc_ctl_sock6, SIOCKILLADDR,  &ifr6);
-        if (result == 0) {
-            result = success;
+        if (ctl_sock >= 0) {
+            success = ioctl(ctl_sock, SIOCKILLADDR,  &ifr6);
+            if (result == 0) {
+                result = success;
+            }
+            close(ctl_sock);
+        } else {
+            result = -1;
         }
-        ifc_close6();
     }
 
     return result;
diff --git a/lmkd/Android.mk b/lmkd/Android.mk
index 8c88661..8980d1c 100644
--- a/lmkd/Android.mk
+++ b/lmkd/Android.mk
@@ -2,7 +2,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := lmkd.c
-LOCAL_SHARED_LIBRARIES := liblog libm libc libprocessgroup
+LOCAL_SHARED_LIBRARIES := liblog libm libc libprocessgroup libcutils
 LOCAL_CFLAGS := -Werror
 
 LOCAL_MODULE := lmkd
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
old mode 100644
new mode 100755
index afc81ed..51c285b
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -33,6 +33,8 @@
 #include <cutils/sockets.h>
 #include <log/log.h>
 #include <processgroup/processgroup.h>
+#include <dlfcn.h>
+#include <cutils/properties.h>
 
 #ifndef __unused
 #define __unused __attribute__((__unused__))
@@ -61,6 +63,14 @@
  */
 #define CTRL_PACKET_MAX (sizeof(int) * (MAX_TARGETS * 2 + 1))
 
+static void* memperf_opt_handle = NULL;
+static int (*memperf_init_fn)(void) = NULL;
+static int (*memperf_am_update_fn)(void*,unsigned int) = NULL;
+static void init_memperf();
+static void de_init_memperf();
+static bool enable_amupdate = false;
+static bool enable_umm = false;
+
 /* default to old in-kernel interface if no memory pressure events */
 static int use_inkernel_interface = 1;
 
@@ -356,6 +366,14 @@
     if (nargs < 0)
         goto wronglen;
 
+    if (enable_umm && enable_amupdate) {
+        int ret = (*memperf_am_update_fn)(ibuf, sizeof(ibuf));
+        if (ret == -1) {
+            ALOGE("Received Error from mem_ctl. unloading the module %d", ret);
+            de_init_memperf();
+        }
+    }
+
     cmd = ntohl(ibuf[0]);
 
     switch(cmd) {
@@ -804,6 +822,48 @@
     }
 }
 
+static void de_init_memperf() {
+    memperf_init_fn = NULL;
+    memperf_am_update_fn = NULL;
+
+    if (memperf_opt_handle) dlclose(memperf_opt_handle);
+
+    memperf_opt_handle = NULL;
+}
+
+static void init_memperf() {
+    int mem_ctl_enable = 0;
+    enable_amupdate = property_get_bool("ro.memperf.amupdate", false);
+    mem_ctl_enable = property_get_bool("ro.memperf.enable", 0);
+    enable_umm = property_get_bool("ro.memperf.umm", false);
+    if (mem_ctl_enable) {
+        char prop[PROPERTY_VALUE_MAX];
+        memset(prop, '\0', sizeof(prop));
+        property_get("ro.memperf.lib", prop, "");
+        memperf_opt_handle = dlopen(prop, RTLD_LAZY);
+        if (memperf_opt_handle != NULL) {
+            dlerror();
+            memperf_init_fn = (int(*)(void))dlsym(memperf_opt_handle, "init_mperfd");
+            memperf_am_update_fn = (int(*)(void*,unsigned int))dlsym(memperf_opt_handle, "amUpdate");
+            const char *dlsym_error = dlerror();
+
+            if((memperf_am_update_fn == NULL) || (memperf_init_fn == NULL)) {
+                ALOGD("Error loading symbol. dlerror : %s", dlsym_error);
+                de_init_memperf();
+            }
+
+            if (memperf_init_fn) {
+                if (-1 == (*memperf_init_fn)()) {
+                    ALOGE("Error during init. Disabling memperf !!!!");
+                    de_init_memperf();
+                }
+            }
+        } else {
+            ALOGE("Failed to load library");
+        }
+    }
+}
+
 int main(int argc __unused, char **argv __unused) {
     struct sched_param param = {
             .sched_priority = 1,
@@ -811,9 +871,15 @@
 
     mlockall(MCL_FUTURE);
     sched_setscheduler(0, SCHED_FIFO, &param);
+
+    init_memperf();
+
     if (!init())
         mainloop();
 
+    if (memperf_opt_handle) {
+        de_init_memperf();
+    }
     ALOGI("exiting");
     return 0;
 }
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 33f22dd..87524b4 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -27,6 +27,7 @@
 
 #include <android-base/file.h>
 #include <android-base/strings.h>
+#include <cutils/properties.h>
 #include <cutils/sched_policy.h>
 #include <cutils/sockets.h>
 #include <log/event_tag_map.h>
@@ -70,12 +71,15 @@
 /* Global Variables */
 
 static const char * g_outputFileName;
+static const char * g_outputPartitionName = NULL;
 // 0 means "no log rotation"
 static size_t g_logRotateSizeKBytes;
 // 0 means "unbounded"
 static size_t g_maxRotatedLogs = DEFAULT_MAX_ROTATED_LOGS;
 static int g_outFD = -1;
+static int g_logDumpFD = -1;
 static size_t g_outByteCount;
+static size_t g_outByteCountOfLogDump;
 static int g_printBinary;
 static int g_devCount;                              // >1 means multiple
 static pcrecpp::RE* g_regex;
@@ -83,6 +87,8 @@
 static size_t g_maxCount;
 static size_t g_printCount;
 static bool g_printItAnyways;
+static bool g_logDumpEnabled;
+static size_t g_logDumpEndPosition = 0;
 
 // if showHelp is set, newline required in fmt statement to transition to usage
 __noreturn static void logcat_panic(bool showHelp, const char *fmt, ...) __printflike(2,3);
@@ -151,6 +157,42 @@
     TEMP_FAILURE_RETRY(write(g_outFD, buf, size));
 }
 
+static void checkAndRotateLogDump(size_t logLength)
+{
+    if (g_outByteCountOfLogDump + logLength >= g_logDumpEndPosition) {
+        lseek(g_logDumpFD, 0, SEEK_SET);
+        g_outByteCountOfLogDump = 0;
+    }
+}
+
+static void writeEntryToLogDump(AndroidLogEntry *entry)
+{
+    int bytesWrittenToLogDump = 0;
+    char defaultBuffer[512];
+    char *outBuffer = NULL;
+    size_t logLength;
+
+    // Get logLength
+    outBuffer = android_log_formatLogLine(g_logformat, defaultBuffer,
+                                          sizeof(defaultBuffer),
+                                          entry,
+                                          &logLength);
+    if (outBuffer != defaultBuffer) {
+        free(outBuffer);
+    }
+
+    // Check if the to-be-inserted log exceeds the available buffer size; And rotate if needed.
+    checkAndRotateLogDump(logLength);
+
+    bytesWrittenToLogDump = android_log_printLogLine(g_logformat, g_logDumpFD, entry);
+
+    if (bytesWrittenToLogDump < 0) {
+        logcat_panic(false, "output error");
+    }
+
+    g_outByteCountOfLogDump += bytesWrittenToLogDump;
+}
+
 static bool regexOk(const AndroidLogEntry& entry)
 {
     if (!g_regex) {
@@ -191,6 +233,10 @@
     }
 
     if (android_log_shouldPrintLine(g_logformat, entry.tag, entry.priority)) {
+        if (g_logDumpEnabled) {
+            writeEntryToLogDump(&entry);
+        }
+
         bool match = regexOk(entry);
 
         g_printCount += match;
@@ -223,6 +269,14 @@
             snprintf(buf, sizeof(buf), "--------- %s %s\n",
                      dev->printed ? "switch to" : "beginning of",
                      dev->device);
+            if (g_logDumpEnabled) {
+                checkAndRotateLogDump(strlen(buf));
+                int bytesWrittenToLogDump = write(g_logDumpFD, buf, strlen(buf));
+                if (bytesWrittenToLogDump < 0) {
+                    logcat_panic(false, "output error");
+                }
+                g_outByteCountOfLogDump += bytesWrittenToLogDump;
+            }
             if (write(g_outFD, buf, strlen(buf)) < 0) {
                 logcat_panic(false, "output error");
             }
@@ -233,6 +287,29 @@
 
 static void setupOutput()
 {
+    if (g_logDumpEnabled) {
+        if (g_outputPartitionName == NULL) {
+            property_set("ctl.stop","logdumpd");
+            logcat_panic(false, "partition name is null");
+        }
+
+        struct stat statbuf;
+        if (stat(g_outputPartitionName, &statbuf) == -1) {
+            property_set("ctl.stop","logdumpd");
+            logcat_panic(false, "Couldn't stat output partition\n");
+        }
+
+        g_logDumpFD = openLogFile (g_outputPartitionName);
+        if (g_logDumpFD < 0) {
+            property_set("ctl.stop","logdumpd");
+            logcat_panic(false, "Can't open output partition");
+        }
+
+        //save end of partition to be used later for log rotation
+        g_logDumpEndPosition = lseek(g_logDumpFD, 0, SEEK_END);
+        //set back file offset to the beginning
+        lseek(g_logDumpFD, 0, SEEK_SET);
+    }
 
     if (g_outputFileName == NULL) {
         g_outFD = STDOUT_FILENO;
@@ -603,7 +680,7 @@
           { NULL,            0,                 NULL,   0 }
         };
 
-        ret = getopt_long(argc, argv, ":cdDLt:T:gG:sQf:r:n:v:b:BSpP:m:e:",
+        ret = getopt_long(argc, argv, ":cdDLt:T:gG:sQf:r:n:v:b:BSpP:m:e:w:",
                           long_options, &option_index);
 
         if (ret < 0) {
@@ -927,6 +1004,11 @@
                 printStatistics = 1;
                 break;
 
+            case 'w':
+                g_logDumpEnabled = true;
+                g_outputPartitionName = optarg;
+                break;
+
             case ':':
                 logcat_panic(true, "Option -%c needs an argument\n", optopt);
                 break;
diff --git a/mkbootimg/mkbootimg b/mkbootimg/mkbootimg
index 5a13da2..d0149e8 100755
--- a/mkbootimg/mkbootimg
+++ b/mkbootimg/mkbootimg
@@ -57,7 +57,7 @@
         args.base + args.second_offset,                 # physical load addr
         args.base + args.tags_offset,                   # physical addr for kernel tags
         args.pagesize,                                  # flash page size we assume
-        0,                                              # future expansion: MUST be 0
+        filesize(args.dt),                              # size in bytes
         (args.os_version << 11) | args.os_patch_level)) # os version and patch level
     args.output.write(pack('16s', args.board.encode())) # asciiz product name
     args.output.write(pack('512s', args.cmdline[:512].encode()))
@@ -66,6 +66,7 @@
     update_sha(sha, args.kernel)
     update_sha(sha, args.ramdisk)
     update_sha(sha, args.second)
+    update_sha(sha, args.dt)
     img_id = pack('32s', sha.digest())
 
     args.output.write(img_id)
@@ -150,6 +151,7 @@
                         choices=[2**i for i in range(11,15)], default=2048)
     parser.add_argument('--id', help='print the image ID on standard output',
                         action='store_true')
+    parser.add_argument('--dt', help='path to the device tree image', type=FileType('rb'))
     parser.add_argument('-o', '--output', help='output file name', type=FileType('wb'),
                         required=True)
     return parser.parse_args()
@@ -159,6 +161,7 @@
     write_padded_file(args.output, args.kernel, args.pagesize)
     write_padded_file(args.output, args.ramdisk, args.pagesize)
     write_padded_file(args.output, args.second, args.pagesize)
+    write_padded_file(args.output, args.dt, args.pagesize)
 
 
 def main():
diff --git a/rootdir/init.rc b/rootdir/init.rc
index df60f65..b9674d3 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -51,18 +51,22 @@
     mount cgroup none /dev/stune schedtune
     mkdir /dev/stune/foreground
     mkdir /dev/stune/background
+    mkdir /dev/stune/system-background
     mkdir /dev/stune/top-app
     chown system system /dev/stune
     chown system system /dev/stune/foreground
     chown system system /dev/stune/background
+    chown system system /dev/stune/system-background
     chown system system /dev/stune/top-app
     chown system system /dev/stune/tasks
     chown system system /dev/stune/foreground/tasks
     chown system system /dev/stune/background/tasks
+    chown system system /dev/stune/system-background/tasks
     chown system system /dev/stune/top-app/tasks
     chmod 0664 /dev/stune/tasks
     chmod 0664 /dev/stune/foreground/tasks
     chmod 0664 /dev/stune/background/tasks
+    chmod 0664 /dev/stune/system-background/tasks
     chmod 0664 /dev/stune/top-app/tasks
 
     # Mount staging areas for devices managed by vold
@@ -561,8 +565,11 @@
     chown system system /sys/class/leds/button-backlight/brightness
     chown system system /sys/class/leds/jogball-backlight/brightness
     chown system system /sys/class/leds/red/brightness
+    chown system system /sys/class/leds/red/blink
     chown system system /sys/class/leds/green/brightness
+    chown system system /sys/class/leds/green/blink
     chown system system /sys/class/leds/blue/brightness
+    chown system system /sys/class/leds/blue/blink
     chown system system /sys/class/leds/red/device/grpfreq
     chown system system /sys/class/leds/red/device/grppwm
     chown system system /sys/class/leds/red/device/blink
diff --git a/rootdir/init.usb.configfs.rc b/rootdir/init.usb.configfs.rc
index 186384b..c46130c 100644
--- a/rootdir/init.usb.configfs.rc
+++ b/rootdir/init.usb.configfs.rc
@@ -1,6 +1,7 @@
 on property:sys.usb.config=none && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/UDC "none"
     stop adbd
+    setprop sys.usb.ffs.ready 0
     write /config/usb_gadget/g1/bDeviceClass 0
     write /config/usb_gadget/g1/bDeviceSubClass 0
     write /config/usb_gadget/g1/bDeviceProtocol 0
@@ -14,6 +15,10 @@
     rm /config/usb_gadget/g1/configs/b.1/f1
     rm /config/usb_gadget/g1/configs/b.1/f2
     rm /config/usb_gadget/g1/configs/b.1/f3
+    rm /config/usb_gadget/g1/configs/b.1/f4
+    rm /config/usb_gadget/g1/configs/b.1/f5
+    write /config/usb_gadget/g1/idVendor 0x18d1
+    write /config/usb_gadget/g1/idProduct 0x4ee7
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f1
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}
     setprop sys.usb.state ${sys.usb.config}
@@ -23,6 +28,10 @@
     rm /config/usb_gadget/g1/configs/b.1/f1
     rm /config/usb_gadget/g1/configs/b.1/f2
     rm /config/usb_gadget/g1/configs/b.1/f3
+    rm /config/usb_gadget/g1/configs/b.1/f4
+    rm /config/usb_gadget/g1/configs/b.1/f5
+    write /config/usb_gadget/g1/idVendor 0x18d1
+    write /config/usb_gadget/g1/idProduct 0x4ee1
     symlink /config/usb_gadget/g1/functions/mtp.gs0 /config/usb_gadget/g1/configs/b.1/f1
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}
     setprop sys.usb.state ${sys.usb.config}
@@ -35,6 +44,10 @@
     rm /config/usb_gadget/g1/configs/b.1/f1
     rm /config/usb_gadget/g1/configs/b.1/f2
     rm /config/usb_gadget/g1/configs/b.1/f3
+    rm /config/usb_gadget/g1/configs/b.1/f4
+    rm /config/usb_gadget/g1/configs/b.1/f5
+    write /config/usb_gadget/g1/idVendor 0x18d1
+    write /config/usb_gadget/g1/idProduct 0x4ee2
     symlink /config/usb_gadget/g1/functions/mtp.gs0 /config/usb_gadget/g1/configs/b.1/f1
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}
@@ -45,6 +58,10 @@
     rm /config/usb_gadget/g1/configs/b.1/f1
     rm /config/usb_gadget/g1/configs/b.1/f2
     rm /config/usb_gadget/g1/configs/b.1/f3
+    rm /config/usb_gadget/g1/configs/b.1/f4
+    rm /config/usb_gadget/g1/configs/b.1/f5
+    write /config/usb_gadget/g1/idVendor 0x18d1
+    write /config/usb_gadget/g1/idProduct 0x4ee5
     symlink /config/usb_gadget/g1/functions/ptp.gs1 /config/usb_gadget/g1/configs/b.1/f1
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}
     setprop sys.usb.state ${sys.usb.config}
@@ -57,6 +74,10 @@
     rm /config/usb_gadget/g1/configs/b.1/f1
     rm /config/usb_gadget/g1/configs/b.1/f2
     rm /config/usb_gadget/g1/configs/b.1/f3
+    rm /config/usb_gadget/g1/configs/b.1/f4
+    rm /config/usb_gadget/g1/configs/b.1/f5
+    write /config/usb_gadget/g1/idVendor 0x18d1
+    write /config/usb_gadget/g1/idProduct 0x4ee6
     symlink /config/usb_gadget/g1/functions/ptp.gs1 /config/usb_gadget/g1/configs/b.1/f1
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}
@@ -67,6 +88,10 @@
     rm /config/usb_gadget/g1/configs/b.1/f1
     rm /config/usb_gadget/g1/configs/b.1/f2
     rm /config/usb_gadget/g1/configs/b.1/f3
+    rm /config/usb_gadget/g1/configs/b.1/f4
+    rm /config/usb_gadget/g1/configs/b.1/f5
+    write /config/usb_gadget/g1/idVendor 0x18d1
+    write /config/usb_gadget/g1/idProduct 0x2d00
     symlink /config/usb_gadget/g1/functions/accessory.gs2 /config/usb_gadget/g1/configs/b.1/f1
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}
     setprop sys.usb.state ${sys.usb.config}
@@ -79,6 +104,10 @@
     rm /config/usb_gadget/g1/configs/b.1/f1
     rm /config/usb_gadget/g1/configs/b.1/f2
     rm /config/usb_gadget/g1/configs/b.1/f3
+    rm /config/usb_gadget/g1/configs/b.1/f4
+    rm /config/usb_gadget/g1/configs/b.1/f5
+    write /config/usb_gadget/g1/idVendor 0x18d1
+    write /config/usb_gadget/g1/idProduct 0x2d01
     symlink /config/usb_gadget/g1/functions/accessory.gs2 /config/usb_gadget/g1/configs/b.1/f1
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}
@@ -89,7 +118,11 @@
     rm /config/usb_gadget/g1/configs/b.1/f1
     rm /config/usb_gadget/g1/configs/b.1/f2
     rm /config/usb_gadget/g1/configs/b.1/f3
-    symlink /config/usb_gadget/g1/functions/audio_source.gs2 /config/usb_gadget/g1/configs/b.1/f1
+    rm /config/usb_gadget/g1/configs/b.1/f4
+    rm /config/usb_gadget/g1/configs/b.1/f5
+    write /config/usb_gadget/g1/idVendor 0x18d1
+    write /config/usb_gadget/g1/idProduct 0x2d02
+    symlink /config/usb_gadget/g1/functions/audio_source.gs3 /config/usb_gadget/g1/configs/b.1/f1
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}
     setprop sys.usb.state ${sys.usb.config}
 
@@ -101,7 +134,11 @@
     rm /config/usb_gadget/g1/configs/b.1/f1
     rm /config/usb_gadget/g1/configs/b.1/f2
     rm /config/usb_gadget/g1/configs/b.1/f3
-    symlink /config/usb_gadget/g1/functions/audio_source.gs2 /config/usb_gadget/g1/configs/b.1/f1
+    rm /config/usb_gadget/g1/configs/b.1/f4
+    rm /config/usb_gadget/g1/configs/b.1/f5
+    write /config/usb_gadget/g1/idVendor 0x18d1
+    write /config/usb_gadget/g1/idProduct 0x2d03
+    symlink /config/usb_gadget/g1/functions/audio_source.gs3 /config/usb_gadget/g1/configs/b.1/f1
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}
     setprop sys.usb.state ${sys.usb.config}
@@ -111,6 +148,10 @@
     rm /config/usb_gadget/g1/configs/b.1/f1
     rm /config/usb_gadget/g1/configs/b.1/f2
     rm /config/usb_gadget/g1/configs/b.1/f3
+    rm /config/usb_gadget/g1/configs/b.1/f4
+    rm /config/usb_gadget/g1/configs/b.1/f5
+    write /config/usb_gadget/g1/idVendor 0x18d1
+    write /config/usb_gadget/g1/idProduct 0x2d04
     symlink /config/usb_gadget/g1/functions/accessory.gs2 /config/usb_gadget/g1/configs/b.1/f1
     symlink /config/usb_gadget/g1/functions/audio_source.gs3 /config/usb_gadget/g1/configs/b.1/f2
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}
@@ -124,6 +165,10 @@
     rm /config/usb_gadget/g1/configs/b.1/f1
     rm /config/usb_gadget/g1/configs/b.1/f2
     rm /config/usb_gadget/g1/configs/b.1/f3
+    rm /config/usb_gadget/g1/configs/b.1/f4
+    rm /config/usb_gadget/g1/configs/b.1/f5
+    write /config/usb_gadget/g1/idVendor 0x18d1
+    write /config/usb_gadget/g1/idProduct 0x2d05
     symlink /config/usb_gadget/g1/functions/accessory.gs2 /config/usb_gadget/g1/configs/b.1/f1
     symlink /config/usb_gadget/g1/functions/audio_source.gs3 /config/usb_gadget/g1/configs/b.1/f2
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f3
@@ -135,6 +180,10 @@
     rm /config/usb_gadget/g1/configs/b.1/f1
     rm /config/usb_gadget/g1/configs/b.1/f2
     rm /config/usb_gadget/g1/configs/b.1/f3
+    rm /config/usb_gadget/g1/configs/b.1/f4
+    rm /config/usb_gadget/g1/configs/b.1/f5
+    write /config/usb_gadget/g1/idVendor 0x18d1
+    write /config/usb_gadget/g1/idProduct 0x4ee8
     symlink /config/usb_gadget/g1/functions/midi.gs5 /config/usb_gadget/g1/configs/b.1/f1
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}
     setprop sys.usb.state ${sys.usb.config}
@@ -147,6 +196,10 @@
     rm /config/usb_gadget/g1/configs/b.1/f1
     rm /config/usb_gadget/g1/configs/b.1/f2
     rm /config/usb_gadget/g1/configs/b.1/f3
+    rm /config/usb_gadget/g1/configs/b.1/f4
+    rm /config/usb_gadget/g1/configs/b.1/f5
+    write /config/usb_gadget/g1/idVendor 0x18d1
+    write /config/usb_gadget/g1/idProduct 0x4ee9
     symlink /config/usb_gadget/g1/functions/midi.gs5 /config/usb_gadget/g1/configs/b.1/f1
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}
@@ -157,6 +210,10 @@
     rm /config/usb_gadget/g1/configs/b.1/f1
     rm /config/usb_gadget/g1/configs/b.1/f2
     rm /config/usb_gadget/g1/configs/b.1/f3
+    rm /config/usb_gadget/g1/configs/b.1/f4
+    rm /config/usb_gadget/g1/configs/b.1/f5
+    write /config/usb_gadget/g1/idVendor 0x18d1
+    write /config/usb_gadget/g1/idProduct 0x4ee3
     symlink /config/usb_gadget/g1/functions/rndis.gs4 /config/usb_gadget/g1/configs/b.1/f1
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}
     setprop sys.usb.state ${sys.usb.config}
@@ -169,6 +226,10 @@
     rm /config/usb_gadget/g1/configs/b.1/f1
     rm /config/usb_gadget/g1/configs/b.1/f2
     rm /config/usb_gadget/g1/configs/b.1/f3
+    rm /config/usb_gadget/g1/configs/b.1/f4
+    rm /config/usb_gadget/g1/configs/b.1/f5
+    write /config/usb_gadget/g1/idVendor 0x18d1
+    write /config/usb_gadget/g1/idProduct 0x4ee4
     symlink /config/usb_gadget/g1/functions/rndis.gs4 /config/usb_gadget/g1/configs/b.1/f1
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index 6ef491c..d16e02f 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -35,7 +35,7 @@
 /dev/dri/*                0666   root       graphics
 
 # these should not be world writable
-/dev/diag                 0660   radio      radio
+/dev/diag                 0660   system     qcom_diag
 /dev/diag_arm9            0660   radio      radio
 /dev/android_adb          0660   adb        adb
 /dev/android_adb_enable   0660   adb        adb
@@ -45,7 +45,7 @@
 /dev/alarm                0664   system     radio
 /dev/rtc0                 0640   system     system
 /dev/tty0                 0660   root       system
-/dev/graphics/*           0660   root       graphics
+/dev/graphics/*           0660   system     graphics
 /dev/msm_hw3dm            0660   system     graphics
 /dev/input/*              0660   root       input
 /dev/eac                  0660   root       audio
diff --git a/sdcard/Android.mk b/sdcard/Android.mk
index c5f3d1d..9bfaf6c 100644
--- a/sdcard/Android.mk
+++ b/sdcard/Android.mk
@@ -1,7 +1,10 @@
 LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
-
+ifeq ($(call is-vendor-board-platform,QCOM),true)
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+endif
 LOCAL_SRC_FILES := sdcard.c
 LOCAL_MODULE := sdcard
 LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index 13ebaf1..4ba7d1b 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -1221,12 +1221,13 @@
     }
     out.fh = ptr_to_id(h);
     out.open_flags = 0;
-
-#ifdef FUSE_SHORTCIRCUIT
-    out.lower_fd = h->fd;
-#else
-    out.padding = 0;
-#endif
+    #ifdef FUSE_SHORTCIRCUIT
+        out.lower_fd = h->fd;
+    #elif defined FUSE_PASSTHROUGH
+        out.passthrough_fd = h->fd;
+    #else
+        out.padding = 0;
+    #endif
 
     fuse_reply(fuse, hdr->unique, &out, sizeof(out));
     return NO_STATUS;
@@ -1391,13 +1392,13 @@
     }
     out.fh = ptr_to_id(h);
     out.open_flags = 0;
-
-#ifdef FUSE_SHORTCIRCUIT
-    out.lower_fd = -1;
-#else
-    out.padding = 0;
-#endif
-
+    #ifdef FUSE_SHORTCIRCUIT
+        out.lower_fd = -1;
+    #elif defined FUSE_PASSTHROUGH
+        out.passthrough_fd = -1;
+    #else
+        out.padding = 0;
+    #endif
     fuse_reply(fuse, hdr->unique, &out, sizeof(out));
     return NO_STATUS;
 }
@@ -1480,9 +1481,12 @@
     out.max_readahead = req->max_readahead;
     out.flags = FUSE_ATOMIC_O_TRUNC | FUSE_BIG_WRITES;
 
-#ifdef FUSE_SHORTCIRCUIT
-    out.flags |= FUSE_SHORTCIRCUIT;
-#endif
+    #ifdef FUSE_SHORTCIRCUIT
+        out.flags |= FUSE_SHORTCIRCUIT;
+    #endif
+    #ifdef FUSE_PASSTHROUGH
+        out.flags |= FUSE_PASSTHROUGH;
+    #endif
 
     out.max_background = 32;
     out.congestion_threshold = 32;