Merge "Stop using kernel logger"
diff --git a/apexd/Android.bp b/apexd/Android.bp
index 92ad092..6f21138 100644
--- a/apexd/Android.bp
+++ b/apexd/Android.bp
@@ -671,24 +671,6 @@
   test_config: "ApexServiceTestCases.xml",
 }
 
-cc_test {
-  name: "flattened_apex_test",
-  defaults: [
-    "apex_flags_defaults",
-    "libapex-deps",
-    "libapexd-deps"
-  ],
-  srcs: ["flattened_apex_test.cpp"],
-  host_supported: false,
-  compile_multilib: "first",
-  static_libs: [
-    "libapex",
-    "libapexd",
-  ],
-  test_suites: ["device-tests"],
-  test_config: "flattened_apex_test_config.xml",
-}
-
 xsd_config {
   name: "apex-info-list",
   srcs: ["ApexInfoList.xsd"],
diff --git a/apexd/apex_database.cpp b/apexd/apex_database.cpp
index f174599..c31df02 100644
--- a/apexd/apex_database.cpp
+++ b/apexd/apex_database.cpp
@@ -247,8 +247,7 @@
 // - /dev/block/loopX : loop device
 // - /dev/block/dm-X : dm-verity
 
-// In case of loop device, it is from a non-flattened
-// APEX file. This original APEX file can be tracked
+// In case of loop device, the original APEX file can be tracked
 // by /sys/block/loopX/loop/backing_file.
 
 // In case of dm-verity, it is mapped to a loop device.
diff --git a/apexd/apex_file_repository.h b/apexd/apex_file_repository.h
index bfddccf..18ea84c 100644
--- a/apexd/apex_file_repository.h
+++ b/apexd/apex_file_repository.h
@@ -214,8 +214,5 @@
   std::unordered_map<std::string, BlockApexOverride> block_apex_overrides_;
 };
 
-std::string GetApexSelectFilenameFromProp(
-    const std::vector<std::string>& prefixes, const std::string& apex_name);
-
 }  // namespace apex
 }  // namespace android
diff --git a/apexd/apexd.cpp b/apexd/apexd.cpp
index 58ff93e..993acb7 100644
--- a/apexd/apexd.cpp
+++ b/apexd/apexd.cpp
@@ -1575,11 +1575,6 @@
 }
 
 Result<void> EmitApexInfoList(bool is_bootstrap) {
-  // on a non-updatable device, we don't have APEX database to emit
-  if (!android::sysprop::ApexProperties::updatable().value_or(false)) {
-    return {};
-  }
-
   // Apexd runs both in "bootstrap" and "default" mount namespace.
   // To expose /apex/apex-info-list.xml separately in each mount namespaces,
   // we write /apex/.<namespace>-apex-info-list .xml file first and then
@@ -3725,129 +3720,6 @@
   return 0;
 }
 
