Merge "Check pointer for null before dereferencing"
diff --git a/Android.mk b/Android.mk
index 508eb4c..282862f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,5 +1,3 @@
-ifneq ($(TARGET_SIMULATOR),true)
-
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -74,5 +72,3 @@
 include $(commands_recovery_local_path)/updater/Android.mk
 include $(commands_recovery_local_path)/applypatch/Android.mk
 commands_recovery_local_path :=
-
-endif    # !TARGET_SIMULATOR
diff --git a/applypatch/Android.mk b/applypatch/Android.mk
index 2848b51..0e529d4 100644
--- a/applypatch/Android.mk
+++ b/applypatch/Android.mk
@@ -12,8 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-ifneq ($(TARGET_SIMULATOR),true)
-
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -57,5 +55,3 @@
 LOCAL_STATIC_LIBRARIES += libz libbz
 
 include $(BUILD_HOST_EXECUTABLE)
-
-endif  # !TARGET_SIMULATOR
diff --git a/default_recovery_ui.c b/default_recovery_ui.c
index 7c4017e..d56164e 100644
--- a/default_recovery_ui.c
+++ b/default_recovery_ui.c
@@ -27,6 +27,7 @@
                        "apply update from external storage",
                        "wipe data/factory reset",
                        "wipe cache partition",
