Merge "liblp: Add support for updateable partition groups."
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 6e143c1..e38e305 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -841,14 +841,19 @@
         return -1;
     }
 
-    std::string service = android::base::StringPrintf(
-        "sideload-host:%d:%d", static_cast<int>(sb.st_size), SIDELOAD_HOST_BLOCK_SIZE);
+    std::string service =
+            android::base::StringPrintf("sideload-host:%" PRId64 ":%d",
+                                        static_cast<int64_t>(sb.st_size), SIDELOAD_HOST_BLOCK_SIZE);
     std::string error;
     unique_fd device_fd(adb_connect(service, &error));
     if (device_fd < 0) {
-        // Try falling back to the older (<= K) sideload method. Maybe this
-        // is an older device that doesn't support sideload-host.
         fprintf(stderr, "adb: sideload connection failed: %s\n", error.c_str());
+
+        // If this is a small enough package, maybe this is an older device that doesn't
+        // support sideload-host. Try falling back to the older (<= K) sideload method.
+        if (sb.st_size > INT_MAX) {
+            return -1;
+        }
         fprintf(stderr, "adb: trying pre-KitKat sideload method...\n");
         return adb_sideload_legacy(filename, package_fd, static_cast<int>(sb.st_size));
     }
@@ -858,7 +863,7 @@
 
     char buf[SIDELOAD_HOST_BLOCK_SIZE];
 