-int ActivateFlattenedApex(const std::vector<std::string>& multi_apex_prefixes) {
-  LOG(INFO) << "ActivateFlattenedApex";
-
-  std::vector<com::android::apex::ApexInfo> apex_infos;
-  std::unordered_map<std::string, std::string> apex_names;
-
-  for (const std::string& dir : gConfig->apex_built_in_dirs) {
-    LOG(INFO) << "Scanning " << dir;
-    auto dir_content = ReadDir(dir, [](const auto& entry) {
-      std::error_code ec;
-      return entry.is_directory(ec);
-    });
-
-    if (!dir_content.ok()) {
-      LOG(ERROR) << "Failed to scan " << dir << " : " << dir_content.error();
-      continue;
-    }
-
-    // Sort to make sure that /apex/apex-info-list.xml generation doesn't depend
-    // on the unstable directory scan.
-    std::vector<std::string> entries = std::move(*dir_content);
-    std::sort(entries.begin(), entries.end());
-
-    for (const std::string& apex_dir : entries) {
-      std::string manifest_file = apex_dir + "/" + kManifestFilenamePb;
-      if (access(manifest_file.c_str(), F_OK) != 0) {
-        PLOG(ERROR) << "Failed to access " << manifest_file;
-        continue;
-      }
-
-      auto manifest = ReadManifest(manifest_file);
-      if (!manifest.ok()) {
-        LOG(ERROR) << "Failed to read apex manifest from " << manifest_file
-                   << " : " << manifest.error();
-        continue;
-      }
-
-      // Support for multi-install-apex with flattened apexes works with "ro."
-      // property but not with "persist." property because "persist." properties
-      // are not loaded yet.
-      auto selected =
-          GetApexSelectFilenameFromProp(multi_apex_prefixes, manifest->name());
-      if (!selected.empty()) {
-        if (selected != android::base::Basename(apex_dir)) {
-          LOG(INFO) << "Skipping APEX at " << apex_dir << " because "
-                    << selected << " is selected for " << manifest->name();
-          continue;
-        }
-        LOG(INFO) << "Selecting APEX at " << apex_dir << " for "
-                  << manifest->name();
-      }
-
-      if (auto it = apex_names.find(manifest->name()); it != apex_names.end()) {
-        LOG(ERROR) << "Failed to activate apex from " << apex_dir
-                   << " : duplicate of " << manifest->name() << " found in "
-                   << it->second;
-        return 1;
-      }
-
-      std::string mount_point = std::string(kApexRoot) + "/" + manifest->name();
-      if (mkdir(mount_point.c_str(), 0755) != 0) {
-        PLOG(ERROR) << "Failed to mkdir " << mount_point;
-        continue;
-      }
-
-      LOG(INFO) << "Bind mounting " << apex_dir << " onto " << mount_point;
-      if (mount(apex_dir.c_str(), mount_point.c_str(), nullptr, MS_BIND,
-                nullptr) != 0) {
-        PLOG(ERROR) << "Failed to bind mount " << apex_dir << " to "
-                    << mount_point;
-        continue;
-      }
-
-      // b/179211712 the stored path should be the realpath, otherwise the path
-      // we get by scanning the directory would be different from the path we
-      // get by reading /proc/mounts, if the apex file is on a symlink dir.
-      std::string realpath;
-      if (!android::base::Realpath(apex_dir, &realpath)) {
-        PLOG(ERROR) << "can't get realpath of " << apex_dir;
-        continue;
-      }
-
-      apex_infos.emplace_back(manifest->name(), /* modulePath= */ realpath,
-                              /* preinstalledModulePath= */ realpath,
-                              /* versionCode= */ manifest->version(),
-                              /* versionName= */ manifest->versionname(),
-                              /* isFactory= */ true, /* isActive= */ true,
-                              /* lastUpdateMillis= */ 0,
-                              /* provideSharedApexLibs= */ false);
-      apex_names.emplace(manifest->name(), apex_dir);
-    }
-  }
-
-  std::string file_name = StringPrintf("%s/%s", kApexRoot, kApexInfoList);
-  unique_fd fd(TEMP_FAILURE_RETRY(
-      open(file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644)));
-  if (fd.get() == -1) {
-    PLOG(ERROR) << "Can't open " << file_name;
-    return 1;
-  }
-
-  std::ostringstream xml;
-  com::android::apex::ApexInfoList apex_info_list(apex_infos);
-  com::android::apex::write(xml, apex_info_list);
-  if (!android::base::WriteStringToFd(xml.str(), fd)) {
-    PLOG(ERROR) << "Can't write to " << file_name;
-    return 1;
-  }
-  fd.reset();
-
-  if (auto status = RestoreconPath(file_name); !status.ok()) {
-    LOG(ERROR) << "Failed to restorecon " << file_name << " : "
-               << status.error();
-    return 1;
-  }
-
-  return 0;
-}
-
-int ActivateFlattenedApex() {
-  return ActivateFlattenedApex(kMultiApexSelectPrefix);
-}
-
 android::apex::MountedApexDatabase& GetApexDatabaseForTesting() {
   return gMountedApexes;
 }
diff --git a/apexd/apexd.h b/apexd/apexd.h
index 09682e0..00810d6 100644
--- a/apexd/apexd.h
+++ b/apexd/apexd.h
@@ -215,10 +215,6 @@
 // TODO(b/172911822): support compressed apexes.
 int OnOtaChrootBootstrap();
 
-// Activates flattened apexes
-int ActivateFlattenedApex();
-int ActivateFlattenedApex(const std::vector<std::string>& multi_apex_prefixes);
-
 android::apex::MountedApexDatabase& GetApexDatabaseForTesting();
 
 // Performs a non-staged install of an APEX specified by |package_path|.
diff --git a/apexd/apexd_main.cpp b/apexd/apexd_main.cpp
index 34a25eb..994872a 100644
--- a/apexd/apexd_main.cpp
+++ b/apexd/apexd_main.cpp
@@ -16,7 +16,6 @@
 
 #define LOG_TAG "apexd"
 