+                       "apply update from cache",
                        NULL };
 
 void device_ui_init(UIParameters* ui_parameters) {
diff --git a/etc/init.rc b/etc/init.rc
index a675a4b..554d4e6 100644
--- a/etc/init.rc
+++ b/etc/init.rc
@@ -31,8 +31,20 @@
 service adbd /sbin/adbd recovery
     disabled
 
-on property:persist.service.adb.enable=1
+# Always start adbd on userdebug and eng builds
+on property:ro.debuggable=1
+    write /sys/class/android_usb/android0/enable 0
+    write /sys/class/android_usb/android0/idVendor 18D1
+    write /sys/class/android_usb/android0/idProduct D001
+    write /sys/class/android_usb/android0/functions adb
+    write /sys/class/android_usb/android0/enable 1
+    write /sys/class/android_usb/android0/iManufacturer $ro.product.manufacturer
+    write /sys/class/android_usb/android0/iProduct $ro.product.model
+    write /sys/class/android_usb/android0/iSerial $ro.serialno
     start adbd
 
-on property:persist.service.adb.enable=0
-    stop adbd
+# Restart adbd so it can run as root
+on property:service.adb.root=1
+    write /sys/class/android_usb/android0/enable 0
+    restart adbd
+    write /sys/class/android_usb/android0/enable 1
diff --git a/minui/Android.mk b/minui/Android.mk
index 7ded5d3..4c4d7c7 100644
--- a/minui/Android.mk
+++ b/minui/Android.mk
@@ -9,8 +9,11 @@
 
 LOCAL_MODULE := libminui
 
-ifneq ($(RECOVERY_24_BIT),)
-  LOCAL_CFLAGS += -DRECOVERY_24_BIT
+ifeq ($(TARGET_RECOVERY_PIXEL_FORMAT),"RGBX_8888")
+  LOCAL_CFLAGS += -DRECOVERY_RGBX
+endif
+ifeq ($(TARGET_RECOVERY_PIXEL_FORMAT),"BGRA_8888")
+  LOCAL_CFLAGS += -DRECOVERY_BGRA
 endif
 
 include $(BUILD_STATIC_LIBRARY)
diff --git a/minui/graphics.c b/minui/graphics.c
index 42c85e7..b79631a 100644
--- a/minui/graphics.c
+++ b/minui/graphics.c
@@ -32,7 +32,10 @@
 #include "font_10x18.h"
 #include "minui.h"
 
-#ifdef RECOVERY_24_BIT
+#if defined(RECOVERY_BGRA)
+#define PIXEL_FORMAT GGL_PIXEL_FORMAT_BGRA_8888
+#define PIXEL_SIZE   4
+#elif defined(RECOVERY_RGBX)
 #define PIXEL_FORMAT GGL_PIXEL_FORMAT_RGBX_8888
 #define PIXEL_SIZE   4
 #else
@@ -58,11 +61,11 @@
 static int gr_vt_fd = -1;
 
 static struct fb_var_screeninfo vi;
+static struct fb_fix_screeninfo fi;
 
 static int get_framebuffer(GGLSurface *fb)
 {
     int fd;
-    struct fb_fix_screeninfo fi;
     void *bits;
 
     fd = open("/dev/graphics/fb0", O_RDWR);
@@ -71,13 +74,48 @@
         return -1;
     }
 
-    if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
+    if (ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
         perror("failed to get fb0 info");
         close(fd);
         return -1;
     }
 
-    if (ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
+    vi.bits_per_pixel = PIXEL_SIZE * 8;
+    if (PIXEL_FORMAT == GGL_PIXEL_FORMAT_BGRA_8888) {
+      vi.red.offset     = 8;
+      vi.red.length     = 8;
+      vi.green.offset   = 16;
+      vi.green.length   = 8;
+      vi.blue.offset    = 24;
+      vi.blue.length    = 8;
+      vi.transp.offset  = 0;
+      vi.transp.length  = 8;
+    } else if (PIXEL_FORMAT == GGL_PIXEL_FORMAT_RGBX_8888) {
+      vi.red.offset     = 24;
+      vi.red.length     = 8;
+      vi.green.offset   = 16;
+      vi.green.length   = 8;
+      vi.blue.offset    = 8;
+      vi.blue.length    = 8;
+      vi.transp.offset  = 0;
+      vi.transp.length  = 8;
+    } else { /* RGB565*/
+      vi.red.offset     = 11;
+      vi.red.length     = 5;
+      vi.green.offset   = 5;
+      vi.green.length   = 6;
+      vi.blue.offset    = 0;
+      vi.blue.length    = 5;
+      vi.transp.offset  = 0;
+      vi.transp.length  = 0;
+    }
+    if (ioctl(fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
+        perror("failed to put fb0 info");
+        close(fd);
+        return -1;
+    }
+
+    if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
         perror("failed to get fb0 info");
         close(fd);
         return -1;
@@ -93,20 +131,20 @@
     fb->version = sizeof(*fb);
     fb->width = vi.xres;
     fb->height = vi.yres;
-    fb->stride = vi.xres;
+    fb->stride = fi.line_length/PIXEL_SIZE;
     fb->data = bits;
     fb->format = PIXEL_FORMAT;
-    memset(fb->data, 0, vi.yres * vi.xres * PIXEL_SIZE);
+    memset(fb->data, 0, vi.yres * fi.line_length);
 
     fb++;
 
     fb->version = sizeof(*fb);
     fb->width = vi.xres;
     fb->height = vi.yres;
-    fb->stride = vi.xres;
-    fb->data = (void*) (((unsigned) bits) + vi.yres * vi.xres * PIXEL_SIZE);
+    fb->stride = fi.line_length/PIXEL_SIZE;
+    fb->data = (void*) (((unsigned) bits) + vi.yres * fi.line_length);
     fb->format = PIXEL_FORMAT;
-    memset(fb->data, 0, vi.yres * vi.xres * PIXEL_SIZE);
+    memset(fb->data, 0, vi.yres * fi.line_length);
 
     return fd;
 }
@@ -115,8 +153,8 @@
   ms->version = sizeof(*ms);
   ms->width = vi.xres;
   ms->height = vi.yres;
-  ms->stride = vi.xres;
-  ms->data = malloc(vi.xres * vi.yres * PIXEL_SIZE);
+  ms->stride = fi.line_length/PIXEL_SIZE;
+  ms->data = malloc(fi.line_length * vi.yres);
   ms->format = PIXEL_FORMAT;
 }
 
@@ -141,7 +179,7 @@
     /* copy data from the in-memory surface to the buffer we're about
      * to make active. */
     memcpy(gr_framebuffer[gr_active_fb].data, gr_mem_surface.data,
-           vi.xres * vi.yres * PIXEL_SIZE);
+           fi.line_length * vi.yres);
 
     /* inform the display driver */
     set_active_framebuffer(gr_active_fb);
