Merge "Remove a homebrew mmap64."
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 82c5798..9a84a4e 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -235,74 +235,16 @@
     return f;
 }
 
-/* Read a line of text till the next newline character.
- * If no newline is found before the buffer is full, continue reading till a new line is seen,
- * then return an empty buffer.  This effectively ignores lines that are too long.
- * On EOF, return null.
- */
-static char *fs_getline(char *buf, int size, FILE *file)
-{
-    int cnt = 0;
-    int eof = 0;
-    int eol = 0;
-    int c;
-
-    if (size < 1) {
-        return NULL;
-    }
-
-    while (cnt < (size - 1)) {
-        c = getc(file);
-        if (c == EOF) {
-            eof = 1;
-            break;
-        }
-
-        *(buf + cnt) = c;
-        cnt++;
-
-        if (c == '\n') {
-            eol = 1;
-            break;
-        }
-    }
-
-    /* Null terminate what we've read */
-    *(buf + cnt) = '\0';
-
-    if (eof) {
-        if (cnt) {
-            return buf;
-        } else {
-            return NULL;
-        }
-    } else if (eol) {
-        return buf;
-    } else {
-        /* The line is too long.  Read till a newline or EOF.
-         * If EOF, return null, if newline, return an empty buffer.
-         */
-        while(1) {
-            c = getc(file);
-            if (c == EOF) {
-                return NULL;
-            } else if (c == '\n') {
-                *buf = '\0';
-                return buf;
-            }
-        }
-    }
-}
-
 struct fstab *fs_mgr_read_fstab(const char *fstab_path)
 {
     FILE *fstab_file;
     int cnt, entries;
-    int len;
-    char line[256];
+    ssize_t len;
+    size_t alloc_len = 0;
+    char *line = NULL;
     const char *delim = " \t";
     char *save_ptr, *p;
-    struct fstab *fstab;
+    struct fstab *fstab = NULL;
     struct fstab_rec *recs;
     struct fs_mgr_flag_values flag_vals;
 #define FS_OPTIONS_LEN 1024
@@ -315,9 +257,8 @@
     }
 
     entries = 0;
-    while (fs_getline(line, sizeof(line), fstab_file)) {
+    while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
         /* if the last character is a newline, shorten the string by 1 byte */
-        len = strlen(line);
         if (line[len - 1] == '\n') {
             line[len - 1] = '\0';
         }
@@ -334,7 +275,7 @@
 
     if (!entries) {
         ERROR("No entries found in fstab\n");
-        return 0;
+        goto err;
     }
 
     /* Allocate and init the fstab structure */
@@ -346,9 +287,8 @@
     fseek(fstab_file, 0, SEEK_SET);
 
     cnt = 0;
-    while (fs_getline(line, sizeof(line), fstab_file)) {
+    while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
         /* if the last character is a newline, shorten the string by 1 byte */
-        len = strlen(line);
         if (line[len - 1] == '\n') {
             line[len - 1] = '\0';
         }
@@ -373,25 +313,25 @@
 
         if (!(p = strtok_r(line, delim, &save_ptr))) {
             ERROR("Error parsing mount source\n");
-            return 0;
+            goto err;
         }
         fstab->recs[cnt].blk_device = strdup(p);
 
         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
             ERROR("Error parsing mount_point\n");
-            return 0;
+            goto err;
         }
         fstab->recs[cnt].mount_point = strdup(p);
 
         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
             ERROR("Error parsing fs_type\n");
-            return 0;
+            goto err;
         }
         fstab->recs[cnt].fs_type = strdup(p);
 
         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
             ERROR("Error parsing mount_flags\n");
-            return 0;
+            goto err;
         }
         tmp_fs_options[0] = '\0';
         fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL,
@@ -406,7 +346,7 @@
 
         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
             ERROR("Error parsing fs_mgr_options\n");
-            return 0;
+            goto err;
         }
         fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags,
                                                     &flag_vals, NULL, 0);
@@ -419,8 +359,15 @@
         cnt++;
     }
     fclose(fstab_file);
-
+    free(line);
     return fstab;
+
+err:
+    fclose(fstab_file);
+    free(line);
+    if (fstab)
+        fs_mgr_free_fstab(fstab);
+    return NULL;
 }
 
 void fs_mgr_free_fstab(struct fstab *fstab)
@@ -435,7 +382,6 @@
         free(fstab->recs[i].fs_options);
         free(fstab->recs[i].key_loc);
         free(fstab->recs[i].label);