-#include <ApexProperties.sysprop.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <selinux/android.h>
@@ -131,32 +130,6 @@
   bool booting = lifecycle.IsBooting();
 
   const bool has_subcommand = argv[1] != nullptr;
-  if (!android::sysprop::ApexProperties::updatable().value_or(false)) {
-    if (!has_subcommand) {
-      if (!booting) {
-        // We've finished booting, but for some reason somebody tried to start
-        // apexd. Simply exit.
-        return 0;
-      }
-
-      LOG(INFO) << "This device does not support updatable APEX. Exiting";
-      // Mark apexd as activated so that init can proceed.
-      android::apex::OnAllPackagesActivated(/*is_bootstrap=*/false);
-    } else if (strcmp("--snapshotde", argv[1]) == 0) {
-      LOG(INFO) << "This device does not support updatable APEX. Exiting";
-      // mark apexd as ready
-      android::apex::OnAllPackagesReady();
-    } else if (strcmp("--otachroot-bootstrap", argv[1]) == 0) {
-      SetDefaultTag("apexd-otachroot");
-      LOG(INFO) << "OTA chroot bootstrap subcommand detected";
-      return android::apex::ActivateFlattenedApex();
-    } else if (strcmp("--bootstrap", argv[1]) == 0) {
-      LOG(INFO) << "Bootstrap subcommand detected";
-      return android::apex::ActivateFlattenedApex();
-    }
-    return 0;
-  }
-
   if (has_subcommand) {
     return HandleSubcommand(argv);
   }
diff --git a/apexd/apexd_test.cpp b/apexd/apexd_test.cpp
index 0b478b0..a7e5f83 100644
--- a/apexd/apexd_test.cpp
+++ b/apexd/apexd_test.cpp
@@ -3049,150 +3049,6 @@
                                    ApexInfoXmlEq(apex_info_xml_2)));
 }
 