-    size_t xfer = 0;
+    int64_t xfer = 0;
     int last_percent = -1;
     while (true) {
         if (!ReadFdExactly(device_fd, buf, 8)) {
@@ -874,20 +879,22 @@
             return 0;
         }
 
-        int block = strtol(buf, nullptr, 10);
-
-        size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
-        if (offset >= static_cast<size_t>(sb.st_size)) {
-            fprintf(stderr, "adb: failed to read block %d past end\n", block);
+        int64_t block = strtoll(buf, nullptr, 10);
+        int64_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
+        if (offset >= static_cast<int64_t>(sb.st_size)) {
+            fprintf(stderr,
+                    "adb: failed to read block %" PRId64 " at offset %" PRId64 ", past end %" PRId64
+                    "\n",
+                    block, offset, static_cast<int64_t>(sb.st_size));
             return -1;
         }
 
         size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
-        if ((offset + SIDELOAD_HOST_BLOCK_SIZE) > static_cast<size_t>(sb.st_size)) {
+        if ((offset + SIDELOAD_HOST_BLOCK_SIZE) > static_cast<int64_t>(sb.st_size)) {
             to_write = sb.st_size - offset;
         }
 
-        if (adb_lseek(package_fd, offset, SEEK_SET) != static_cast<int>(offset)) {
+        if (adb_lseek(package_fd, offset, SEEK_SET) != offset) {
             fprintf(stderr, "adb: failed to seek to package block: %s\n", strerror(errno));
             return -1;
         }
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index be0bdd0..b8d7e06 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -52,10 +52,11 @@
 #include <fcntl.h>
 #include <io.h>
 #include <process.h>
+#include <stdint.h>
 #include <sys/stat.h>
 #include <utime.h>
-#include <winsock2.h>
 #include <windows.h>
+#include <winsock2.h>
 #include <ws2tcpip.h>
 
 #include <memory>   // unique_ptr
@@ -92,7 +93,7 @@
 extern int adb_creat(const char* path, int mode);
 extern int adb_read(int fd, void* buf, int len);
 extern int adb_write(int fd, const void* buf, int len);
-extern int adb_lseek(int fd, int pos, int where);
+extern int64_t adb_lseek(int fd, int64_t pos, int where);
 extern int adb_shutdown(int fd, int direction = SHUT_RDWR);
 extern int adb_close(int fd);
 extern int adb_register_socket(SOCKET s);
@@ -315,25 +316,24 @@
 
 #else /* !_WIN32 a.k.a. Unix */
 
-#include <cutils/sockets.h>
 #include <fcntl.h>
-#include <poll.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-
-#include <pthread.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdarg.h>
 #include <netdb.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
+#include <poll.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdint.h>
 #include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
 #include <unistd.h>
 
 #include <string>
 
+#include <cutils/sockets.h>
+
 #define OS_PATH_SEPARATORS "/"
 #define OS_PATH_SEPARATOR '/'
 #define OS_PATH_SEPARATOR_STR "/"
@@ -443,12 +443,15 @@
 #undef   write
 #define  write  ___xxx_write
 
-static __inline__ int   adb_lseek(int  fd, int  pos, int  where)
-{
+static __inline__ int64_t adb_lseek(int fd, int64_t pos, int where) {
+#if defined(__APPLE__)
     return lseek(fd, pos, where);
+#else
+    return lseek64(fd, pos, where);
+#endif
 }
-#undef   lseek
-#define  lseek   ___xxx_lseek
+#undef lseek
+#define lseek ___xxx_lseek
 
 static __inline__  int    adb_unlink(const char*  path)
 {
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 026dd1c..8784757 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -52,12 +52,11 @@
 
 typedef const struct FHClassRec_* FHClass;
 typedef struct FHRec_* FH;
-typedef struct EventHookRec_* EventHook;
 
 typedef struct FHClassRec_ {
     void (*_fh_init)(FH);
     int (*_fh_close)(FH);
-    int (*_fh_lseek)(FH, int, int);
+    int64_t (*_fh_lseek)(FH, int64_t, int);
     int (*_fh_read)(FH, void*, int);
     int (*_fh_write)(FH, const void*, int);
     int (*_fh_writev)(FH, const adb_iovec*, int);
@@ -65,7 +64,7 @@
 
 static void _fh_file_init(FH);
 static int _fh_file_close(FH);
-static int _fh_file_lseek(FH, int, int);
+static int64_t _fh_file_lseek(FH, int64_t, int);
 static int _fh_file_read(FH, void*, int);
 static int _fh_file_write(FH, const void*, int);
 static int _fh_file_writev(FH, const adb_iovec*, int);
@@ -81,7 +80,7 @@
 
 static void _fh_socket_init(FH);
 static int _fh_socket_close(FH);
-static int _fh_socket_lseek(FH, int, int);
+static int64_t _fh_socket_lseek(FH, int64_t, int);
 static int _fh_socket_read(FH, void*, int);
 static int _fh_socket_write(FH, const void*, int);
 static int _fh_socket_writev(FH, const adb_iovec*, int);
@@ -318,10 +317,8 @@
     return wrote_bytes;
 }
 
-static int _fh_file_lseek(FH f, int pos, int origin) {
+static int64_t _fh_file_lseek(FH f, int64_t pos, int origin) {
     DWORD method;
-    DWORD result;
-
     switch (origin) {
         case SEEK_SET:
             method = FILE_BEGIN;
@@ -337,14 +334,13 @@
             return -1;
     }
 
-    result = SetFilePointer(f->fh_handle, pos, nullptr, method);
-    if (result == INVALID_SET_FILE_POINTER) {
+    LARGE_INTEGER li = {.QuadPart = pos};
+    if (!SetFilePointerEx(f->fh_handle, li, &li, method)) {
         errno = EIO;
         return -1;
-    } else {
-        f->eof = 0;
     }
-    return (int)result;
+    f->eof = 0;
+    return li.QuadPart;
 }
 
 /**************************************************************************/
@@ -491,14 +487,12 @@
     return f->clazz->_fh_writev(f, iov, iovcnt);
 }
 
-int adb_lseek(int fd, int pos, int where) {
+int64_t adb_lseek(int fd, int64_t pos, int where) {
     FH f = _fh_from_int(fd, __func__);
-
     if (!f) {
         errno = EBADF;
         return -1;
     }
-
     return f->clazz->_fh_lseek(f, pos, where);
 }
 
@@ -644,7 +638,7 @@
     return 0;
 }
 
-static int _fh_socket_lseek(FH f, int pos, int origin) {
+static int64_t _fh_socket_lseek(FH f, int64_t pos, int origin) {
     errno = EPIPE;
     return -1;
 }
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index d29ccf4..1598a5c 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -529,8 +529,18 @@
     errno = 0;
     ret = mount(source, target, rec->fs_type, mountflags, rec->fs_options);
     save_errno = errno;
-    PINFO << __FUNCTION__ << "(source=" << source << ",target=" << target
-          << ",type=" << rec->fs_type << ")=" << ret;
+    const char* target_missing = "";
+    const char* source_missing = "";
+    if (save_errno == ENOENT) {
+        if (access(target, F_OK)) {
+            target_missing = "(missing)";
+        } else if (access(source, F_OK)) {
+            source_missing = "(missing)";
+        }
+        errno = save_errno;
+    }
+    PINFO << __FUNCTION__ << "(source=" << source << source_missing << ",target=" << target
+          << target_missing << ",type=" << rec->fs_type << ")=" << ret;
     if ((ret == 0) && (mountflags & MS_RDONLY) != 0) {
         fs_mgr_set_blk_ro(source);
     }
@@ -840,7 +850,7 @@
 }
 
 bool fs_mgr_update_checkpoint_partition(struct fstab_rec* rec) {
-    if (fs_mgr_is_checkpoint(rec)) {
+    if (fs_mgr_is_checkpoint_fs(rec)) {
         if (!strcmp(rec->fs_type, "f2fs")) {
             std::string opts(rec->fs_options);
 
@@ -850,9 +860,42 @@
         } else {
             LERROR << rec->fs_type << " does not implement checkpoints.";
         }
-    } else if (rec->fs_mgr_flags & MF_CHECKPOINT_BLK) {
-        LERROR << "Block based checkpoint not implemented.";
-        return false;
+    } else if (fs_mgr_is_checkpoint_blk(rec)) {
+        call_vdc({"checkpoint", "restoreCheckpoint", rec->blk_device});
+
+        android::base::unique_fd fd(
+                TEMP_FAILURE_RETRY(open(rec->blk_device, O_RDONLY | O_CLOEXEC)));
+        if (!fd) {
+            PERROR << "Cannot open device " << rec->blk_device;
+            return false;
+        }
+
+        uint64_t size = get_block_device_size(fd) / 512;
+        if (!size) {
+            PERROR << "Cannot get device size";
+            return false;
+        }
+
+        android::dm::DmTable table;
+        if (!table.AddTarget(
+                    std::make_unique<android::dm::DmTargetBow>(0, size, rec->blk_device))) {
+            LERROR << "Failed to add Bow target";
+            return false;
+        }
+
+        DeviceMapper& dm = DeviceMapper::Instance();
+        if (!dm.CreateDevice("bow", table)) {
+            PERROR << "Failed to create bow device";
+            return false;
+        }
+
+        std::string name;
+        if (!dm.GetDmDevicePathByName("bow", &name)) {
+            PERROR << "Failed to get bow device name";
+            return false;
+        }
+
+        rec->blk_device = strdup(name.c_str());
     }
     return true;
 }
diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h
index aab89e5..175b0f0 100644
--- a/fs_mgr/libdm/include/libdm/dm_target.h
+++ b/fs_mgr/libdm/include/libdm/dm_target.h
@@ -156,6 +156,20 @@
     std::string target_string_;
 };
 
+// dm-bow is the backup on write target that can provide checkpoint capability
+// for file systems that do not support checkpoints natively
+class DmTargetBow final : public DmTarget {
+  public:
+    DmTargetBow(uint64_t start, uint64_t length, const std::string& target_string)
+        : DmTarget(start, length), target_string_(target_string) {}
+
+    std::string name() const override { return "bow"; }
+    std::string GetParameterString() const override { return target_string_; }
+
+  private:
+    std::string target_string_;
+};
+
 }  // namespace dm
 }  // namespace android
 
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index 879ba21..f78093b 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -42,6 +42,7 @@
 using DmTargetLinear = ::android::dm::DmTargetLinear;
 using DmTargetZero = ::android::dm::DmTargetZero;
 using DmTargetAndroidVerity = ::android::dm::DmTargetAndroidVerity;
+using DmTargetBow = ::android::dm::DmTargetBow;
 using DmTargetTypeInfo = ::android::dm::DmTargetTypeInfo;
 using DmBlockDevice = ::android::dm::DeviceMapper::DmBlockDevice;
 
@@ -108,6 +109,13 @@
             std::string block_device = NextArg();
             return std::make_unique<DmTargetAndroidVerity>(start_sector, num_sectors, keyid,
                                                            block_device);
+        } else if (target_type == "bow") {
+            if (!HasArgs(1)) {
+                std::cerr << "Expected \"bow\" <block_device>" << std::endl;
+                return nullptr;
+            }
+            std::string block_device = NextArg();
+            return std::make_unique<DmTargetBow>(start_sector, num_sectors, block_device);
         } else {
             std::cerr << "Unrecognized target type: " << target_type << std::endl;
             return nullptr;
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 71a8e0d..6f97d19 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -68,6 +68,7 @@
     bool CreateLogicalPartitions();
     bool MountPartition(fstab_rec* fstab_rec);
     bool MountPartitions();
+    bool IsDmLinearEnabled();
     bool GetBackingDmLinearDevices();
 
     virtual ListenerAction UeventCallback(const Uevent& uevent);
@@ -134,22 +135,6 @@
     return !ForceNormalBoot() && access("/system/bin/recovery", F_OK) == 0;
 }
 
-static inline bool IsDmLinearEnabled() {
-    static bool checked = false;
-    static bool enabled = false;
-    if (checked) {
-        return enabled;
-    }
-    import_kernel_cmdline(false,
-                          [](const std::string& key, const std::string& value, bool in_qemu) {
-                              if (key == "androidboot.logical_partitions" && value == "1") {
-                                  enabled = true;
-                              }
-                          });
-    checked = true;
-    return enabled;
-}
-
 // Class Definitions
 // -----------------
 FirstStageMount::FirstStageMount()
@@ -198,6 +183,13 @@
     return GetBackingDmLinearDevices() && GetDmVerityDevices() && InitRequiredDevices();
 }
 
+bool FirstStageMount::IsDmLinearEnabled() {
+    for (auto fstab_rec : mount_fstab_recs_) {
+        if (fs_mgr_is_logical(fstab_rec)) return true;
+    }
+    return false;
+}
+
 bool FirstStageMount::GetBackingDmLinearDevices() {
     // Add any additional devices required for dm-linear mappings.
     if (!IsDmLinearEnabled()) {
diff --git a/liblog/include/log/log_main.h b/liblog/include/log/log_main.h
index e7b1728..53653de 100644
--- a/liblog/include/log/log_main.h
+++ b/liblog/include/log/log_main.h
@@ -56,15 +56,24 @@
 /*
  * Use __VA_ARGS__ if running a static analyzer,
  * to avoid warnings of unused variables in __VA_ARGS__.
- * __FAKE_USE_VA_ARGS is undefined at link time,
- * so don't link with __clang_analyzer__ defined.
+ * Use contexpr function in C++ mode, so these macros can be used
+ * in other constexpr functions without warning.
  */
 #ifdef __clang_analyzer__
-extern void __fake_use_va_args(int, ...);
-#define __FAKE_USE_VA_ARGS(...) __fake_use_va_args(0, ##__VA_ARGS__)
+#ifdef __cplusplus
+extern "C++" {
+template <typename... Ts>
+constexpr int __fake_use_va_args(Ts...) {
+  return 0;
+}
+}
+#else
+extern int __fake_use_va_args(int, ...);
+#endif /* __cplusplus */
+#define __FAKE_USE_VA_ARGS(...) ((void)__fake_use_va_args(0, ##__VA_ARGS__))
 #else
 #define __FAKE_USE_VA_ARGS(...) ((void)(0))
-#endif
+#endif /* __clang_analyzer__ */
 
 #ifndef __predict_false
 #define __predict_false(exp) __builtin_expect((exp) != 0, 0)
diff --git a/rootdir/init.rc b/rootdir/init.rc
index f39ea7c..2a70a4a 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -400,6 +400,7 @@
 
     # Make sure we have the device encryption key.
     start vold
+    exec - system system -- /system/bin/vdc checkpoint prepareDriveForCheckpoint /data
     installkey /data
 
     # Start bootcharting as soon as possible after the data partition is