diff --git a/mtdutils/Android.mk b/mtdutils/Android.mk
index 4166536..ef417fa 100644
--- a/mtdutils/Android.mk
+++ b/mtdutils/Android.mk
@@ -1,5 +1,3 @@
-ifneq ($(TARGET_SIMULATOR),true)
-
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -18,5 +16,3 @@
 LOCAL_STATIC_LIBRARIES := libmtdutils
 LOCAL_SHARED_LIBRARIES := libcutils libc
 include $(BUILD_EXECUTABLE)
-
-endif	# !TARGET_SIMULATOR
diff --git a/recovery.c b/recovery.c
index 3a412d5..1e3eb5a 100644
--- a/recovery.c
+++ b/recovery.c
@@ -52,6 +52,7 @@
 static const char *INTENT_FILE = "/cache/recovery/intent";
 static const char *LOG_FILE = "/cache/recovery/log";
 static const char *LAST_LOG_FILE = "/cache/recovery/last_log";
+static const char *CACHE_ROOT = "/cache";
 static const char *SDCARD_ROOT = "/sdcard";
 static const char *TEMPORARY_LOG_FILE = "/tmp/recovery.log";
 static const char *SIDELOAD_TEMP_DIR = "/tmp/sideload";
@@ -468,8 +469,8 @@
 }
 
 static int