-void PrepareFlattenedApex(const std::string& apex_dir,
-                          const std::string& apex_name, int version) {
-  ASSERT_EQ(mkdir(apex_dir.c_str(), 0755), 0);
-
-  ::apex::proto::ApexManifest manifest;
-  manifest.set_name(apex_name);
-  manifest.set_version(version);
-  manifest.set_versionname(std::to_string(version));
-
-  std::string out;
-  manifest.SerializeToString(&out);
-  ASSERT_TRUE(WriteStringToFile(out, apex_dir + "/apex_manifest.pb"));
-}
-
-TEST_F(ApexdMountTest, ActivateFlattenedApex) {
-  std::string apex_dir_1 = GetBuiltInDir() + "/com.android.apex.test_package";
-  std::string apex_dir_2 = GetBuiltInDir() + "/com.android.apex.test_package_2";
-  PrepareFlattenedApex(apex_dir_1, "com.android.apex.test_package", 2);
-  PrepareFlattenedApex(apex_dir_2, "com.android.apex.test_package_2", 1);
-
-  ASSERT_EQ(ActivateFlattenedApex(), 0);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package_2"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  ASSERT_EQ(GetSelinuxContext("/apex/apex-info-list.xml"),
-            "u:object_r:apex_info_file:s0");
-
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_1 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_dir_1,
-      /* preinstalledModulePath= */ apex_dir_1,
-      /* versionCode= */ 2, /* versionName= */ "2",
-      /* isFactory= */ true, /* isActive= */ true,
-      /* lastUpdateMillis= */ 0,
-      /* provideSharedApexLibs= */ false);
-  auto apex_info_xml_2 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package_2",
-      /* modulePath= */ apex_dir_2,
-      /* preinstalledModulePath= */ apex_dir_2,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ true,
-      /* lastUpdateMillis= */ 0,
-      /* provideSharedApexLibs= */ false);
-
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
-                                   ApexInfoXmlEq(apex_info_xml_2)));
-}
-
-TEST_F(ApexdMountTest, ActivateFlattenedApexShouldFailWithDuplicate) {
-  // Two flattened APEXes with the same name
-  PrepareFlattenedApex(GetBuiltInDir() + "/com.android.apex.test_package",
-                       "com.android.apex.test_package", 1);
-  PrepareFlattenedApex(GetBuiltInDir() + "/com.android.apex.test_package_2",
-                       "com.android.apex.test_package", 1);
-
-  CaptureStderr();
-  ASSERT_EQ(ActivateFlattenedApex(), 1);
-  std::string error = GetCapturedStderr();
-  ASSERT_THAT(error,
-              HasSubstr("duplicate of com.android.apex.test_package found"));
-}
-
-TEST_F(ApexdMountTest, ActivateFlattenedApexSupportsMultiApex) {
-  auto apex_dir = GetBuiltInDir() + "/com.android.apex.test_package";
-  // Two flattened APEXes with the same name
-  PrepareFlattenedApex(apex_dir, "com.android.apex.test_package", 1);
-  PrepareFlattenedApex(apex_dir + "_something_else",
-                       "com.android.apex.test_package", 1);
-
-  // With sysprop indicating multi-apex
-  std::string property_prefix = "debug.apexd.test.persistprefix.";
-  android::base::SetProperty(property_prefix + "com.android.apex.test_package",
-                             "com.android.apex.test_package");
-
-  ASSERT_EQ(ActivateFlattenedApex({property_prefix}), 0);  // Succeeds
-
-  // apex-info-list.xml should have original paths (realpaths) not symlinks
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_dir,
-      /* preinstalledModulePath= */ apex_dir,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ true,
-      /* lastUpdateMillis= */ 0,
-      /* provideSharedApexLibs= */ false);
-  ASSERT_THAT(info_list->getApexInfo(), ElementsAre(ApexInfoXmlEq(apex_info)));
-
-  android::base::SetProperty(property_prefix + "com.android.apex.test_package",
-                             "");
-}
-
-TEST_F(ApexdMountTest, ActivateFlattenedApexShouldHaveRealPaths) {
-  // Prepare flattened apexes somewhere else
-  TemporaryDir dir;
-  auto apex_dir_1 = fmt::format("{}/apex1", dir.path);
-  auto apex_dir_2 = fmt::format("{}/apex2", dir.path);
-  PrepareFlattenedApex(apex_dir_1, "com.android.apex.test_package", 2);
-  PrepareFlattenedApex(apex_dir_2, "com.android.apex.test_package_2", 1);
-
-  // Symlink flattened apexes under builtin dir.
-  auto symlink_apex_dir1 = fmt::format("{}/apex1", GetBuiltInDir());
-  auto symlink_apex_dir2 = fmt::format("{}/apex2", GetBuiltInDir());
-  ASSERT_EQ(0, symlink(apex_dir_1.c_str(), symlink_apex_dir1.c_str()));
-  ASSERT_EQ(0, symlink(apex_dir_2.c_str(), symlink_apex_dir2.c_str()));
-
-  ASSERT_EQ(ActivateFlattenedApex(), 0);
-
-  // apex-info-list.xml should have original paths (realpaths) not symlinks
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_1 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_dir_1,
-      /* preinstalledModulePath= */ apex_dir_1,
-      /* versionCode= */ 2, /* versionName= */ "2",
-      /* isFactory= */ true, /* isActive= */ true,
-      /* lastUpdateMillis= */ 0,
-      /* provideSharedApexLibs= */ false);
-  auto apex_info_xml_2 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package_2",
-      /* modulePath= */ apex_dir_2,
-      /* preinstalledModulePath= */ apex_dir_2,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ true,
-      /* lastUpdateMillis= */ 0,
-      /* provideSharedApexLibs= */ false);
-
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
-                                   ApexInfoXmlEq(apex_info_xml_2)));
-}
-
 TEST_F(ApexdMountTest, OnStartOnlyPreInstalledApexes) {
   MockCheckpointInterface checkpoint_interface;
   // Need to call InitializeVold before calling OnStart
diff --git a/apexd/dump_apex_info.cpp b/apexd/dump_apex_info.cpp
index c677e84..d9842ab 100644
--- a/apexd/dump_apex_info.cpp
+++ b/apexd/dump_apex_info.cpp
@@ -18,27 +18,19 @@
 #include <android-base/logging.h>
 #include <getopt.h>
 
-#include <chrono>
 #include <string>
 
 #include "apex_constants.h"
 #include "apex_file_repository.h"
-#include "apexd_utils.h"
 #include "com_android_apex.h"
 
 using android::apex::kApexInfoList;
-using android::apex::kManifestFilenamePb;
-using android::apex::PathExists;
-using android::apex::ReadDir;
-using android::apex::ReadManifest;
 using com::android::apex::ApexInfo;
 
 void usage(const char* cmd) {
   std::cout << "Usage: " << cmd << " --root_dir=<dir>" << std::endl;
 }
 
-std::vector<ApexInfo> LoadFlattenedApexes(const std::string& root_dir);
-
 // Create apex-info-list based on pre installed apexes
 int main(int argc, char** argv) {
   android::base::InitLogging(argv, android::base::StdioLogger);
@@ -124,16 +116,11 @@
                        /* preinstalledModulePath= */ path, manifest.version(),
                        manifest.versionname(),
                        /* isFactory= */ true, /* isActive= */ true,
-                       /*l astUpdateMillis= */ std::nullopt,
+                       /* lastUpdateMillis= */ std::nullopt,
                        manifest.providesharedapexlibs());
     apex_infos.emplace_back(std::move(apex_info));
   }
 
