Merge "libaaudio: changed name from liboboe"
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index e7f1a07..a4a0b52 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -1303,6 +1303,36 @@
     return num;
 }
 
+static std::string fb_fix_numeric_var(std::string var) {
+    // Some bootloaders (angler, for example), send spurious leading whitespace.
+    var = android::base::Trim(var);
+    // Some bootloaders (hammerhead, for example) use implicit hex.
+    // This code used to use strtol with base 16.
+    if (!android::base::StartsWith(var, "0x")) var = "0x" + var;
+    return var;
+}
+
+static unsigned fb_get_flash_block_size(Transport* transport, std::string name) {
+    std::string sizeString;
+    if (!fb_getvar(transport, name.c_str(), &sizeString)) {
+        /* This device does not report flash block sizes, so return 0 */
+        return 0;
+    }
+    sizeString = fb_fix_numeric_var(sizeString);
+
+    unsigned size;
+    if (!android::base::ParseUint(sizeString, &size)) {
+        fprintf(stderr, "Couldn't parse %s '%s'.\n", name.c_str(), sizeString.c_str());
+        return 0;
+    }
+    if (size < 4096 || (size & (size - 1)) != 0) {
+        fprintf(stderr, "Invalid %s %u: must be a power of 2 and at least 4096.\n",
+                name.c_str(), size);
+        return 0;
+    }
+    return size;
+}
+
 static void fb_perform_format(Transport* transport,
                               const char* partition, int skip_if_not_supported,
                               const char* type_override, const char* size_override,
@@ -1345,11 +1375,7 @@
         }
         partition_size = size_override;
     }
-    // Some bootloaders (angler, for example), send spurious leading whitespace.
-    partition_size = android::base::Trim(partition_size);
-    // Some bootloaders (hammerhead, for example) use implicit hex.
-    // This code used to use strtol with base 16.
-    if (!android::base::StartsWith(partition_size, "0x")) partition_size = "0x" + partition_size;
+    partition_size = fb_fix_numeric_var(partition_size);
 
     gen = fs_get_generator(partition_type);
     if (!gen) {
@@ -1370,7 +1396,12 @@
     }
 
     fd = fileno(tmpfile());