-        i++;
     }
 
     /* Free the fstab_recs array created by calloc(3) */
diff --git a/include/cutils/trace.h b/include/cutils/trace.h
index a0dd1e0..1c8f107 100644
--- a/include/cutils/trace.h
+++ b/include/cutils/trace.h
@@ -259,6 +259,23 @@
     }
 }
 
+/**
+ * Traces a 64-bit integer counter value.  name is used to identify the
+ * counter. This can be used to track how a value changes over time.
+ */
+#define ATRACE_INT64(name, value) atrace_int64(ATRACE_TAG, name, value)
+static inline void atrace_int64(uint64_t tag, const char* name, int64_t value)
+{
+    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
+        char buf[ATRACE_MESSAGE_LENGTH];
+        size_t len;
+
+        len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "C|%d|%s|%lld",
+                getpid(), name, value);
+        write(atrace_marker_fd, buf, len);
+    }
+}
+
 #else // not HAVE_ANDROID_OS
 
 #define ATRACE_INIT()
diff --git a/include/system/graphics.h b/include/system/graphics.h
index 154f9cb..be86ae4 100644
--- a/include/system/graphics.h
+++ b/include/system/graphics.h
@@ -293,6 +293,8 @@
     HAL_TRANSFORM_ROT_180   = 0x03,
     /* rotate source image 270 degrees clockwise */
     HAL_TRANSFORM_ROT_270   = 0x07,
+    /* don't use. see system/window.h */
+    HAL_TRANSFORM_RESERVED  = 0x08,
 };
 
 #ifdef __cplusplus
diff --git a/include/system/window.h b/include/system/window.h
index 7ce59e0..649bd71 100644
--- a/include/system/window.h
+++ b/include/system/window.h
@@ -296,12 +296,15 @@
     NATIVE_WINDOW_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H ,
     /* flip source image vertically */
     NATIVE_WINDOW_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V,
-    /* rotate source image 90 degrees clock-wise */
+    /* rotate source image 90 degrees clock-wise, and is applied after TRANSFORM_FLIP_{H|V} */
     NATIVE_WINDOW_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90,
     /* rotate source image 180 degrees */
     NATIVE_WINDOW_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180,
     /* rotate source image 270 degrees clock-wise */
     NATIVE_WINDOW_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270,
+    /* transforms source by the inverse transform of the screen it is displayed onto. This
+     * transform is applied last */
+    NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY = 0x08
 };
 
 /* parameter for NATIVE_WINDOW_SET_SCALING_MODE */
diff --git a/init/util.c b/init/util.c
index 078b99b..9aaa77d 100644
--- a/init/util.c
+++ b/init/util.c
@@ -405,7 +405,9 @@
 
 void get_hardware_name(char *hardware, unsigned int *revision)
 {
-    char data[1024];
+    const char *cpuinfo = "/proc/cpuinfo";
+    char *data = NULL;
+    size_t len = 0, limit = 1024;
     int fd, n;
     char *x, *hw, *rev;
 
@@ -413,14 +415,32 @@
     if (hardware[0])
         return;
 
-    fd = open("/proc/cpuinfo", O_RDONLY);
+    fd = open(cpuinfo, O_RDONLY);
     if (fd < 0) return;
 
-    n = read(fd, data, 1023);
-    close(fd);
-    if (n < 0) return;
+    for (;;) {
+        x = realloc(data, limit);
+        if (!x) {
+            ERROR("Failed to allocate memory to read %s\n", cpuinfo);
+            goto done;
+        }
+        data = x;
 
-    data[n] = 0;
+        n = read(fd, data + len, limit - len);
+        if (n < 0) {
+            ERROR("Failed reading %s: %s (%d)\n", cpuinfo, strerror(errno), errno);
+            goto done;
+        }
+        len += n;
+
+        if (len < limit)
+            break;
+
+        /* We filled the buffer, so increase size and loop to read more */
+        limit *= 2;
+    }
+
+    data[len] = 0;
     hw = strstr(data, "\nHardware");
     rev = strstr(data, "\nRevision");
 
@@ -445,6 +465,10 @@
             *revision = strtoul(x + 2, 0, 16);
         }
     }