-  // As a second guess, try to load "flattened" apexes
-  if (apex_infos.empty()) {
-    apex_infos = LoadFlattenedApexes(root_dir);
-  }
-
   std::stringstream xml;
   com::android::apex::ApexInfoList apex_info_list(apex_infos);
   com::android::apex::write(xml, apex_info_list);
@@ -154,54 +141,3 @@
 
   return 0;
 }
-
-std::vector<ApexInfo> LoadFlattenedApexes(const std::string& root_dir) {
-  std::vector<ApexInfo> apex_infos;
-
-  for (const std::string& dir : ::android::apex::kApexPackageBuiltinDirs) {
-    if (auto res = PathExists(root_dir + dir); !res.ok() || !*res) {
-      continue;
-    }
-
-    auto dir_content = ReadDir(root_dir + dir, [](const auto& entry) {
-      std::error_code ec;
-      return entry.is_directory(ec);
-    });
-
-    if (!dir_content.ok()) {
-      LOG(ERROR) << "Failed to scan " << dir << " : " << dir_content.error();
-      continue;
-    }
-
-    // Sort to make sure that /apex/apex-info-list.xml generation doesn't depend
-    // on the unstable directory scan.
-    std::vector<std::string> entries = std::move(*dir_content);
-    std::sort(entries.begin(), entries.end());
-
-    for (const std::string& apex_dir : entries) {
-      std::string manifest_file = apex_dir + "/" + kManifestFilenamePb;
-      if (access(manifest_file.c_str(), F_OK) != 0) {
-        PLOG(ERROR) << "Failed to access " << manifest_file;
-        continue;
-      }
-
-      auto manifest = ReadManifest(manifest_file);
-      if (!manifest.ok()) {
-        LOG(ERROR) << "Failed to read apex manifest from " << manifest_file
-                   << " : " << manifest.error();
-        continue;
-      }
-
-      // Remove leading path (root_dir)
-      const auto& path = apex_dir.substr(root_dir.length());
-      apex_infos.emplace_back(manifest->name(), /* modulePath= */ path,
-                              /* preinstalledModulePath= */ path,
-                              /* versionCode= */ manifest->version(),
-                              /* versionName= */ manifest->versionname(),
-                              /* isFactory= */ true, /* isActive= */ true,
-                              /* lastUpdateMillis= */ 0,
-                              /* provideSharedApexLibs= */ false);
-    }
-  }
-  return apex_infos;
-}
diff --git a/apexd/flattened_apex_test.cpp b/apexd/flattened_apex_test.cpp
deleted file mode 100644
index c2deddd..0000000
--- a/apexd/flattened_apex_test.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2019 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 <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/strings.h>
-
-#include <gtest/gtest.h>
-#include <filesystem>
-#include <memory>
-
-#include <ApexProperties.sysprop.h>
-#include "apex_constants.h"
-#include "apex_shim.h"
-#include "apexd_utils.h"
-#include "string_log.h"
-
-namespace android {
-namespace apex {
-
-TEST(FlattenedApexTest, SysPropIsFalse) {
-  bool value = android::sysprop::ApexProperties::updatable().value_or(false);
-  ASSERT_FALSE(value);
-}
-
-TEST(FlattenedApexTest, ApexFilesAreFlattened) {
-  namespace fs = std::filesystem;
-  auto assert_is_dir = [&](const fs::directory_entry& entry) {
-    if (entry.path().filename() == shim::kSystemShimApexName) {
-      return;
-    }
-    std::error_code ec;
-    bool is_dir = entry.is_directory(ec);
-    ASSERT_FALSE(ec) << ec.message();
-    ASSERT_TRUE(is_dir) << entry.path() << " is not a directory";
-  };
-  WalkDir(kApexPackageSystemDir, assert_is_dir);
-}
-
-TEST(FlattenedApexTest, MountsAreCorrect) {
-  using android::base::ReadFileToString;
-  using android::base::Split;
-  std::string mounts;
-  ASSERT_TRUE(ReadFileToString("/proc/self/mountinfo", &mounts));
-  bool has_apex_mount = false;
-  for (const auto& mount : Split(mounts, "\n")) {
-    const std::vector<std::string>& tokens = Split(mount, " ");
-    // line format:
-    // mnt_id parent_mnt_id major:minor source target option propagation_type
-    if (tokens.size() < 7) {
-      continue;
-    }
-    const std::string& source = tokens[3];
-    const std::string& target = tokens[4];
-    if (source == kApexPackageSystemDir && target == "/apex") {
-      has_apex_mount = true;
-    }
-  }
-  ASSERT_TRUE(has_apex_mount) << "Failed to find apex mount point";
-}
-
-TEST(FlattenedApexTest, ApexdIsNotRunning) {
-  constexpr const char* kCmd = "pidof -s apexd";
-  std::unique_ptr<FILE, int (*)(FILE*)> pipe(popen(kCmd, "r"), pclose);
-  ASSERT_NE(nullptr, pipe) << "Failed to open pipe for: " << kCmd;
-  char buf[1024];
-  if (fgets(buf, 1024, pipe.get()) != nullptr) {
-    FAIL() << "apexd is running and has pid " << buf;
-  }
-}
-
-}  // namespace apex
-}  // namespace android
-
-int main(int argc, char** argv) {
-  ::testing::InitGoogleTest(&argc, argv);
-  android::base::InitLogging(argv, &android::base::StderrLogger);
-  return RUN_ALL_TESTS();
-}
diff --git a/apexd/flattened_apex_test_config.xml b/apexd/flattened_apex_test_config.xml
deleted file mode 100644
index f50d1fe..0000000
--- a/apexd/flattened_apex_test_config.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 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.
--->
-<configuration description="Runs flattened_apex_test.">
-    <option name="test-suite-tag" value="apct" />
-    <option name="test-suite-tag" value="apct-native" />
-    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
-        <option name="cleanup" value="true" />
-        <option name="push" value="flattened_apex_test->/data/local/tmp/flattened_apex_test" />
-    </target_preparer>
-
-    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
-
-    <test class="com.android.tradefed.testtype.GTest" >
-        <option name="native-test-device-path" value="/data/local/tmp" />
-        <option name="module-name" value="flattened_apex_test" />
-    </test>
-</configuration>
diff --git a/docs/README.md b/docs/README.md
index 241516a..a43245a 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -484,18 +484,7 @@
 
 ## Configuring system to support APEX updates
 
