#include "model/PrivateVolume.h"
#include <thread>
+#include <utility>
#include <android-base/chrono_utils.h>
#include <android-base/file.h>
using android::base::WriteStringToFile;
using android::hardware::Return;
using android::hardware::Void;
-using android::hardware::health::storage::V1_0::IStorage;
-using android::hardware::health::storage::V1_0::IGarbageCollectCallback;
-using android::hardware::health::storage::V1_0::Result;
+using HStorage = android::hardware::health::storage::V1_0::IStorage;
+using HGarbageCollectCallback = android::hardware::health::storage::V1_0::IGarbageCollectCallback;
+using HResult = android::hardware::health::storage::V1_0::Result;
namespace android {
namespace vold {
return;
}
-class GcCallback : public IGarbageCollectCallback {
- public:
- Return<void> onFinish(Result result) override {
+enum class IDL { HIDL };
+std::ostream& operator<<(std::ostream& os, IDL idl) {
+ return os << "HIDL";
+}
+
+template <IDL idl, typename Result>
+class GcCallbackImpl {
+ protected:
+ void onFinishInternal(Result result) {
std::unique_lock<std::mutex> lock(mMutex);
mFinished = true;
mResult = result;
lock.unlock();
mCv.notify_all();
- return Void();
}
+
+ public:
void wait(uint64_t seconds) {
std::unique_lock<std::mutex> lock(mMutex);
mCv.wait_for(lock, std::chrono::seconds(seconds), [this] { return mFinished; });
if (!mFinished) {
- LOG(WARNING) << "Dev GC on HAL timeout";
+ LOG(WARNING) << "Dev GC on " << idl << " HAL timeout";
} else if (mResult != Result::SUCCESS) {
- LOG(WARNING) << "Dev GC on HAL failed with " << toString(mResult);
+ LOG(WARNING) << "Dev GC on " << idl << " HAL failed with " << toString(mResult);
} else {
- LOG(INFO) << "Dev GC on HAL successful";
+ LOG(INFO) << "Dev GC on " << idl << " HAL successful";
}
}
Result mResult{Result::UNKNOWN_ERROR};
};
-static void runDevGcOnHal(sp<IStorage> service) {
- LOG(DEBUG) << "Start Dev GC on HAL";
- sp<GcCallback> cb = new GcCallback();
+class HGcCallbackImpl : public HGarbageCollectCallback, public GcCallbackImpl<IDL::HIDL, HResult> {
+ Return<void> onFinish(HResult result) override {
+ onFinishInternal(result);
+ return Void();
+ }
+};
+
+template <IDL idl, typename Service, typename GcCallbackImpl, typename GetDescription>
+static void runDevGcOnHal(Service service, GcCallbackImpl cb, GetDescription get_description) {
+ LOG(DEBUG) << "Start Dev GC on " << idl << " HAL";
auto ret = service->garbageCollect(DEVGC_TIMEOUT_SEC, cb);
if (!ret.isOk()) {
- LOG(WARNING) << "Cannot start Dev GC on HAL: " << ret.description();
+ LOG(WARNING) << "Cannot start Dev GC on " << idl
+ << " HAL: " << std::invoke(get_description, ret);
return;
}
cb->wait(DEVGC_TIMEOUT_SEC);
}
static void runDevGc(void) {
- auto service = IStorage::getService();
- if (service != nullptr) {
- runDevGcOnHal(service);
- } else {
- // fallback to legacy code path
- runDevGcFstab();
+ auto hidl_service = HStorage::getService();
+ if (hidl_service != nullptr) {
+ runDevGcOnHal<IDL::HIDL>(hidl_service, sp<HGcCallbackImpl>(new HGcCallbackImpl()),
+ &Return<void>::description);
+ return;
}
+ // fallback to legacy code path
+ runDevGcFstab();
}
int RunIdleMaint(const android::sp<android::os::IVoldTaskListener>& listener) {