Merge "ion-unit-tests: Add system heap presence test"
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index f00129a..c744fe4 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -136,11 +136,27 @@
 
     UpdateState state = ReadUpdateState(file.get());
     if (state == UpdateState::None) return true;
-    if (state != UpdateState::Initiated) {
-        LOG(ERROR) << "Cannot cancel update after it has completed or started merging";
-        return false;
+
+    if (state == UpdateState::Initiated) {
+        LOG(INFO) << "Update has been initiated, now canceling";
+        return RemoveAllUpdateState(file.get());
     }
-    return RemoveAllUpdateState(file.get());
+
+    if (state == UpdateState::Unverified) {
+        // We completed an update, but it can still be canceled if we haven't booted into it.
+        auto boot_file = GetSnapshotBootIndicatorPath();
+        std::string contents;
+        if (!android::base::ReadFileToString(boot_file, &contents)) {
+            PLOG(WARNING) << "Cannot read " << boot_file << ", proceed to canceling the update:";
+            return RemoveAllUpdateState(file.get());
+        }
+        if (device_->GetSlotSuffix() == contents) {
+            LOG(INFO) << "Canceling a previously completed update";
+            return RemoveAllUpdateState(file.get());
+        }
+    }
+    LOG(ERROR) << "Cannot cancel update after it has completed or started merging";
+    return false;
 }
 
 bool SnapshotManager::RemoveAllUpdateState(LockedFile* lock) {
diff --git a/init/interface_utils.cpp b/init/interface_utils.cpp
index a54860f..ddbacd7 100644
--- a/init/interface_utils.cpp
+++ b/init/interface_utils.cpp
@@ -77,6 +77,12 @@
                                                 const InterfaceInheritanceHierarchyMap& hierarchy) {
     std::set<FQName> interface_fqnames;
     for (const std::string& instance : instances) {
+        // There is insufficient build-time information on AIDL interfaces to check them here
+        // TODO(b/139307527): Rework how services store interfaces to avoid excess string parsing
+        if (base::Split(instance, "/")[0] == "aidl") {
+            continue;
+        }
+
         FqInstance fqinstance;
         if (!fqinstance.setTo(instance)) {
             return Error() << "Unable to parse interface instance '" << instance << "'";
diff --git a/init/service_parser.cpp b/init/service_parser.cpp
index dd552fb..543be23 100644
--- a/init/service_parser.cpp
+++ b/init/service_parser.cpp
@@ -145,17 +145,21 @@
     const std::string& interface_name = args[1];
     const std::string& instance_name = args[2];
 
-    FQName fq_name;
-    if (!FQName::parse(interface_name, &fq_name)) {
-        return Error() << "Invalid fully-qualified name for interface '" << interface_name << "'";
-    }
+    // AIDL services don't use fully qualified names and instead just use "interface aidl <name>"
+    if (interface_name != "aidl") {
+        FQName fq_name;
+        if (!FQName::parse(interface_name, &fq_name)) {
+            return Error() << "Invalid fully-qualified name for interface '" << interface_name
+                           << "'";
+        }
 
-    if (!fq_name.isFullyQualified()) {
-        return Error() << "Interface name not fully-qualified '" << interface_name << "'";
-    }
+        if (!fq_name.isFullyQualified()) {
+            return Error() << "Interface name not fully-qualified '" << interface_name << "'";
+        }
 
-    if (fq_name.isValidValueName()) {
-        return Error() << "Interface name must not be a value name '" << interface_name << "'";
+        if (fq_name.isValidValueName()) {
+            return Error() << "Interface name must not be a value name '" << interface_name << "'";
+        }
     }
 
     const std::string fullname = interface_name + "/" + instance_name;
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 0d3d4db..58db96c 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -445,7 +445,6 @@
     mark_post_data
 
     # Start checkpoint before we touch data
-    start vold
     exec - system system -- /system/bin/vdc checkpoint prepareCheckpoint
 
     # We chown/chmod /data again so because mount is run as root + defaults