-Set the following system property to `true` to support APEX file updates.
-
-```
-<device.mk>:
-
-PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true
-
-BoardConfig.mk:
-TARGET_FLATTEN_APEX := false
-```
-
-or just
+Inherit `updatable_apex.mk`.
 
 ```
 <device.mk>:
@@ -503,36 +492,6 @@
 $(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)
 ```
 
-## Flattened APEX
-
-For legacy devices, it is sometimes impossible or infeasible to update the old
-kernel to fully support APEX. For example, the kernel might have been built
-without `CONFIG_BLK_DEV_LOOP=Y`, which is crucial for mounting the file system
-image inside an APEX.
-
-Flattened APEX is a specially built APEX that can be activated on devices with a
-legacy kernel. Files in a flattened APEX are directly installed to a directory
-under the built-in partition. For example, `lib/libFoo.so` in a flattend APEX
-`my.apex` is installed to `/system/apex/my.apex/lib/libFoo.so`.
-
-Activating a flattened APEX doesn't involve the loop device. The entire
-directory `/system/apex/my.apex` is directly bind-mounted to `/apex/name@ver`.
-
-Flattened APEXs can't be updated by downloading updated versions of the APEXs
-from network because the downloaded APEXs can't be flattened. Flattened APEXs
-can be updated only via a regular OTA.
-
-Note that flattened APEX is the default configuration for now. This means all
-APEXes are by default flattened unless you explicitly configure your device to
-support updatable APEX (explained above).
-
-Also note that, mixing flattened and non-flattened APEXes in a device is NOT
-supported. It should be either all non-flattened or all flattened. This is
-especially important when shipping pre-signed APEX prebuilts for the projects
-like Mainline. APEXes that are not pre-signed (i.e. built from the source)
-should also be non-flattened and signed with proper keys in that case. The
-device should inherit from `updatable_apex.mk` as explained above.
-
 ## Compressed apexes {#compressed-apex}
 
 APEX compression is a new feature introduced in Android S. Its main purpose is