-    if (fs_generator_generate(gen, fd, size, initial_dir)) {
+
+    unsigned eraseBlkSize, logicalBlkSize;
+    eraseBlkSize = fb_get_flash_block_size(transport, "erase-block-size");
+    logicalBlkSize = fb_get_flash_block_size(transport, "logical-block-size");
+
+    if (fs_generator_generate(gen, fd, size, initial_dir, eraseBlkSize, logicalBlkSize)) {
         fprintf(stderr, "Cannot generate image: %s\n", strerror(errno));
         close(fd);
         return;
diff --git a/fastboot/fs.cpp b/fastboot/fs.cpp
index 9b73165..5d9ccfe 100644
--- a/fastboot/fs.cpp
+++ b/fastboot/fs.cpp
@@ -14,18 +14,21 @@
 #include <ext4_utils/make_ext4fs.h>
 #include <sparse/sparse.h>
 
-static int generate_ext4_image(int fd, long long partSize, const std::string& initial_dir)
+static int generate_ext4_image(int fd, long long partSize, const std::string& initial_dir,
+                                       unsigned eraseBlkSize, unsigned logicalBlkSize)
 {
     if (initial_dir.empty()) {
-        make_ext4fs_sparse_fd(fd, partSize, NULL, NULL);
+        make_ext4fs_sparse_fd_align(fd, partSize, NULL, NULL, eraseBlkSize, logicalBlkSize);
     } else {
-        make_ext4fs_sparse_fd_directory(fd, partSize, NULL, NULL, initial_dir.c_str());
+        make_ext4fs_sparse_fd_directory_align(fd, partSize, NULL, NULL, initial_dir.c_str(),
+                                              eraseBlkSize, logicalBlkSize);
     }
     return 0;
 }
 
 #ifdef USE_F2FS
-static int generate_f2fs_image(int fd, long long partSize, const std::string& initial_dir)
+static int generate_f2fs_image(int fd, long long partSize, const std::string& initial_dir,
+                               unsigned /* unused */, unsigned /* unused */)
 {
     if (!initial_dir.empty()) {
         fprintf(stderr, "Unable to set initial directory on F2FS filesystem\n");
@@ -39,7 +42,8 @@
     const char* fs_type;  //must match what fastboot reports for partition type
 
     //returns 0 or error value
-    int (*generate)(int fd, long long partSize, const std::string& initial_dir);
+    int (*generate)(int fd, long long partSize, const std::string& initial_dir,
+                    unsigned eraseBlkSize, unsigned logicalBlkSize);
 
 } generators[] = {
     { "ext4", generate_ext4_image},
@@ -58,7 +62,7 @@
 }
 
 int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize,
-    const std::string& initial_dir)
+    const std::string& initial_dir, unsigned eraseBlkSize, unsigned logicalBlkSize)
 {
-    return gen->generate(tmpFileNo, partSize, initial_dir);
+    return gen->generate(tmpFileNo, partSize, initial_dir, eraseBlkSize, logicalBlkSize);
 }
diff --git a/fastboot/fs.h b/fastboot/fs.h
index 0a68507..0a5f5a4 100644
--- a/fastboot/fs.h
+++ b/fastboot/fs.h
@@ -8,6 +8,6 @@
 
 const struct fs_generator* fs_get_generator(const std::string& fs_type);
 int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize,
-    const std::string& initial_dir);
+    const std::string& initial_dir, unsigned eraseBlkSize = 0, unsigned logicalBlkSize = 0);
 
 #endif
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp
index 70140d8..dd08271 100644
--- a/fs_mgr/fs_mgr_avb.cpp
+++ b/fs_mgr/fs_mgr_avb.cpp
@@ -215,8 +215,8 @@
 
     // Reads digest.
     if (digest.size() != expected_digest_size) {
-        LERROR << "Unexpected digest size: " << digest.size() << " (expected: "
-               << expected_digest_size << ")";
+        LERROR << "Unexpected digest size: " << digest.size()
+               << " (expected: " << expected_digest_size << ")";
         return false;
     }
 
@@ -482,22 +482,6 @@
     return true;
 }
 
