Implement vendor-available vold interface
Bug: 362567323
Test: mmm system/vold
Change-Id: I967faeb221741cbd8d6c13b25cd57c37fbb6e839
diff --git a/Android.bp b/Android.bp
index ba3267c..1eeb1a1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -43,6 +43,7 @@
"libfs_mgr",
"libsquashfs_utils",
"libvold_binder",
+ "android.system.vold-V1-cpp",
],
shared_libs: [
"android.hardware.boot@1.0",
@@ -103,6 +104,11 @@
export_include_dirs: ["."],
}
+vintf_fragment {
+ name: "android.system.vold-service.xml",
+ src: "android.system.vold-service.xml",
+}
+
// Static library factored out to support testing
cc_library_static {
name: "libvold",
@@ -132,6 +138,7 @@
"NetlinkManager.cpp",
"Process.cpp",
"Utils.cpp",
+ "VendorVoldNativeService.cpp",
"VoldNativeService.cpp",
"VoldNativeServiceValidation.cpp",
"VoldUtil.cpp",
@@ -198,6 +205,7 @@
],
},
},
+ vintf_fragment_modules: ["android.system.vold-service.xml"],
}
cc_binary {
diff --git a/Checkpoint.cpp b/Checkpoint.cpp
index 598a87b..27d99e7 100644
--- a/Checkpoint.cpp
+++ b/Checkpoint.cpp
@@ -159,6 +159,21 @@
// Protects isCheckpointing, needsCheckpointWasCalled and code that makes decisions based on status
// of isCheckpointing
std::mutex isCheckpointingLock;
+
+std::mutex listenersLock;
+std::vector<android::sp<android::system::vold::IVoldCheckpointListener>> listeners;
+} // namespace
+
+void notifyCheckpointListeners() {
+ std::lock_guard<std::mutex> lock(listenersLock);
+
+ for (auto& listener : listeners) {
+ listener->onCheckpointingComplete();
+ listener = nullptr;
+ }
+
+ // Reclaim vector memory; we likely won't need it again.
+ listeners = std::vector<android::sp<android::system::vold::IVoldCheckpointListener>>();
}
Status cp_commitChanges() {
@@ -221,6 +236,8 @@
if (!android::base::RemoveFileIfExists(kMetadataCPFile, &err_str))
return error(err_str.c_str());
+ notifyCheckpointListeners();
+
std::thread(DoCheckpointCommittedWork).detach();
return Status::ok();
}
@@ -300,6 +317,9 @@
if (ret) {
ret = content != "0";
isCheckpointing = ret;
+ if (!isCheckpointing) {
+ notifyCheckpointListeners();
+ }
return ret;
}
return false;
@@ -801,5 +821,20 @@
needsCheckpointWasCalled = false;
}
+bool cp_registerCheckpointListener(
+ android::sp<android::system::vold::IVoldCheckpointListener> listener) {
+ std::lock_guard<std::mutex> checkpointGuard(isCheckpointingLock);
+ if (needsCheckpointWasCalled && !isCheckpointing) {
+ // Either checkpoint already committed or we didn't need one
+ return false;
+ }
+
+ // Either we don't know whether we need a checkpoint or we're already checkpointing,
+ // so we need to save this listener to notify later.
+ std::lock_guard<std::mutex> listenersGuard(listenersLock);
+ listeners.push_back(std::move(listener));
+ return true;
+}
+
} // namespace vold
} // namespace android
diff --git a/Checkpoint.h b/Checkpoint.h
index 6f3acac..7625310 100644
--- a/Checkpoint.h
+++ b/Checkpoint.h
@@ -17,6 +17,7 @@
#ifndef _CHECKPOINT_H
#define _CHECKPOINT_H
+#include <android/system/vold/IVold.h>
#include <binder/Status.h>
#include <string>
@@ -48,6 +49,9 @@
android::binder::Status cp_markBootAttempt();
void cp_resetCheckpoint();
+
+bool cp_registerCheckpointListener(
+ android::sp<android::system::vold::IVoldCheckpointListener> listener);
} // namespace vold
} // namespace android
diff --git a/VendorVoldNativeService.cpp b/VendorVoldNativeService.cpp
new file mode 100644
index 0000000..6d13a14
--- /dev/null
+++ b/VendorVoldNativeService.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 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 "VendorVoldNativeService.h"
+
+#include <mutex>
+
+#include <android-base/logging.h>
+#include <binder/IServiceManager.h>
+#include <private/android_filesystem_config.h>
+#include <utils/Trace.h>
+
+#include "Checkpoint.h"
+#include "VoldNativeServiceValidation.h"
+#include "VolumeManager.h"
+
+#define ENFORCE_SYSTEM_OR_ROOT \
+ { \
+ binder::Status status = CheckUidOrRoot(AID_SYSTEM); \
+ if (!status.isOk()) { \
+ return status; \
+ } \
+ }
+
+#define ACQUIRE_LOCK \
+ std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getLock()); \
+ ATRACE_CALL();
+
+namespace android::vold {
+
+status_t VendorVoldNativeService::try_start() {
+ auto service_name = String16("android.system.vold.IVold/default");
+ if (!defaultServiceManager()->isDeclared(service_name)) {
+ LOG(DEBUG) << "Service for VendorVoldNativeService (" << service_name << ") not declared.";
+ return OK;
+ }
+ return defaultServiceManager()->addService(std::move(service_name),
+ new VendorVoldNativeService());
+}
+
+binder::Status VendorVoldNativeService::registerCheckpointListener(
+ const sp<android::system::vold::IVoldCheckpointListener>& listener,
+ android::system::vold::CheckpointingState* _aidl_return) {
+ ENFORCE_SYSTEM_OR_ROOT;
+ ACQUIRE_LOCK;
+
+ bool possible_checkpointing = cp_registerCheckpointListener(listener);
+ *_aidl_return = possible_checkpointing
+ ? android::system::vold::CheckpointingState::POSSIBLE_CHECKPOINTING
+ : android::system::vold::CheckpointingState::CHECKPOINTING_COMPLETE;
+ return binder::Status::ok();
+}
+
+} // namespace android::vold
diff --git a/VendorVoldNativeService.h b/VendorVoldNativeService.h
new file mode 100644
index 0000000..884ccb0
--- /dev/null
+++ b/VendorVoldNativeService.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#ifndef _VENDOR_VOLD_NATIVE_SERVICE_H_
+#define _VENDOR_VOLD_NATIVE_SERVICE_H_
+
+#include <android/system/vold/BnVold.h>
+#include <android/system/vold/CheckpointingState.h>
+#include <android/system/vold/IVoldCheckpointListener.h>
+
+namespace android::vold {
+
+class VendorVoldNativeService : public android::system::vold::BnVold {
+ public:
+ /** Start the service, but if it's not declared, give up and return OK. */
+ static status_t try_start();
+
+ binder::Status registerCheckpointListener(
+ const sp<android::system::vold::IVoldCheckpointListener>& listener,
+ android::system::vold::CheckpointingState* _aidl_return) final;
+};
+
+} // namespace android::vold
+
+#endif // _VENDOR_VOLD_NATIVE_SERVICE_H_
\ No newline at end of file
diff --git a/android.system.vold-service.xml b/android.system.vold-service.xml
new file mode 100644
index 0000000..ea084b7
--- /dev/null
+++ b/android.system.vold-service.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="framework">
+ <hal format="aidl">
+ <name>android.system.vold</name>
+ <version>1</version>
+ <interface>
+ <name>IVold</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
\ No newline at end of file
diff --git a/main.cpp b/main.cpp
index 078ee14..bdce76e 100644
--- a/main.cpp
+++ b/main.cpp
@@ -19,6 +19,7 @@
#include "FsCrypt.h"
#include "MetadataCrypt.h"
#include "NetlinkManager.h"
+#include "VendorVoldNativeService.h"
#include "VoldNativeService.h"
#include "VoldUtil.h"
#include "VolumeManager.h"
@@ -126,9 +127,16 @@
exit(1);
}
ATRACE_END();
-
LOG(DEBUG) << "VoldNativeService::start() completed OK";
+ ATRACE_BEGIN("VendorVoldNativeService::try_start");
+ if (android::vold::VendorVoldNativeService::try_start() != android::OK) {
+ LOG(ERROR) << "Unable to start VendorVoldNativeService";
+ exit(1);
+ }
+ ATRACE_END();
+ LOG(DEBUG) << "VendorVoldNativeService::try_start() completed OK";
+
ATRACE_BEGIN("NetlinkManager::start");
if (nm->start()) {
PLOG(ERROR) << "Unable to start NetlinkManager";
diff --git a/tests/VoldFuzzer.cpp b/tests/VoldFuzzer.cpp
index 630a785..b47a783 100644
--- a/tests/VoldFuzzer.cpp
+++ b/tests/VoldFuzzer.cpp
@@ -17,6 +17,7 @@
#include <android-base/logging.h>
#include <fuzzbinder/libbinder_driver.h>
+#include "VendorVoldNativeService.h"
#include "VoldNativeService.h"
#include "sehandle.h"
@@ -37,6 +38,7 @@
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
auto voldService = sp<android::vold::VoldNativeService>::make();
- fuzzService(voldService, FuzzedDataProvider(data, size));
+ auto voldVendorService = sp<android::vold::VendorVoldNativeService>::make();
+ fuzzService({voldService, voldVendorService}, FuzzedDataProvider(data, size));
return 0;
}
\ No newline at end of file