diff --git a/docs/howto.md b/docs/howto.md
index 1c0b4c4..853f976 100644
--- a/docs/howto.md
+++ b/docs/howto.md
@@ -414,52 +414,14 @@
 
 ## Configuring system to support APEX updates
 
-Set the following system property to true to support APEX file updates.
+Inherit `updatable_apex.mk`.
 
 ```
 <device.mk>:
 
-PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true
-
-BoardConfig.mk:
-TARGET_FLATTEN_APEX := false
-
-or just
-<device.mk>:
-
 $(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)
 ```
 
-## Flattened APEX
-
-For legacy devices, it is sometimes impossible or infeasible to update the old
-kernel to fully support APEX. For example, the kernel might have been built
-without `CONFIG_BLK_DEV_LOOP=Y`, which is crucial for mounting the file system
-image inside an APEX.
-
-Flattened APEX is a specially built APEX that can be activated on devices with a
-legacy kernel. Files in a flattened APEX are directly installed to a directory
-under the built-in partition. For example, `lib/libFoo.so` in a flattened APEX
-my.apex is installed to `/system/apex/my.apex/lib/libFoo.so`.
-
-Activating a flattened APEX doesn't involve the loop device. The entire
-directory `/system/apex/my.apex` is directly bind-mounted to `/apex/name@ver`.
-
-Flattened APEXs can‘t be updated by downloading updated versions of the APEXs
-from network because the downloaded APEXs can’t be flattened. Flattened APEXs
-can be updated only via a regular OTA.
-
-Note that flattened APEX is the default configuration for now (2019/Aug). This
-means all APEXes are by default flattened unless you explicitly configure your
-device to support updatable APEX (explained above).
-
-Also note that, mixing flattened and non-flattened APEXes in a device is NOT
-supported. It should be either all non-flattened or all flattened. This is
-especially important when shipping pre-signed APEX prebuilts for the projects
-like Mainline. APEXes that are not pre-signed (i.e. built from the source)
-should also be non-flattened and signed with proper keys in that case. The
-device should inherit from `updatable_apex.mk` as explained above.
-
 ## Building APEX without Soong
 
 An APEX can be built without relying on the build commands generated by Soong.
diff --git a/libs/libapexutil/apexutil.h b/libs/libapexutil/apexutil.h
index f351294..0e8a8a4 100644
--- a/libs/libapexutil/apexutil.h
+++ b/libs/libapexutil/apexutil.h
@@ -24,8 +24,7 @@
 namespace apex {
 
 // Returns active APEX packages as a map of path(e.g. /apex/com.android.foo) to
-// ApexManifest. This is very similar to ApexService::getActivePackages, but it
-// doesn't rely on whether APEXes are flattened or not.
+// ApexManifest. This is very similar to ApexService::getActivePackages.
 // For testing purpose, it accepts the apex root path which is defined by
 // kApexRoot constant.
 std::map<std::string, ::apex::proto::ApexManifest>
diff --git a/shim/build/Android.bp b/shim/build/Android.bp
index 433700b..d1b5890 100644
--- a/shim/build/Android.bp
+++ b/shim/build/Android.bp
@@ -298,20 +298,6 @@
   updatable: false,
 }
 