-static inline bool polling_vbmeta_blk_device(struct fstab *fstab)
-{
-    // It needs the block device symlink: fstab_rec->blk_device to read
-    // /vbmeta partition. However, the symlink created by ueventd might
-    // not be ready at this point. Use test_access() to poll it before
-    // trying to read the partition.
-    struct fstab_rec *fstab_entry =
-        fs_mgr_get_entry_for_mount_point(fstab, "/vbmeta");
-
-    // Makes sure /vbmeta block device is ready to access.
-    if (fs_mgr_test_access(fstab_entry->blk_device) < 0) {
-        return false;
-    }
-    return true;
-}
-
 static bool init_is_avb_used()
 {
     // When AVB is used, boot loader should set androidboot.vbmeta.{hash_alg,
@@ -529,11 +513,6 @@
 {
     FS_MGR_CHECK(fstab != nullptr);
 
-    if (!polling_vbmeta_blk_device(fstab)) {
-        LERROR << "Failed to find block device of /vbmeta";
-        return FS_MGR_SETUP_AVB_FAIL;
-    }
-
     // Gets the expected hash value of vbmeta images from
     // kernel cmdline.
     if (!load_vbmeta_prop(&fs_mgr_vbmeta_prop)) {
diff --git a/fs_mgr/fs_mgr_avb_ops.cpp b/fs_mgr/fs_mgr_avb_ops.cpp
index 7683166..f96f124 100644
--- a/fs_mgr/fs_mgr_avb_ops.cpp
+++ b/fs_mgr/fs_mgr_avb_ops.cpp
@@ -66,7 +66,7 @@
         fs_mgr_get_entry_for_mount_point(fs_mgr_fstab, "/misc");
 
     if (fstab_entry == nullptr) {
-        LERROR << "Partition (" << partition << ") not found in fstab";
+        LERROR << "/misc mount point not found in fstab";
         return AVB_IO_RESULT_ERROR_IO;
     }
 
@@ -79,6 +79,13 @@
         path = by_name_prefix + partition_name;
     }
 
+    // Ensures the device path (a symlink created by init) is ready to
+    // access. fs_mgr_test_access() will test a few iterations if the
+    // path doesn't exist yet.
+    if (fs_mgr_test_access(path.c_str()) < 0) {
+        return AVB_IO_RESULT_ERROR_IO;
+    }
+
     android::base::unique_fd fd(
         TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
 
diff --git a/init/.clang-format b/init/.clang-format
new file mode 100644
index 0000000..48d423f
--- /dev/null
+++ b/init/.clang-format
@@ -0,0 +1,14 @@
+---
+Language:        Cpp
+BasedOnStyle:  Google
+BinPackArguments: true
+BinPackParameters: true
+ColumnLimit:     100
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+IndentWidth:     4
+Standard:        Auto
+TabWidth:        8
+UseTab:          Never
+DerivePointerAlignment: false
+PointerAlignment: Left
+...
diff --git a/init/Android.mk b/init/Android.mk
index 9e61fb2..a10a714 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -134,3 +134,8 @@
 LOCAL_CLANG := true
 LOCAL_CPPFLAGS := -Wall -Wextra -Werror
 include $(BUILD_NATIVE_TEST)
+
+
+# Include targets in subdirs.
+# =========================================================
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/init/test_service/Android.mk b/init/test_service/Android.mk
new file mode 100644
index 0000000..30c9e9d
--- /dev/null
+++ b/init/test_service/Android.mk
@@ -0,0 +1,27 @@
+# Copyright (C) 2016 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.
+
+LOCAL_PATH := $(call my-dir)
+
+# Sample service for testing.
+# =========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := test_service
+LOCAL_SRC_FILES := test_service.cpp
+
+LOCAL_SHARED_LIBRARIES += libbase
+
+LOCAL_INIT_RC := test_service.rc
+
+include $(BUILD_EXECUTABLE)
diff --git a/init/test_service/README.md b/init/test_service/README.md
new file mode 100644
index 0000000..6773235
--- /dev/null
+++ b/init/test_service/README.md
@@ -0,0 +1,43 @@
+# Sample service for testing
+This is a sample service that can be used for testing init.
+
+## Design
+The service includes a `.rc` file that allows starting it from init.
+
+    service test_service /system/bin/test_service CapAmb 0000000000003000
+        class main
+        user system
+        group system
+        capabilities NET_ADMIN NET_RAW
+        disabled
+        oneshot
+
+The service accepts any even number of arguments on the command line
+(i.e. any number of pairs of arguments.)
+It will attempt to find the first element of each pair of arguments in
+`/proc/self/status`, and attempt to exactly match the second element of the pair
+to the relevant line of `proc/self/status`.
+
+### Example
+In the above case, the service will look for lines containing `CapAmb`:
+
+    cat /proc/self/status
+    ...
+    CapAmb:	0000000000003000
+
+And then attempt to exactly match the token after `:`, `0000000000003000`,
+with the command-line argument.
+If they match, the service exits successfully. If not, the service will exit
+with an error.
+
+## Usage
+	mmma -j <jobs> system/core/init/testservice
+	adb root
+	adb remount
+	adb sync
+	adb reboot
+	adb root
+	adb shell start test_service
+	adb logcat -b all -d | grep test_service
+
+Look for an exit status of 0.
diff --git a/init/test_service/test_service.cpp b/init/test_service/test_service.cpp
new file mode 100644
index 0000000..e7206f8
--- /dev/null
+++ b/init/test_service/test_service.cpp
@@ -0,0 +1,78 @@
+// Copyright (C) 2016 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.
+
+#include <unistd.h>
+
+#include <map>
+#include <sstream>
+#include <string>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+
+void Usage(char* argv[]) {
+    printf("Usage: %s <status field> <value> [<status field> <value>]*\n", argv[0]);
+    printf("E.g.: $ %s Uid \"1000 1000 1000 1000\"\n", argv[0]);
+}
+
+int main(int argc, char* argv[]) {
+    if (argc < 3) {
+        Usage(argv);
+        LOG(FATAL) << "no status field requested";
+    }
+    if (argc % 2 == 0) {
+        // Since |argc| counts argv[0], if |argc| is odd, then the number of
+        // command-line arguments is even.
+        Usage(argv);
+        LOG(FATAL) << "need even number of command-line arguments";
+    }
+
+    std::string status;
+    bool res = android::base::ReadFileToString("/proc/self/status", &status, true);
+    if (!res) {
+        PLOG(FATAL) << "could not read /proc/self/status";
+    }
+
+    std::map<std::string, std::string> fields;
+    std::vector<std::string> lines = android::base::Split(status, "\n");
+    for (const auto& line : lines) {
+        std::vector<std::string> tokens = android::base::Split(line, ":");
+        if (tokens.size() >= 2) {
+            std::string field = tokens[0];
+            std::string value = android::base::Trim(tokens[1]);
+            if (field.length() > 0) {
+                fields[field] = value;
+            }
+        }
+    }
+
+    bool test_fails = false;
+    size_t uargc = static_cast<size_t>(argc);  // |argc| >= 3.
+    for (size_t i = 1; i < static_cast<size_t>(argc); i = i + 2) {
+        std::string expected_value = argv[i + 1];
+        auto f = fields.find(argv[i]);
+        if (f != fields.end()) {
+            if (f->second != expected_value) {
+                LOG(ERROR) << "field '" << argv[i] << "' expected '" << expected_value
+                           << "', actual '" << f->second << "'";
+                test_fails = true;
+            }
+        } else {
+            LOG(WARNING) << "could not find field '" << argv[i] << "'";
+        }
+    }
+
+    return test_fails ? 1 : 0;
+}
diff --git a/init/test_service/test_service.rc b/init/test_service/test_service.rc
new file mode 100644
index 0000000..91e1a0f
--- /dev/null
+++ b/init/test_service/test_service.rc
@@ -0,0 +1,7 @@
+service test_service /system/bin/test_service CapAmb 0000000000003000
+    class main
+    user system
+    group system
+    capabilities NET_ADMIN NET_RAW
+    disabled
+    oneshot
diff --git a/libappfuse/tests/FuseBufferTest.cc b/libappfuse/tests/FuseBufferTest.cc
index db35d33..1a1abd5 100644
--- a/libappfuse/tests/FuseBufferTest.cc
+++ b/libappfuse/tests/FuseBufferTest.cc
@@ -31,7 +31,7 @@
 constexpr char kTempFile[] = "/data/local/tmp/appfuse_test_dump";
 
 void OpenTempFile(android::base::unique_fd* fd) {
-  fd->reset(open(kTempFile, O_CREAT | O_RDWR));
+  fd->reset(open(kTempFile, O_CREAT | O_RDWR, 0600));
   ASSERT_NE(-1, *fd) << strerror(errno);
   unlink(kTempFile);
   ASSERT_NE(-1, *fd) << strerror(errno);
diff --git a/libcutils/include/cutils/properties.h b/libcutils/include/cutils/properties.h
index adf670b..b45f58f 100644
--- a/libcutils/include/cutils/properties.h
+++ b/libcutils/include/cutils/properties.h
@@ -43,7 +43,12 @@
 ** If the property read fails or returns an empty value, the default
 ** value is used (if nonnull).
 */
-int property_get(const char *key, char *value, const char *default_value);
+int property_get(const char *key, char *value, const char *default_value)
+/* Sometimes we use not-Bionic with this, so we need this check. */
+#if defined(__BIONIC_FORTIFY)
+        __overloadable __RENAME_CLANG(property_get)
+#endif
+        ;
 
 /* property_get_bool: returns the value of key coerced into a
 ** boolean. If the property is not set, then the default value is returned.
@@ -106,14 +111,40 @@
 /* property_set: returns 0 on success, < 0 on failure
 */
 int property_set(const char *key, const char *value);
-    
-int property_list(void (*propfn)(const char *key, const char *value, void *cookie), void *cookie);    
 
-#if defined(__BIONIC_FORTIFY) && !defined(__clang__)
+int property_list(void (*propfn)(const char *key, const char *value, void *cookie), void *cookie);
+
+#if defined(__BIONIC_FORTIFY)
+#define __property_get_err_str "property_get() called with too small of a buffer"
+
+#if defined(__clang__)
+
+/* Some projects use -Weverything; enable_if is clang-specific.
+** FIXME: This is marked used because we'll otherwise get complaints about an
+** unused static function. This is more robust than marking it unused, since
+** -Wused-but-marked-unused is a thing that will complain if this function is
+** actually used, thus making FORTIFY noisier when an error happens. It's going
+** to go away anyway during our FORTIFY cleanup.
+**/
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wgcc-compat"
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+int property_get(const char *key, char *value, const char *default_value)
+        __overloadable
+        __enable_if(__bos(value) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
+                    __bos(value) < PROPERTY_VALUE_MAX, __property_get_err_str)
+        __errorattr(__property_get_err_str)
+        __attribute__((used));
+#pragma clang diagnostic pop
+
+/* No object size? No FORTIFY.
+*/
+
+#else /* defined(__clang__) */
 
 extern int __property_get_real(const char *, char *, const char *)
     __asm__(__USER_LABEL_PREFIX__ "property_get");
-__errordecl(__property_get_too_small_error, "property_get() called with too small of a buffer");
+__errordecl(__property_get_too_small_error, __property_get_err_str);
 
 __BIONIC_FORTIFY_INLINE
 int property_get(const char *key, char *value, const char *default_value) {
@@ -124,7 +155,10 @@
     return __property_get_real(key, value, default_value);
 }
 
-#endif
+#endif /* defined(__clang__) */
+
+#undef __property_get_err_str
+#endif /* defined(__BIONIC_FORTIFY) */
 
 #ifdef __cplusplus
 }
diff --git a/liblog/logd_reader.c b/liblog/logd_reader.c
index ccc7da8..9411f36 100644
--- a/liblog/logd_reader.c
+++ b/liblog/logd_reader.c
@@ -91,7 +91,7 @@
 
 static int logdAvailable(log_id_t logId)
 {
-    if (logId > LOG_ID_KERNEL) {
+    if (logId >= LOG_ID_MAX || logId == LOG_ID_KERNEL) {
         return -EINVAL;
     }
     if (logId == LOG_ID_SECURITY) {
diff --git a/tzdatacheck/tzdatacheck.cpp b/tzdatacheck/tzdatacheck.cpp
index fb5c84b..769f0f5 100644
--- a/tzdatacheck/tzdatacheck.cpp
+++ b/tzdatacheck/tzdatacheck.cpp
@@ -30,26 +30,48 @@
 
 #include "android-base/logging.h"
 
-static const char* BUNDLE_VERSION_FILENAME = "/bundle_version";
-// bundle_version is an ASCII file consisting of 17 bytes in the form: AAA.BBB|CCCCC|DDD
-// AAA.BBB is the major/minor version of the bundle format (e.g. 001.001),
+// The name of the file containing the distro version information.
+// See also libcore.tzdata.update2.TimeZoneDistro / libcore.tzdata.update2.DistroVersion.
+static const char* DISTRO_VERSION_FILENAME = "/distro_version";
+
+// distro_version is an ASCII file consisting of 17 bytes in the form: AAA.BBB|CCCCC|DDD
+// AAA.BBB is the major/minor version of the distro format (e.g. 001.001),
 // CCCCC is the rules version (e.g. 2016g)
-// DDD is the android revision for this rules version to allow for bundle corrections (e.g. 001)
+// DDD is the android revision for this rules version to allow for distro corrections (e.g. 001)
 // We only need the first 13 to determine if it is suitable for the device.
-static const int BUNDLE_VERSION_LENGTH = 13;
-// The major version of the bundle format supported by this code as a null-terminated char[].
-static const char REQUIRED_BUNDLE_VERSION[] = "001";
-static const size_t REQUIRED_BUNDLE_VERSION_LEN = sizeof(REQUIRED_BUNDLE_VERSION) - 1; // exclude \0
+static const int DISTRO_VERSION_LENGTH = 13;
+
+// The major version of the distro format supported by this code as a null-terminated char[].
+// See also libcore.tzdata.update2.TimeZoneDistro / libcore.tzdata.update2.DistroVersion.
+static const char SUPPORTED_DISTRO_MAJOR_VERSION[] = "001";
+
+// The length of the distro format major version excluding the \0
+static const size_t SUPPORTED_DISTRO_MAJOR_VERSION_LEN = sizeof(SUPPORTED_DISTRO_MAJOR_VERSION) - 1;
+
+// The minor version of the distro format supported by this code as a null-terminated char[].
+// See also libcore.tzdata.update2.TimeZoneDistro / libcore.tzdata.update2.DistroVersion.
+static const char SUPPORTED_DISTRO_MINOR_VERSION[] = "001";
+
+// The length of the distro format minor version excluding the \0
+static const size_t SUPPORTED_DISTRO_MINOR_VERSION_LEN = sizeof(SUPPORTED_DISTRO_MINOR_VERSION) - 1;
+
+// The length of the distro format version. e.g. 001.001
+static const size_t SUPPORTED_DISTRO_VERSION_LEN =
+        SUPPORTED_DISTRO_MAJOR_VERSION_LEN + SUPPORTED_DISTRO_MINOR_VERSION_LEN + 1;
+
 // The length of the IANA rules version bytes. e.g. 2016a
 static const size_t RULES_VERSION_LEN = 5;
-// Bundle version bytes are: AAA.BBB|CCCCC - the rules version is CCCCC
-static const size_t BUNDLE_VERSION_RULES_IDX = 8;
 
+// Distro version bytes are: AAA.BBB|CCCCC - the rules version is CCCCC
+static const size_t DISTRO_VERSION_RULES_IDX = 8;
+
+// See also libcore.tzdata.update2.TimeZoneDistro.
 static const char* TZDATA_FILENAME = "/tzdata";
+
 // tzdata file header (as much as we need for the version):
 // byte[11] tzdata_version  -- e.g. "tzdata2012f"
 static const int TZ_HEADER_LENGTH = 11;
-// The major version of the bundle format supported by this code as a null-terminated char[].
+
 static const char TZ_DATA_HEADER_PREFIX[] = "tzdata";
 static const size_t TZ_DATA_HEADER_PREFIX_LEN = sizeof(TZ_DATA_HEADER_PREFIX) - 1; // exclude \0
 
@@ -57,7 +79,7 @@
 static void usage() {
     std::cerr << "Usage: tzdatacheck SYSTEM_TZ_DIR DATA_TZ_DIR\n"
             "\n"
-            "Checks whether any timezone update bundle in DATA_TZ_DIR is compatible with the\n"
+            "Checks whether any timezone update distro in DATA_TZ_DIR is compatible with the\n"
             "current Android release and better than or the same as base system timezone rules in\n"
             "SYSTEM_TZ_DIR. If the timezone rules in SYSTEM_TZ_DIR are a higher version than the\n"
             "one in DATA_TZ_DIR the DATA_TZ_DIR is renamed and then deleted.\n";
@@ -108,8 +130,8 @@
     return true;
 }
 
-static bool checkValidBundleVersion(const char* buffer) {
-    // See BUNDLE_VERSION_LENGTH comments above for a description of the format.
+static bool checkValidDistroVersion(const char* buffer) {
+    // See DISTRO_VERSION_LENGTH comments above for a description of the format.
     size_t i = 0;
     if (!checkDigits(buffer, 3, &i)) {
       return false;
@@ -246,13 +268,13 @@
 }
 
 /*
- * Deletes the timezone update bundle directory.
+ * Deletes the timezone update distro directory.
  */
-static void deleteUpdateBundleDir(std::string& bundleDirName) {
-    LOG(INFO) << "Removing: " << bundleDirName;
-    bool deleted = deleteDir(bundleDirName);
+static void deleteUpdateDistroDir(std::string& distroDirName) {
+    LOG(INFO) << "Removing: " << distroDirName;
+    bool deleted = deleteDir(distroDirName);
     if (!deleted) {
-        LOG(WARNING) << "Deletion of bundle dir " << bundleDirName << " was not successful";
+        LOG(WARNING) << "Deletion of distro dir " << distroDirName << " was not successful";
     }
 }
 
@@ -278,60 +300,83 @@
     const char* systemZoneInfoDir = argv[1];
     const char* dataZoneInfoDir = argv[2];
 
-    // Check the bundle directory exists. If it does not, exit quickly: nothing to do.
+    // Check the distro directory exists. If it does not, exit quickly: nothing to do.
     std::string dataCurrentDirName(dataZoneInfoDir);
     dataCurrentDirName += "/current";
     int dataCurrentDirStatus = checkPath(dataCurrentDirName);
     if (dataCurrentDirStatus == NONE) {
-        LOG(INFO) << "timezone bundle dir " << dataCurrentDirName
+        LOG(INFO) << "timezone distro dir " << dataCurrentDirName
                 << " does not exist. No action required.";
         return 0;
     }
-    // If the bundle directory path is not a directory or we can't stat() the path, exit with a
+    // If the distro directory path is not a directory or we can't stat() the path, exit with a
     // warning: either there's a problem accessing storage or the world is not as it should be;
     // nothing to do.
     if (dataCurrentDirStatus != IS_DIR) {
-        LOG(WARNING) << "Current bundle dir " << dataCurrentDirName
+        LOG(WARNING) << "Current distro dir " << dataCurrentDirName
                 << " could not be accessed or is not a directory. result=" << dataCurrentDirStatus;
         return 2;
     }
 
-    // Check the installed bundle version.
-    std::string bundleVersionFileName(dataCurrentDirName);
-    bundleVersionFileName += BUNDLE_VERSION_FILENAME;
-    std::vector<char> bundleVersion;
-    bundleVersion.reserve(BUNDLE_VERSION_LENGTH);
-    bool bundleVersionReadOk =
-            readBytes(bundleVersionFileName, bundleVersion.data(), BUNDLE_VERSION_LENGTH);
-    if (!bundleVersionReadOk) {
-        LOG(WARNING) << "bundle version file " << bundleVersionFileName
-                << " does not exist or is too short. Deleting bundle dir.";
+    // Check the installed distro version.
+    std::string distroVersionFileName(dataCurrentDirName);
+    distroVersionFileName += DISTRO_VERSION_FILENAME;
+    std::vector<char> distroVersion;
+    distroVersion.reserve(DISTRO_VERSION_LENGTH);
+    bool distroVersionReadOk =
+            readBytes(distroVersionFileName, distroVersion.data(), DISTRO_VERSION_LENGTH);
+    if (!distroVersionReadOk) {
+        LOG(WARNING) << "distro version file " << distroVersionFileName
+                << " does not exist or is too short. Deleting distro dir.";
         // Implies the contents of the data partition is corrupt in some way. Try to clean up.
         deleteConfigUpdaterMetadataDir(dataZoneInfoDir);
-        deleteUpdateBundleDir(dataCurrentDirName);
+        deleteUpdateDistroDir(dataCurrentDirName);
         return 3;
     }
 
-    if (!checkValidBundleVersion(bundleVersion.data())) {
-        LOG(WARNING) << "bundle version file " << bundleVersionFileName
-                << " is not valid. Deleting bundle dir.";
+    if (!checkValidDistroVersion(distroVersion.data())) {
+        LOG(WARNING) << "distro version file " << distroVersionFileName
+                << " is not valid. Deleting distro dir.";
         // Implies the contents of the data partition is corrupt in some way. Try to clean up.
         deleteConfigUpdaterMetadataDir(dataZoneInfoDir);
-        deleteUpdateBundleDir(dataCurrentDirName);
+        deleteUpdateDistroDir(dataCurrentDirName);
         return 4;
     }
 
-    // Check the first 3 bytes of the bundleVersionHeader: these are the major version (e.g. 001).
-    // It must match exactly to be ok. The minor version is currently ignored.
-    if (strncmp(&bundleVersion[0], REQUIRED_BUNDLE_VERSION, REQUIRED_BUNDLE_VERSION_LEN) != 0) {
-        LOG(INFO) << "bundle version file " << bundleVersionFileName
-                << " is not the required version " << REQUIRED_BUNDLE_VERSION
-                << ". Deleting bundle dir.";
-        // This shouldn't happen with 001, but it in future, this will imply there has been an OTA
-        // and the installed bundle is not compatible with the new version of Android. Remove the
-        // installed bundle.
+    std::string actualDistroVersion =
+            std::string(distroVersion.data(), SUPPORTED_DISTRO_VERSION_LEN);
+    // Check the first 3 bytes of the distro version: these are the major version (e.g. 001).
+    // It must match the one we support exactly to be ok.
+    if (strncmp(
+            &distroVersion[0],
+            SUPPORTED_DISTRO_MAJOR_VERSION,
+            SUPPORTED_DISTRO_MAJOR_VERSION_LEN) != 0) {
+
+        LOG(INFO) << "distro version file " << distroVersionFileName
+                << " major version is not the required version " << SUPPORTED_DISTRO_MAJOR_VERSION
+                << ", was \"" << actualDistroVersion << "\". Deleting distro dir.";
+        // This implies there has been an OTA and the installed distro is not compatible with the
+        // new version of Android. Remove the installed distro.
         deleteConfigUpdaterMetadataDir(dataZoneInfoDir);
-        deleteUpdateBundleDir(dataCurrentDirName);
+        deleteUpdateDistroDir(dataCurrentDirName);
+        return 5;
+    }
+
+    // Check the last 3 bytes of the distro version: these are the minor version (e.g. 001).
+    // If the version in the distro is < the minor version required by this device it cannot be
+    // used.
+    if (strncmp(
+            &distroVersion[4],
+            SUPPORTED_DISTRO_MINOR_VERSION,
+            SUPPORTED_DISTRO_MINOR_VERSION_LEN) < 0) {
+
+        LOG(INFO) << "distro version file " << distroVersionFileName
+                << " minor version is not the required version " << SUPPORTED_DISTRO_MINOR_VERSION
+                << ", was \"" << actualDistroVersion << "\". Deleting distro dir.";
+        // This implies there has been an OTA and the installed distro is not compatible with the
+        // new version of Android. Remove the installed distro.
+        deleteConfigUpdaterMetadataDir(dataZoneInfoDir);
+        deleteUpdateDistroDir(dataCurrentDirName);
         return 5;
     }
 
@@ -353,22 +398,22 @@
         return 7;
     }
 
-    // Compare the bundle rules version against the system rules version.
+    // Compare the distro rules version against the system rules version.
     if (strncmp(
             &systemTzDataHeader[TZ_DATA_HEADER_PREFIX_LEN],
-            &bundleVersion[BUNDLE_VERSION_RULES_IDX],
+            &distroVersion[DISTRO_VERSION_RULES_IDX],
             RULES_VERSION_LEN) <= 0) {
-        LOG(INFO) << "Found an installed bundle but it is valid. No action taken.";
+        LOG(INFO) << "Found an installed distro but it is valid. No action taken.";
         // Implies there is an installed update, but it is good.
         return 0;
     }
 
     // Implies there has been an OTA and the system version of the timezone rules is now newer
-    // than the version installed in /data. Remove the installed bundle.
-    LOG(INFO) << "timezone bundle in " << dataCurrentDirName << " is older than data in "
+    // than the version installed in /data. Remove the installed distro.
+    LOG(INFO) << "timezone distro in " << dataCurrentDirName << " is older than data in "
             << systemTzDataFileName << "; fixing...";
 
     deleteConfigUpdaterMetadataDir(dataZoneInfoDir);
-    deleteUpdateBundleDir(dataCurrentDirName);
+    deleteUpdateDistroDir(dataCurrentDirName);
     return 0;
 }