-sdcard_directory(const char* path) {
-    ensure_path_mounted(SDCARD_ROOT);
+update_directory(const char* path, const char* unmount_when_done) {
+    ensure_path_mounted(path);
 
     const char* MENU_HEADERS[] = { "Choose a package to install:",
                                    path,
@@ -480,7 +481,9 @@
     d = opendir(path);
     if (d == NULL) {
         LOGE("error opening %s: %s\n", path, strerror(errno));
-        ensure_path_unmounted(SDCARD_ROOT);
+        if (unmount_when_done != NULL) {
+            ensure_path_unmounted(unmount_when_done);
+        }
         return 0;
     }
 
@@ -545,7 +548,7 @@
         char* item = zips[chosen_item];
         int item_len = strlen(item);
         if (chosen_item == 0) {          // item 0 is always "../"
-            // go up but continue browsing (if the caller is sdcard_directory)
+            // go up but continue browsing (if the caller is update_directory)
             result = -1;
             break;
         } else if (item[item_len-1] == '/') {
@@ -555,7 +558,7 @@
             strlcat(new_path, "/", PATH_MAX);
             strlcat(new_path, item, PATH_MAX);
             new_path[strlen(new_path)-1] = '\0';  // truncate the trailing '/'
-            result = sdcard_directory(new_path);
+            result = update_directory(new_path, unmount_when_done);
             if (result >= 0) break;
         } else {
             // selected a zip file:  attempt to install it, and return
@@ -568,7 +571,9 @@
             ui_print("\n-- Install %s ...\n", path);
             set_sdcard_update_bootloader_message();
             char* copy = copy_sideloaded_package(new_path);
-            ensure_path_unmounted(SDCARD_ROOT);
+            if (unmount_when_done != NULL) {
+                ensure_path_unmounted(unmount_when_done);
+            }
             if (copy) {
                 result = install_package(copy);
                 free(copy);
@@ -584,7 +589,9 @@
     free(zips);
     free(headers);
 
-    ensure_path_unmounted(SDCARD_ROOT);
+    if (unmount_when_done != NULL) {
+        ensure_path_unmounted(unmount_when_done);
+    }
     return result;
 }
 
@@ -642,6 +649,7 @@
         // statement below.
         chosen_item = device_perform_action(chosen_item);
 
+        int status;
         switch (chosen_item) {
             case ITEM_REBOOT:
                 return;
@@ -659,8 +667,7 @@
                 break;
 
             case ITEM_APPLY_SDCARD:
-                ;
-                int status = sdcard_directory(SDCARD_ROOT);
+                status = update_directory(SDCARD_ROOT, SDCARD_ROOT);
                 if (status >= 0) {
                     if (status != INSTALL_SUCCESS) {
                         ui_set_background(BACKGROUND_ICON_ERROR);
@@ -672,6 +679,21 @@
                     }
                 }
                 break;
+            case ITEM_APPLY_CACHE:
+                // Don't unmount cache at the end of this.
+                status = update_directory(CACHE_ROOT, NULL);
+                if (status >= 0) {
+                    if (status != INSTALL_SUCCESS) {
+                        ui_set_background(BACKGROUND_ICON_ERROR);
+                        ui_print("Installation aborted.\n");
+                    } else if (!ui_text_visible()) {
+                        return;  // reboot if logs aren't visible
+                    } else {
+                        ui_print("\nInstall from cache complete.\n");
+                    }
+                }
+                break;
+
         }
     }
 }
diff --git a/recovery_ui.h b/recovery_ui.h
index e56a24b..5f01770 100644
--- a/recovery_ui.h
+++ b/recovery_ui.h
@@ -76,6 +76,7 @@
 #define ITEM_APPLY_SDCARD    1  // historical synonym for ITEM_APPLY_EXT
 #define ITEM_WIPE_DATA       2
 #define ITEM_WIPE_CACHE      3
+#define ITEM_APPLY_CACHE     4
 
 // Header text to display above the main menu.
 extern char* MENU_HEADERS[];
diff --git a/tools/ota/Android.mk b/tools/ota/Android.mk
index 0bde7ee..142c3b2 100644
--- a/tools/ota/Android.mk
+++ b/tools/ota/Android.mk
@@ -14,8 +14,6 @@
 
 LOCAL_PATH := $(call my-dir)
 
-ifneq ($(TARGET_SIMULATOR),true)
-
 include $(CLEAR_VARS)
 LOCAL_FORCE_STATIC_EXECUTABLE := true
 LOCAL_MODULE := add-property-tag
@@ -33,5 +31,3 @@
 LOCAL_SRC_FILES := check-lost+found.c
 LOCAL_STATIC_LIBRARIES := libcutils libc
 include $(BUILD_EXECUTABLE)
-
-endif  # !TARGET_SIMULATOR
diff --git a/ui.c b/ui.c
index 0744da4..1736319 100644
--- a/ui.c
+++ b/ui.c
@@ -592,17 +592,18 @@
 
 // Return true if USB is connected.
 static int usb_connected() {
-    int fd = open("/sys/class/switch/usb_connected/state", O_RDONLY);
+    int fd = open("/sys/class/android_usb/android0/state", O_RDONLY);
     if (fd < 0) {
-        printf("failed to open /sys/class/switch/usb_connected/state: %s\n",
+        printf("failed to open /sys/class/android_usb/android0/state: %s\n",
                strerror(errno));
         return 0;
     }
 
     char buf;
-    int connected = (read(fd, &buf, 1) == 1) && (buf == '1');
+    /* USB is connected if android_usb state is CONNECTED or CONFIGURED */
+    int connected = (read(fd, &buf, 1) == 1) && (buf == 'C');
     if (close(fd) < 0) {
-        printf("failed to close /sys/class/switch/usb_connected/state: %s\n",
+        printf("failed to close /sys/class/android_usb/android0/state: %s\n",
                strerror(errno));
     }
     return connected;