-// This is to install the flattened version of com.android.apex.cts.shim.
-// Because com.android.apex.cts.shim is provided as prebuilt and the build system
-// doesn't support install "flattened" version from "prebult" yet, GSI, which should
-// have both "flatttened" and "unflattened" APEXes, is missing the flattened version
-// of com.android.apex.cts.shim.
-// TODO(b/159426728):  When the build system can install "flattened" from "prebuilts",
-// this can be removed.
-override_apex {
-  name: "com.android.apex.cts.shim.v1_with_prebuilts",
-  base: "com.android.apex.cts.shim.v1",
-  apps: ["CtsShimPrebuilt", "CtsShimPrivPrebuilt"],
-  allowed_files: "prebuilts_shim_allowed_list.txt",
-}
-
 genrule {
   name: "com.android.apex.cts.shim_not_pre_installed.pem",
   out: ["com.android.apex.cts.shim_not_pre_installed.pem"],
diff --git a/shim/build/prebuilts_shim_allowed_list.txt b/shim/build/prebuilts_shim_allowed_list.txt
deleted file mode 100644
index 7da513f..0000000
--- a/shim/build/prebuilts_shim_allowed_list.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-./apex_manifest.pb
-./app/CtsShimPrebuilt/CtsShimPrebuilt.apk
-./etc/hash.txt
-./priv-app/CtsShimPrivPrebuilt/CtsShimPrivPrebuilt.apk
diff --git a/tools/deapexer.py b/tools/deapexer.py
index 33e5582..f4a5c7f 100755
--- a/tools/deapexer.py
+++ b/tools/deapexer.py
@@ -164,7 +164,6 @@
     self._fsckerofs = args.fsckerofs_path
     self._apex = args.apex
     self._tempdir = tempfile.mkdtemp()
-    # TODO(b/139125405): support flattened APEXes.
     with zipfile.ZipFile(self._apex, 'r') as zip_ref:
       self._payload = zip_ref.extract('apex_payload.img', path=self._tempdir)
     self._payload_fs_type = RetrieveFileSystemType(self._payload)
@@ -189,11 +188,8 @@
   def _list(self, path):
     if path in self._cache:
       return self._cache[path]
-    process = subprocess.Popen([self._debugfs, '-R', 'ls -l -p %s' % path, self._payload],
-                               stdout=subprocess.PIPE, stderr=subprocess.PIPE,
-                               universal_newlines=True)
-    stdout, _ = process.communicate()
-    res = str(stdout)
+    res = subprocess.check_output([self._debugfs, '-R', 'ls -l -p %s' % path, self._payload],
+                                  text=True, stderr=subprocess.DEVNULL)
     entries = []
     for line in res.split('\n'):
       if not line:
@@ -212,17 +208,15 @@
       is_directory=bits[1]=='4'
 
       if not is_symlink and not is_directory:
-        process = subprocess.Popen([self._debugfs, '-R', 'dump_extents <%s>' % ino,
-                                    self._payload], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
-                                    universal_newlines=True)
-        stdout, _ = process.communicate()
+        stdout = subprocess.check_output([self._debugfs, '-R', 'dump_extents <%s>' % ino,
+                                          self._payload], text=True, stderr=subprocess.DEVNULL)
         # Output of dump_extents for an inode fragmented in 3 blocks (length and addresses represent
         # block-sized sections):
         # Level Entries       Logical      Physical Length Flags
         # 0/ 0   1/  3     0 -     0    18 -    18      1
         # 0/ 0   2/  3     1 -    15    20 -    34     15
         # 0/ 0   3/  3    16 -  1863    37 -  1884   1848
-        res = str(stdout).splitlines()
+        res = stdout.splitlines()
         res.pop(0) # the first line contains only columns names
         left_length = int(size)
         try: # dump_extents sometimes has an unexpected output
@@ -261,21 +255,15 @@
 
   def extract(self, dest):
     if self._payload_fs_type == 'erofs':
-      process = subprocess.Popen([self._fsckerofs, '--extract=%s' % (dest), '--overwrite', self._payload],
-                                 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
-                                 universal_newlines=True)
+      subprocess.run([self._fsckerofs, '--extract=%s' % (dest), '--overwrite', self._payload],
+                     stdout=subprocess.DEVNULL, check=True)
     elif self._payload_fs_type == 'ext4':
-      process = subprocess.Popen([self._debugfs, '-R', 'rdump ./ %s' % (dest), self._payload],
-                                 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
-                                 universal_newlines=True)
+      subprocess.run([self._debugfs, '-R', 'rdump ./ %s' % (dest), self._payload],
+                     stdout=subprocess.DEVNULL, check=True)
     else:
       # TODO(b/279688635) f2fs is not supported yet.
       sys.exit(f"{self._payload_fs_type} is not supported for `extract`.")
 
-    _, stderr = process.communicate()
-    if process.returncode != 0:
-      print(stderr, file=sys.stderr)
-
 
 def RunList(args):
   if GetType(args.apex) == ApexType.COMPRESSED:
diff --git a/tools/host-apex-verifier.sh b/tools/host-apex-verifier.sh
index e732758..1114aaa 100755
--- a/tools/host-apex-verifier.sh
+++ b/tools/host-apex-verifier.sh
@@ -1,12 +1,6 @@
 #!/bin/bash
 set -x
 
-APEX_UPDATABLE="`adb shell getprop ro.apex.updatable`"
-if [[ $APEX_UPDATABLE != "true" ]]; then
-  echo "Skipping this test: device uses flattened APEXes."
-  exit 0;
-fi
-
 echo "Pulling APEXes from the device factory APEX directories."
 TEMP_DIR="`mktemp -d`"
 adb pull /system/apex/ $TEMP_DIR/system