Merge "Move LinearAlloc to libhwui"
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index e76c341..e59a96a 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -312,6 +312,7 @@
 static void copy_to_file(int inFd, int outFd) {
     const size_t BUFSIZE = 32 * 1024;
     char* buf = (char*) malloc(BUFSIZE);
+    if (buf == nullptr) fatal("couldn't allocate buffer for copy_to_file");
     int len;
     long total = 0;
 
@@ -419,6 +420,11 @@
     fdi = 0; //dup(0);
 
     int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2));
+    if (fds == nullptr) {
+        fprintf(stderr, "couldn't allocate fds array: %s\n", strerror(errno));
+        return 1;
+    }
+
     fds[0] = fd;
     fds[1] = fdi;
 
diff --git a/adb/services.cpp b/adb/services.cpp
index ff13722..e6c84a4 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -689,6 +689,10 @@
         return create_device_tracker();
     } else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) {
         auto sinfo = reinterpret_cast<state_info*>(malloc(sizeof(state_info)));
+        if (sinfo == nullptr) {
+            fprintf(stderr, "couldn't allocate state_info: %s", strerror(errno));
+            return NULL;
+        }
 
         if (serial)
             sinfo->serial = strdup(serial);
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 37f9d7b..d395a80 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -493,10 +493,8 @@
 asocket*
 create_device_tracker(void)
 {
-    device_tracker* tracker = reinterpret_cast<device_tracker*>(
-        calloc(1, sizeof(*tracker)));
-
-    if(tracker == 0) fatal("cannot allocate device tracker");
+    device_tracker* tracker = reinterpret_cast<device_tracker*>(calloc(1, sizeof(*tracker)));
+    if (tracker == nullptr) fatal("cannot allocate device tracker");
 
     D( "device tracker %p created\n", tracker);
 
@@ -1002,8 +1000,11 @@
 
 int register_socket_transport(int s, const char *serial, int port, int local)
 {
-    atransport *t = reinterpret_cast<atransport*>(
-        calloc(1, sizeof(atransport)));
+    atransport *t = reinterpret_cast<atransport*>(calloc(1, sizeof(atransport)));
+    if (t == nullptr) {
+        return -1;
+    }
+
     atransport *n;
     char buff[32];
 
@@ -1102,8 +1103,8 @@
 
 void register_usb_transport(usb_handle *usb, const char *serial, const char *devpath, unsigned writeable)
 {
-    atransport *t = reinterpret_cast<atransport*>(
-        calloc(1, sizeof(atransport)));
+    atransport *t = reinterpret_cast<atransport*>(calloc(1, sizeof(atransport)));
+    if (t == nullptr) fatal("cannot allocate USB atransport");
     D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
       serial ? serial : "");
     init_usb_transport(t, usb, (writeable ? CS_OFFLINE : CS_NOPERM));
diff --git a/adb/usb_linux.cpp b/adb/usb_linux.cpp
index 6fd2b40..9f23511 100644
--- a/adb/usb_linux.cpp
+++ b/adb/usb_linux.cpp
@@ -598,8 +598,8 @@
 
     D("[ usb located new device %s (%d/%d/%d) ]\n",
         dev_name, ep_in, ep_out, interface);
-    usb_handle* usb = reinterpret_cast<usb_handle*>(
-        calloc(1, sizeof(usb_handle)));
+    usb_handle* usb = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
+    if (usb == nullptr) fatal("couldn't allocate usb_handle");
     strcpy(usb->fname, dev_name);
     usb->ep_in = ep_in;
     usb->ep_out = ep_out;
diff --git a/adb/usb_linux_client.cpp b/adb/usb_linux_client.cpp
index 6d21104..18289e2 100644
--- a/adb/usb_linux_client.cpp
+++ b/adb/usb_linux_client.cpp
@@ -241,6 +241,8 @@
 static void usb_adb_init()
 {
     usb_handle* h = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
+    if (h == nullptr) fatal("couldn't allocate usb_handle");
+
     h->write = usb_adb_write;
     h->read = usb_adb_read;
     h->kick = usb_adb_kick;
@@ -468,6 +470,8 @@
     D("[ usb_init - using FunctionFS ]\n");
 
     usb_handle* h = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
+    if (h == nullptr) fatal("couldn't allocate usb_handle");
+
     h->write = usb_ffs_write;
     h->read = usb_ffs_read;
     h->kick = usb_ffs_kick;
diff --git a/adb/usb_osx.cpp b/adb/usb_osx.cpp
index 303ae45..a795ce3 100644
--- a/adb/usb_osx.cpp
+++ b/adb/usb_osx.cpp
@@ -336,6 +336,7 @@
         goto err_bad_adb_interface;
 
     handle = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
+    if (handle == nullptr) goto err_bad_adb_interface;
 
     //* Iterate over the endpoints for this interface and find the first
     //* bulk in/out pipes available.  These will be our read/write pipes.
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 3bbaf83..4567b04 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -515,15 +515,6 @@
     return ret;
 }
 
-int do_setcon(int nargs, char **args) {
-    if (is_selinux_enabled() <= 0)
-        return 0;
-    if (setcon(args[1]) < 0) {
-        return -errno;
-    }
-    return 0;
-}
-
 int do_setprop(int nargs, char **args)
 {
     const char *name = args[1];
diff --git a/init/init.cpp b/init/init.cpp
index b1d65db..ed20661 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -940,7 +940,13 @@
     return 0;
 }
 
-static void selinux_initialize() {
+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;
 
     selinux_callback cb;
@@ -953,19 +959,27 @@
         return;
     }
 
-    INFO("Loading SELinux policy...\n");
-    if (selinux_android_load_policy() < 0) {
-        ERROR("SELinux: Failed to load policy; rebooting into recovery mode\n");
-        android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
-        while (1) { pause(); }  // never reached
+    if (in_kernel_domain) {
+        if (write_file("/sys/fs/selinux/checkreqprot", "0") == -1) {
+            ERROR("couldn't write to /sys/fs/selinux/checkreqprot: %s\n",
+                  strerror(errno));
+            security_failure();
+        }
+
+        INFO("Loading SELinux policy...\n");
+        if (selinux_android_load_policy() < 0) {
+            ERROR("failed to load policy: %s\n", strerror(errno));
+            security_failure();
+        }
+
+        bool is_enforcing = selinux_is_enforcing();
+        security_setenforce(is_enforcing);
+
+        NOTICE("(Initializing SELinux %s took %.2fs.)\n",
+               is_enforcing ? "enforcing" : "non-enforcing", t.duration());
+    } else {
+        selinux_init_all_handles();
     }
-
-    selinux_init_all_handles();
-    bool is_enforcing = selinux_is_enforcing();
-    INFO("SELinux: security_setenforce(%d)\n", is_enforcing);
-    security_setenforce(is_enforcing);
-
-    NOTICE("(Initializing SELinux took %.2fs.)\n", t.duration());
 }
 
 int main(int argc, char** argv) {
@@ -1006,7 +1020,8 @@
     klog_init();
     klog_set_level(KLOG_NOTICE_LEVEL);
 
-    NOTICE("init started!\n");
+    bool is_first_stage = (argc == 1);
+    NOTICE("init%s started!\n", is_first_stage ? "" : " second stage");
 
     property_init();
 
@@ -1019,7 +1034,23 @@
     // used by init as well as the current required properties.
     export_kernel_boot_props();
 
-    selinux_initialize();
+    // Set up SELinux, including loading the SELinux policy if we're in the kernel domain.
+    selinux_initialize(is_first_stage);
+
+    // If we're in the kernel domain, re-exec init to transition to the init domain now
+    // that the SELinux policy has been loaded.
+    if (is_first_stage) {
+        if (restorecon("/init") == -1) {
+            ERROR("restorecon failed: %s\n", strerror(errno));
+            security_failure();
+        }
+        char* path = argv[0];
+        char* args[] = { path, const_cast<char*>("--second-stage"), nullptr };
+        if (execv(path, args) == -1) {
+            ERROR("execv(\"%s\") failed: %s\n", path, strerror(errno));
+            security_failure();
+        }
+    }
 
     // These directories were necessarily created before initial policy load
     // and therefore need their security context restored to the proper value.
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index ff31093..b76b04e 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -184,7 +184,6 @@
     case 's':
         if (!strcmp(s, "eclabel")) return K_seclabel;
         if (!strcmp(s, "ervice")) return K_service;
-        if (!strcmp(s, "etcon")) return K_setcon;
         if (!strcmp(s, "etenv")) return K_setenv;
         if (!strcmp(s, "etprop")) return K_setprop;
         if (!strcmp(s, "etrlimit")) return K_setrlimit;
diff --git a/init/keywords.h b/init/keywords.h
index 059dde1..37f01b8 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -20,7 +20,6 @@
 int do_restorecon_recursive(int nargs, char **args);
 int do_rm(int nargs, char **args);
 int do_rmdir(int nargs, char **args);
-int do_setcon(int nargs, char **args);
 int do_setprop(int nargs, char **args);
 int do_setrlimit(int nargs, char **args);
 int do_start(int nargs, char **args);
@@ -76,7 +75,6 @@
     KEYWORD(rmdir,       COMMAND, 1, do_rmdir)
     KEYWORD(seclabel,    OPTION,  0, 0)
     KEYWORD(service,     SECTION, 0, 0)
-    KEYWORD(setcon,      COMMAND, 1, do_setcon)
     KEYWORD(setenv,      OPTION,  2, 0)
     KEYWORD(setprop,     COMMAND, 2, do_setprop)
     KEYWORD(setrlimit,   COMMAND, 3, do_setrlimit)
diff --git a/init/readme.txt b/init/readme.txt
index 84afd11..6b9c42d 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -252,11 +252,6 @@
 rmdir <path>
    Calls rmdir(2) on the given path.
 
-setcon <seclabel>
-   Set the current process security context to the specified string.
-   This is typically only used from early-init to set the init context
-   before any other process is started.
-
 setprop <name> <value>
    Set system property <name> to <value>. Properties are expanded
    within <value>.
diff --git a/liblog/log_is_loggable.c b/liblog/log_is_loggable.c
index df67123..2e09192 100644
--- a/liblog/log_is_loggable.c
+++ b/liblog/log_is_loggable.c
@@ -28,7 +28,7 @@
         return def;
     }
     {
-        static const char log_namespace[] = "log.tag.";
+        static const char log_namespace[] = "persist.log.tag.";
         char key[sizeof(log_namespace) + strlen(tag)];
 
         strcpy(key, log_namespace);
@@ -37,6 +37,9 @@
         if (__system_property_get(key + 8, buf) <= 0) {
             buf[0] = '\0';
         }
+        if (!buf[0] && __system_property_get(key, buf) <= 0) {
+            buf[0] = '\0';
+        }
     }
     switch (toupper(buf[0])) {
         case 'V': return ANDROID_LOG_VERBOSE;
@@ -53,17 +56,6 @@
 
 int __android_log_is_loggable(int prio, const char *tag, int def)
 {
-    static char user;
-    int logLevel;
-
-    if (user == 0) {
-        char buf[PROP_VALUE_MAX];
-        if (__system_property_get("ro.build.type", buf) <= 0) {
-            buf[0] = '\0';
-        }
-        user = strcmp(buf, "user") ? -1 : 1;
-    }
-
-    logLevel = (user == 1) ? def : __android_log_level(tag, def);
+    int logLevel = __android_log_level(tag, def);
     return logLevel >= 0 && prio >= logLevel;
 }
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 1859461..1dced11 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -247,7 +247,7 @@
     uint64_t getKey() { return value; }
 };
 
-struct LogBufferElementEntry {
+class LogBufferElementEntry {
     const uint64_t key;
     LogBufferElement *last;
 
@@ -259,8 +259,9 @@
     LogBufferElement *getLast() { return last; }
 };
 
-struct LogBufferElementLast : public android::BasicHashtable<uint64_t, LogBufferElementEntry> {
+class LogBufferElementLast : public android::BasicHashtable<uint64_t, LogBufferElementEntry> {
 
+public:
     bool merge(LogBufferElement *e, unsigned short dropped) {
         LogBufferElementKey key(e->getUid(), e->getPid(), e->getTid());
         android::hash_t hash = android::hash_type(key.getKey());
@@ -286,6 +287,21 @@
             add(hash, LogBufferElementEntry(key.getKey(), e));
     }
 
+    inline void clear() {
+        android::BasicHashtable<uint64_t, LogBufferElementEntry>::clear();
+    }
+
+    void clear(LogBufferElement *e) {
+        uint64_t current = e->getRealTime().nsec() - NS_PER_SEC;
+        ssize_t index = -1;
+        while((index = next(index)) >= 0) {
+            if (current > editEntryAt(index).getLast()->getRealTime().nsec()) {
+                removeAt(index);
+                index = -1;
+            }
+        }
+    }
+
 };
 
 // prune "pruneRows" of type "id" from the buffer.
@@ -349,9 +365,16 @@
 
             if (sorted.get()) {
                 if (sorted[0] && sorted[1]) {
-                    worst = sorted[0]->getKey();
                     worst_sizes = sorted[0]->getSizes();
-                    second_worst_sizes = sorted[1]->getSizes();
+                    // Calculate threshold as 12.5% of available storage
+                    size_t threshold = log_buffer_size(id) / 8;
+                    if (worst_sizes > threshold) {
+                        worst = sorted[0]->getKey();
+                        second_worst_sizes = sorted[1]->getSizes();
+                        if (second_worst_sizes < threshold) {
+                            second_worst_sizes = threshold;
+                        }
+                    }
                 }
             }
         }
@@ -395,7 +418,7 @@
             leading = false;
 
             if (hasBlacklist && mPrune.naughty(e)) {
-                last.clear();
+                last.clear(e);
                 it = erase(it);
                 if (dropped) {
                     continue;
@@ -423,7 +446,7 @@
             }
 
             if (e->getUid() != worst) {
-                last.clear();
+                last.clear(e);
                 ++it;
                 continue;
             }
diff --git a/rootdir/etc/mountd.conf b/rootdir/etc/mountd.conf
deleted file mode 100644
index 094a2c7..0000000
--- a/rootdir/etc/mountd.conf
+++ /dev/null
@@ -1,19 +0,0 @@
-## mountd configuration file
-
-## add a mount entry for each mount point to be managed by mountd
-mount {
-    ## root block device with partition map or raw FAT file system
-    block_device    /dev/block/mmcblk0
-        
-    ## mount point for block device
-    mount_point     /sdcard
-    
-    ## true if this mount point can be shared via USB mass storage
-    enable_ums      true
-    
-    ## path to the UMS driver file for specifying the block device path  
-    ## use this for the mass_storage function driver
-    driver_store_path   /sys/devices/platform/usb_mass_storage/lun0/file
-    ## use this for android_usb composite gadget driver
-    ##driver_store_path   /sys/devices/platform/msm_hsusb/gadget/lun0/file
-}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 696c9b9..bdcaee4 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -14,13 +14,6 @@
     # Set init and its forked children's oom_adj.
     write /proc/1/oom_score_adj -1000
 
-    # Apply strict SELinux checking of PROT_EXEC on mmap/mprotect calls.
-    write /sys/fs/selinux/checkreqprot 0
-
-    # Set the security context for the init process.
-    # This should occur before anything else (e.g. ueventd) is started.
-    setcon u:r:init:s0
-
     # Set the security context of /adb_keys if present.
     restorecon /adb_keys
 
@@ -165,6 +158,7 @@
 # Load properties from /system/ + /factory after fs mount.
 on load_all_props_action
     load_all_props
+    start logd
     start logd-reinit
 
 # Indicate to fw loaders that the relevant mounts are up.
@@ -461,6 +455,7 @@
 
 on property:vold.decrypt=trigger_load_persist_props
     load_persist_props
+    start logd
     start logd-reinit
 
 on property:vold.decrypt=trigger_post_fs_data
@@ -506,7 +501,6 @@
     socket logdw dgram 0222 logd logd
 
 service logd-reinit /system/bin/logd --reinit
-    start logd
     oneshot
     disabled
 
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index 4712e90..f8b23a3 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -1866,7 +1866,7 @@
     struct fuse fuse;
 
     /* cleanup from previous instance, if necessary */
-    umount2(dest_path, 2);
+    umount2(dest_path, MNT_DETACH);
 
     fd = open("/dev/fuse", O_RDWR);
     if (fd < 0){