+
+done:
+    close(fd);
+    free(data);
 }
 
 void import_kernel_cmdline(int in_qemu,
diff --git a/libsparse/Android.mk b/libsparse/Android.mk
index 9025cc0..a21e090 100644
--- a/libsparse/Android.mk
+++ b/libsparse/Android.mk
@@ -82,8 +82,8 @@
 
 
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES := simg2simg.c
-LOCAL_MODULE := simg2simg
+LOCAL_SRC_FILES := append2simg.c
+LOCAL_MODULE := append2simg
 LOCAL_STATIC_LIBRARIES := \
     libsparse_host \
     libz
diff --git a/libsparse/append2simg.c b/libsparse/append2simg.c
new file mode 100644
index 0000000..180584f
--- /dev/null
+++ b/libsparse/append2simg.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _FILE_OFFSET_BITS 64
+#define _LARGEFILE64_SOURCE 1
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sparse/sparse.h>
+#include "sparse_file.h"
+#include "backed_block.h"
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#if defined(__APPLE__) && defined(__MACH__)
+#define lseek64 lseek
+#endif
+#if defined(__APPLE__) && defined(__MACH__)
+#define lseek64 lseek
+#define off64_t off_t
+#endif
+
+void usage()
+{
+    fprintf(stderr, "Usage: append2simg <output> <input>\n");
+}
+
+int main(int argc, char *argv[])
+{
+    int output;
+    int output_block;
+    char *output_path;
+    struct sparse_file *sparse_output;
+
+    int input;
+    char *input_path;
+    off64_t input_len;
+
+    if (argc == 3) {
+        output_path = argv[1];
+        input_path = argv[2];
+    } else {
+        usage();
+        exit(-1);
+    }
+
+    output = open(output_path, O_RDWR | O_BINARY);
+    if (output < 0) {
+        fprintf(stderr, "Couldn't open output file (%s)\n", strerror(errno));
+        exit(-1);
+    }
+
+    sparse_output = sparse_file_import_auto(output, true);
+    if (!sparse_output) {
+        fprintf(stderr, "Couldn't import output file\n");
+        exit(-1);
+    }
+
+    input = open(input_path, O_RDONLY | O_BINARY);
+    if (input < 0) {
+        fprintf(stderr, "Couldn't open input file (%s)\n", strerror(errno));
+        exit(-1);
+    }
+
+    input_len = lseek64(input, 0, SEEK_END);
+    if (input_len < 0) {
+        fprintf(stderr, "Couldn't get input file length (%s)\n", strerror(errno));
+        exit(-1);
+    } else if (input_len % sparse_output->block_size) {
+        fprintf(stderr, "Input file is not a multiple of the output file's block size");
+        exit(-1);
+    }
+    lseek64(input, 0, SEEK_SET);
+
+    output_block = sparse_output->len / sparse_output->block_size;
+    if (sparse_file_add_fd(sparse_output, input, 0, input_len, output_block) < 0) {
+        fprintf(stderr, "Couldn't add input file\n");
+        exit(-1);
+    }
+    sparse_output->len += input_len;
+
+    lseek64(output, 0, SEEK_SET);
+    if (sparse_file_write(sparse_output, output, false, true, false) < 0) {
+        fprintf(stderr, "Failed to write sparse file\n");
+        exit(-1);
+    }
+
+    sparse_file_destroy(sparse_output);
+    close(output);
+    close(input);
+    exit(0);
+}
diff --git a/libsparse/output_file.c b/libsparse/output_file.c
index 5014e4a..2428022 100644
--- a/libsparse/output_file.c
+++ b/libsparse/output_file.c
@@ -46,15 +46,6 @@
 #define off64_t off_t
 #endif
 
-#ifdef __BIONIC__
-extern void*  __mmap2(void *, size_t, int, int, int, off_t);
-static inline void *mmap64(void *addr, size_t length, int prot, int flags,
-        int fd, off64_t offset)
-{
-    return __mmap2(addr, length, prot, flags, fd, offset >> 12);
-}
-#endif
-
 #define min(a, b) \
 	({ typeof(a) _a = (a); typeof(b) _b = (b); (_a < _b) ? _a : _b; })
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 3f6ce6d..3d17124 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -181,6 +181,9 @@
     # We restorecon /data in case the userdata partition has been reset.
     restorecon /data
 
+    # Avoid predictable entropy pool. Carry over entropy from previous boot.
+    copy /data/system/entropy.dat /dev/urandom
+
     # Create dump dir and collect dumps.
     # Do this before we mount cache so eventually we can use cache for
     # storing dumps on platforms which do not have a dedicated dump partition.
@@ -346,7 +349,6 @@
     chown root radio /proc/cmdline
 
 # Set these so we can remotely update SELinux policy
-    chown system system /sys/fs/selinux/load
     chown system system /sys/fs/selinux/enforce
 
 # Define TCP buffer sizes for various networks