mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 05:49:27 +00:00
Merge changes from topic "health_storage_aidl"
* changes: health storage AIDL VTS test. health storage: refactor common code for test Add default impl for health storage AIDL HAL Add health.storage AIDL HAL Refactor common implementation for health storage HAL.
This commit is contained in:
@@ -266,6 +266,14 @@
|
||||
<instance>default</instance>
|
||||
</interface>
|
||||
</hal>
|
||||
<hal format="aidl" optional="true">
|
||||
<name>android.hardware.health.storage</name>
|
||||
<version>1</version>
|
||||
<interface>
|
||||
<name>IStorage</name>
|
||||
<instance>default</instance>
|
||||
</interface>
|
||||
</hal>
|
||||
<hal format="aidl" optional="true">
|
||||
<name>android.hardware.identity</name>
|
||||
<version>1-2</version>
|
||||
|
||||
@@ -38,6 +38,7 @@ cc_binary {
|
||||
],
|
||||
|
||||
static_libs: [
|
||||
"libhealth_storage_impl_common",
|
||||
"libfstab",
|
||||
],
|
||||
|
||||
|
||||
@@ -18,11 +18,8 @@
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <android-base/chrono_utils.h>
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <fstab/fstab.h>
|
||||
#include <health-storage-impl/common.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
@@ -31,69 +28,9 @@ namespace storage {
|
||||
namespace V1_0 {
|
||||
namespace implementation {
|
||||
|
||||
using base::ReadFileToString;
|
||||
using base::Timer;
|
||||
using base::Trim;
|
||||
using base::WriteStringToFd;
|
||||
using base::WriteStringToFile;
|
||||
using fs_mgr::Fstab;
|
||||
using fs_mgr::ReadDefaultFstab;
|
||||
|
||||
std::string getGarbageCollectPath() {
|
||||
Fstab fstab;
|
||||
ReadDefaultFstab(&fstab);
|
||||
|
||||
for (const auto& entry : fstab) {
|
||||
if (!entry.sysfs_path.empty()) {
|
||||
return entry.sysfs_path + "/manual_gc";
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
Return<void> Storage::garbageCollect(uint64_t timeoutSeconds,
|
||||
const sp<IGarbageCollectCallback>& cb) {
|
||||
Result result = Result::SUCCESS;
|
||||
std::string path = getGarbageCollectPath();
|
||||
|
||||
if (path.empty()) {
|
||||
LOG(WARNING) << "Cannot find Dev GC path";
|
||||
result = Result::UNKNOWN_ERROR;
|
||||
} else {
|
||||
Timer timer;
|
||||
LOG(INFO) << "Start Dev GC on " << path;
|
||||
while (1) {
|
||||
std::string require;
|
||||
if (!ReadFileToString(path, &require)) {
|
||||
PLOG(WARNING) << "Reading manual_gc failed in " << path;
|
||||
result = Result::IO_ERROR;
|
||||
break;
|
||||
}
|
||||
require = Trim(require);
|
||||
if (require == "" || require == "off" || require == "disabled") {
|
||||
LOG(DEBUG) << "No more to do Dev GC";
|
||||
break;
|
||||
}
|
||||
LOG(DEBUG) << "Trigger Dev GC on " << path;
|
||||
if (!WriteStringToFile("1", path)) {
|
||||
PLOG(WARNING) << "Start Dev GC failed on " << path;
|
||||
result = Result::IO_ERROR;
|
||||
break;
|
||||
}
|
||||
if (timer.duration() >= std::chrono::seconds(timeoutSeconds)) {
|
||||
LOG(WARNING) << "Dev GC timeout";
|
||||
// Timeout is not treated as an error. Try next time.
|
||||
break;
|
||||
}
|
||||
sleep(2);
|
||||
}
|
||||
LOG(INFO) << "Stop Dev GC on " << path;
|
||||
if (!WriteStringToFile("0", path)) {
|
||||
PLOG(WARNING) << "Stop Dev GC failed on " << path;
|
||||
result = Result::IO_ERROR;
|
||||
}
|
||||
}
|
||||
Result result = GarbageCollect(timeoutSeconds);
|
||||
|
||||
if (cb != nullptr) {
|
||||
auto ret = cb->onFinish(result);
|
||||
@@ -110,28 +47,7 @@ Return<void> Storage::debug(const hidl_handle& handle, const hidl_vec<hidl_strin
|
||||
}
|
||||
|
||||
int fd = handle->data[0];
|
||||
std::stringstream output;
|
||||
|
||||
std::string path = getGarbageCollectPath();
|
||||
if (path.empty()) {
|
||||
output << "Cannot find Dev GC path";
|
||||
} else {
|
||||
std::string require;
|
||||
|
||||
if (ReadFileToString(path, &require)) {
|
||||
output << path << ":" << require << std::endl;
|
||||
}
|
||||
|
||||
if (WriteStringToFile("0", path)) {
|
||||
output << "stop success" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WriteStringToFd(output.str(), fd)) {
|
||||
PLOG(WARNING) << "debug: cannot write to fd";
|
||||
}
|
||||
|
||||
fsync(fd);
|
||||
DebugDump(fd);
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@ cc_test {
|
||||
defaults: ["VtsHalTargetTestDefaults"],
|
||||
srcs: ["VtsHalHealthStorageV1_0TargetTest.cpp"],
|
||||
static_libs: ["android.hardware.health.storage@1.0"],
|
||||
header_libs: [
|
||||
"libhealth_storage_test_common_headers",
|
||||
],
|
||||
shared_libs: [
|
||||
"libhidlbase",
|
||||
],
|
||||
|
||||
@@ -14,14 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android/hardware/health/storage/1.0/IStorage.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <health-storage-test/common.h>
|
||||
#include <hidl/GtestPrinter.h>
|
||||
#include <hidl/HidlTransportSupport.h>
|
||||
#include <hidl/ServiceManagement.h>
|
||||
#include <unistd.h>
|
||||
#include <thread>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
@@ -29,61 +32,17 @@ namespace health {
|
||||
namespace storage {
|
||||
namespace V1_0 {
|
||||
|
||||
using namespace ::android::hardware::health::storage::test;
|
||||
using ::std::literals::chrono_literals::operator""ms;
|
||||
|
||||
#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk()) << ret.description()
|
||||
|
||||
// Dev GC timeout. This is the timeout used by vold.
|
||||
const uint64_t kDevGcTimeoutSec = 120;
|
||||
const std::chrono::seconds kDevGcTimeout{kDevGcTimeoutSec};
|
||||
// Dev GC timeout tolerance. The HAL may not immediately return after the
|
||||
// timeout, so include an acceptable tolerance.
|
||||
const std::chrono::seconds kDevGcTolerance{3};
|
||||
// Time accounted for RPC calls.
|
||||
const std::chrono::milliseconds kRpcTime{1000};
|
||||
|
||||
template <typename R>
|
||||
std::string toString(std::chrono::duration<R, std::milli> time) {
|
||||
return std::to_string(time.count()) + "ms";
|
||||
}
|
||||
|
||||
/** An atomic boolean flag that indicates whether a task has finished. */
|
||||
class Flag {
|
||||
public:
|
||||
void onFinish() {
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
onFinishLocked(&lock);
|
||||
}
|
||||
template <typename R, typename P>
|
||||
bool wait(std::chrono::duration<R, P> duration) {
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
return waitLocked(&lock, duration);
|
||||
}
|
||||
|
||||
protected:
|
||||
/** Will unlock. */
|
||||
void onFinishLocked(std::unique_lock<std::mutex>* lock) {
|
||||
mFinished = true;
|
||||
lock->unlock();
|
||||
mCv.notify_all();
|
||||
}
|
||||
template <typename R, typename P>
|
||||
bool waitLocked(std::unique_lock<std::mutex>* lock, std::chrono::duration<R, P> duration) {
|
||||
mCv.wait_for(*lock, duration, [this] { return mFinished; });
|
||||
return mFinished;
|
||||
}
|
||||
|
||||
bool mFinished{false};
|
||||
std::mutex mMutex;
|
||||
std::condition_variable mCv;
|
||||
};
|
||||
|
||||
class GcCallback : public IGarbageCollectCallback, public Flag {
|
||||
public:
|
||||
public:
|
||||
Return<void> onFinish(Result result) override {
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
mResult = result;
|
||||
Flag::onFinishLocked(&lock);
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
result_ = result;
|
||||
Flag::OnFinishLocked(&lock);
|
||||
return Void();
|
||||
}
|
||||
|
||||
@@ -93,13 +52,13 @@ class GcCallback : public IGarbageCollectCallback, public Flag {
|
||||
*/
|
||||
template <typename R, typename P>
|
||||
void waitForResult(std::chrono::duration<R, P> timeout, Result expected) {
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
ASSERT_TRUE(waitLocked(&lock, timeout)) << "timeout after " << toString(timeout);
|
||||
EXPECT_EQ(expected, mResult);
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
ASSERT_TRUE(WaitLocked(&lock, timeout)) << "timeout after " << to_string(timeout);
|
||||
EXPECT_EQ(expected, result_);
|
||||
}
|
||||
|
||||
private:
|
||||
Result mResult{Result::UNKNOWN_ERROR};
|
||||
private:
|
||||
Result result_{Result::UNKNOWN_ERROR};
|
||||
};
|
||||
|
||||
class HealthStorageHidlTest : public ::testing::TestWithParam<std::string> {
|
||||
@@ -127,10 +86,10 @@ class HealthStorageHidlTest : public ::testing::TestWithParam<std::string> {
|
||||
auto pingFlag = std::make_shared<Flag>();
|
||||
std::thread([service, pingFlag] {
|
||||
service->ping();
|
||||
pingFlag->onFinish();
|
||||
pingFlag->OnFinish();
|
||||
})
|
||||
.detach();
|
||||
return pingFlag->wait(timeout);
|
||||
return pingFlag->Wait(timeout);
|
||||
}
|
||||
|
||||
sp<IStorage> fs;
|
||||
@@ -147,7 +106,7 @@ TEST_P(HealthStorageHidlTest, GcNullCallback) {
|
||||
// Hold test process because HAL can be single-threaded and doing GC.
|
||||
ASSERT_TRUE(ping(kDevGcTimeout + kDevGcTolerance + kRpcTime))
|
||||
<< "Service must be available after "
|
||||
<< toString(kDevGcTimeout + kDevGcTolerance + kRpcTime);
|
||||
<< to_string(kDevGcTimeout + kDevGcTolerance + kRpcTime);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
33
health/storage/aidl/Android.bp
Normal file
33
health/storage/aidl/Android.bp
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright (C) 2021 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.
|
||||
|
||||
aidl_interface {
|
||||
name: "android.hardware.health.storage",
|
||||
vendor_available: true,
|
||||
srcs: ["android/hardware/health/storage/*.aidl"],
|
||||
stability: "vintf",
|
||||
backend: {
|
||||
cpp: {
|
||||
enabled: false,
|
||||
},
|
||||
java: {
|
||||
enabled: false,
|
||||
},
|
||||
ndk: {
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.hardware.health.storage;
|
||||
@VintfStability
|
||||
interface IGarbageCollectCallback {
|
||||
oneway void onFinish(in android.hardware.health.storage.Result result);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.hardware.health.storage;
|
||||
@VintfStability
|
||||
interface IStorage {
|
||||
oneway void garbageCollect(in long timeoutSeconds, in android.hardware.health.storage.IGarbageCollectCallback callback);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.hardware.health.storage;
|
||||
@Backing(type="int") @VintfStability
|
||||
enum Result {
|
||||
SUCCESS = 0,
|
||||
IO_ERROR = 1,
|
||||
UNKNOWN_ERROR = 2,
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
package android.hardware.health.storage;
|
||||
|
||||
import android.hardware.health.storage.Result;
|
||||
|
||||
/**
|
||||
* Callback interface to IStorage.garbageCollect.
|
||||
*/
|
||||
@VintfStability
|
||||
interface IGarbageCollectCallback {
|
||||
/**
|
||||
* When garbage collection has finished, the implementation must
|
||||
* invoke this function to indicate the result of the garbage collection.
|
||||
*
|
||||
* @param out result Execution result. See documentation for Result for
|
||||
* details.
|
||||
*/
|
||||
oneway void onFinish(in Result result);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
package android.hardware.health.storage;
|
||||
|
||||
import android.hardware.health.storage.IGarbageCollectCallback;
|
||||
|
||||
/**
|
||||
* IStorage is an interface that provides operations on underlying storage
|
||||
* devices, including flash memory.
|
||||
*/
|
||||
@VintfStability
|
||||
interface IStorage {
|
||||
/**
|
||||
* Start garbage collection on the driver of storage devices.
|
||||
*
|
||||
* Garbage collection must be started at regular intervals when it is a good
|
||||
* time for a longer-running cleanup tasks, roughly daily.
|
||||
*
|
||||
* When garbage collection finishes or encounters an error before the
|
||||
* specified timeout, the implementation must call IGarbageCollect.finish
|
||||
* immediately with appropriate result.
|
||||
*
|
||||
* If garbage collection does not finish within the specified timeout,
|
||||
* the implementation must stop garbage collection, and must not call
|
||||
* IGarbageCollect.finish.
|
||||
*
|
||||
* @param timeoutSeconds timeout in seconds. The implementation must
|
||||
* return after the timeout is reached.
|
||||
*
|
||||
* @param callback callback interface. Callback must be null if the client
|
||||
* does not need to receive any callbacks.
|
||||
*
|
||||
*/
|
||||
oneway void garbageCollect(in long timeoutSeconds, in IGarbageCollectCallback callback);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
package android.hardware.health.storage;
|
||||
|
||||
/**
|
||||
* Status values for HAL methods.
|
||||
*/
|
||||
@VintfStability
|
||||
@Backing(type="int")
|
||||
enum Result {
|
||||
/**
|
||||
* Execution of the method is successful.
|
||||
*/
|
||||
SUCCESS = 0,
|
||||
/**
|
||||
* An IO error is encountered when the HAL communicates with the device.
|
||||
*/
|
||||
IO_ERROR,
|
||||
/**
|
||||
* An unknown error is encountered.
|
||||
*/
|
||||
UNKNOWN_ERROR,
|
||||
}
|
||||
53
health/storage/aidl/default/Android.bp
Normal file
53
health/storage/aidl/default/Android.bp
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
cc_defaults {
|
||||
name: "libhealth_storage_impl_defaults",
|
||||
vendor: true,
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
"android.hardware.health.storage-unstable-ndk_platform",
|
||||
],
|
||||
static_libs: [
|
||||
"libfstab",
|
||||
"libhealth_storage_impl_common",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libhealth_storage_default_impl",
|
||||
defaults: ["libhealth_storage_impl_defaults"],
|
||||
srcs: [
|
||||
"Storage.cpp",
|
||||
],
|
||||
visibility: [
|
||||
":__subpackages__",
|
||||
"//hardware/interfaces/tests/extension/health/storage:__subpackages__",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.health.storage-service.default",
|
||||
defaults: ["libhealth_storage_impl_defaults"],
|
||||
relative_install_path: "hw",
|
||||
init_rc: ["health-storage-default.rc"],
|
||||
vintf_fragments: ["health-storage-default.xml"],
|
||||
srcs: ["main.cpp"],
|
||||
static_libs: [
|
||||
"libhealth_storage_default_impl",
|
||||
],
|
||||
}
|
||||
54
health/storage/aidl/default/Storage.cpp
Normal file
54
health/storage/aidl/default/Storage.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 "Storage.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <health-storage-impl/common.h>
|
||||
|
||||
using ::android::hardware::health::storage::DebugDump;
|
||||
using ::android::hardware::health::storage::GarbageCollect;
|
||||
|
||||
using HResult = android::hardware::health::storage::V1_0::Result;
|
||||
using AResult = aidl::android::hardware::health::storage::Result;
|
||||
// Ensure static_cast<AResult>(any HResult) works
|
||||
static_assert(static_cast<AResult>(HResult::SUCCESS) == AResult::SUCCESS);
|
||||
static_assert(static_cast<AResult>(HResult::IO_ERROR) == AResult::IO_ERROR);
|
||||
static_assert(static_cast<AResult>(HResult::UNKNOWN_ERROR) == AResult::UNKNOWN_ERROR);
|
||||
|
||||
namespace aidl::android::hardware::health::storage {
|
||||
|
||||
ndk::ScopedAStatus Storage::garbageCollect(
|
||||
int64_t timeout_seconds, const std::shared_ptr<IGarbageCollectCallback>& callback) {
|
||||
AResult result = static_cast<AResult>(GarbageCollect(static_cast<uint64_t>(timeout_seconds)));
|
||||
if (callback != nullptr) {
|
||||
auto status = callback->onFinish(result);
|
||||
if (!status.isOk()) {
|
||||
LOG(WARNING) << "Cannot return result " << toString(result)
|
||||
<< " to callback: " << status.getDescription();
|
||||
}
|
||||
}
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
binder_status_t Storage::dump(int fd, const char**, uint32_t) {
|
||||
DebugDump(fd);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::health::storage
|
||||
30
health/storage/aidl/default/Storage.h
Normal file
30
health/storage/aidl/default/Storage.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/health/storage/BnStorage.h>
|
||||
|
||||
namespace aidl::android::hardware::health::storage {
|
||||
|
||||
class Storage : public BnStorage {
|
||||
ndk::ScopedAStatus garbageCollect(
|
||||
int64_t timeout_seconds,
|
||||
const std::shared_ptr<IGarbageCollectCallback>& callback) override;
|
||||
binder_status_t dump(int fd, const char** args, uint32_t num_args) override;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::health::storage
|
||||
7
health/storage/aidl/default/health-storage-default.rc
Normal file
7
health/storage/aidl/default/health-storage-default.rc
Normal file
@@ -0,0 +1,7 @@
|
||||
service vendor.health-storage-default /vendor/bin/hw/android.hardware.health.storage-service.default
|
||||
interface aidl android.hardware.health.storage.IStorage/default
|
||||
oneshot
|
||||
disabled
|
||||
class hal
|
||||
user system
|
||||
group system
|
||||
7
health/storage/aidl/default/health-storage-default.xml
Normal file
7
health/storage/aidl/default/health-storage-default.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<manifest version="1.0" type="device">
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.health.storage</name>
|
||||
<version>1</version>
|
||||
<fqname>IStorage/default</fqname>
|
||||
</hal>
|
||||
</manifest>
|
||||
37
health/storage/aidl/default/main.cpp
Normal file
37
health/storage/aidl/default/main.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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/logging.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
|
||||
#include "Storage.h"
|
||||
|
||||
using aidl::android::hardware::health::storage::Storage;
|
||||
using std::string_literals::operator""s;
|
||||
|
||||
int main() {
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(0);
|
||||
|
||||
// make a default storage service
|
||||
auto storage = ndk::SharedRefBase::make<Storage>();
|
||||
const std::string name = Storage::descriptor + "/default"s;
|
||||
CHECK_EQ(STATUS_OK,
|
||||
AServiceManager_registerLazyService(storage->asBinder().get(), name.c_str()));
|
||||
|
||||
ABinderProcess_joinThreadPool();
|
||||
return EXIT_FAILURE; // should not reach
|
||||
}
|
||||
37
health/storage/aidl/vts/functional/Android.bp
Normal file
37
health/storage/aidl/vts/functional/Android.bp
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2021 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.
|
||||
|
||||
cc_test {
|
||||
name: "VtsHalHealthStorageTargetTest",
|
||||
defaults: [
|
||||
"VtsHalTargetTestDefaults",
|
||||
"use_libaidlvintf_gtest_helper_static",
|
||||
],
|
||||
srcs: [
|
||||
"VtsHalHealthStorageTargetTest.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbinder_ndk",
|
||||
],
|
||||
static_libs: [
|
||||
"android.hardware.health.storage-ndk_platform",
|
||||
],
|
||||
header_libs: [
|
||||
"libhealth_storage_test_common_headers",
|
||||
],
|
||||
test_suites: [
|
||||
"vts",
|
||||
],
|
||||
test_config: "VtsHalHealthStorageTargetTest.xml",
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 <chrono>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include <aidl/Gtest.h>
|
||||
#include <aidl/Vintf.h>
|
||||
#include <aidl/android/hardware/health/storage/BnGarbageCollectCallback.h>
|
||||
#include <aidl/android/hardware/health/storage/IStorage.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android/binder_ibinder.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <health-storage-test/common.h>
|
||||
|
||||
namespace aidl::android::hardware::health::storage {
|
||||
|
||||
using namespace ::android::hardware::health::storage::test;
|
||||
using std::chrono_literals::operator""ms;
|
||||
|
||||
#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk()) << ret.getDescription()
|
||||
#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk()) << ret.getDescription()
|
||||
|
||||
class GcCallback : public BnGarbageCollectCallback, public Flag {
|
||||
public:
|
||||
ndk::ScopedAStatus onFinish(Result result) override {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
result_ = result;
|
||||
OnFinishLocked(&lock);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for a specific "timeout". If GC has finished, test that the result
|
||||
* is equal to the "expected" value.
|
||||
*/
|
||||
template <typename R, typename P>
|
||||
void WaitForResult(std::chrono::duration<R, P> timeout, Result expected) {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
ASSERT_TRUE(WaitLocked(&lock, timeout)) << "timeout after " << to_string(timeout);
|
||||
EXPECT_EQ(expected, result_);
|
||||
}
|
||||
|
||||
private:
|
||||
Result result_{Result::UNKNOWN_ERROR};
|
||||
};
|
||||
|
||||
class HealthStorageAidl : public testing::TestWithParam<std::string> {
|
||||
public:
|
||||
virtual void SetUp() override {
|
||||
std::string name = GetParam();
|
||||
ASSERT_TRUE(AServiceManager_isDeclared(name.c_str())) << name;
|
||||
ndk::SpAIBinder binder(AServiceManager_waitForService(name.c_str()));
|
||||
ASSERT_NE(binder, nullptr);
|
||||
storage_ = IStorage::fromBinder(binder);
|
||||
ASSERT_NE(storage_, nullptr);
|
||||
}
|
||||
|
||||
virtual void TearDown() override {
|
||||
EXPECT_TRUE(ping(kRpcTime))
|
||||
<< "Service is not responsive; expect subsequent tests to fail.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Ping the service and expect it to return after "timeout". Return true
|
||||
* iff the service is responsive within "timeout".
|
||||
*/
|
||||
template <typename R, typename P>
|
||||
bool ping(std::chrono::duration<R, P> timeout) {
|
||||
// Ensure the service is responsive after the test.
|
||||
std::shared_ptr<IStorage> service = storage_;
|
||||
auto ping_flag = std::make_shared<Flag>();
|
||||
std::thread([service, ping_flag] {
|
||||
EXPECT_EQ(STATUS_OK, AIBinder_ping(service->asBinder().get()));
|
||||
ping_flag->OnFinish();
|
||||
}).detach();
|
||||
return ping_flag->Wait(timeout);
|
||||
}
|
||||
|
||||
std::shared_ptr<IStorage> storage_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Ensure garbage collection works on null callback.
|
||||
*/
|
||||
TEST_P(HealthStorageAidl, GcNullCallback) {
|
||||
ASSERT_OK(storage_->garbageCollect(kDevGcTimeoutSec, nullptr));
|
||||
|
||||
// Hold test process because HAL can be single-threaded and doing GC.
|
||||
ASSERT_TRUE(ping(kDevGcTimeout + kDevGcTolerance + kRpcTime))
|
||||
<< "Service must be available after "
|
||||
<< to_string(kDevGcTimeout + kDevGcTolerance + kRpcTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure garbage collection works on non-null callback.
|
||||
*/
|
||||
TEST_P(HealthStorageAidl, GcNonNullCallback) {
|
||||
std::shared_ptr<GcCallback> cb = ndk::SharedRefBase::make<GcCallback>();
|
||||
ASSERT_OK(storage_->garbageCollect(kDevGcTimeoutSec, cb));
|
||||
cb->WaitForResult(kDevGcTimeout + kDevGcTolerance + kRpcTime, Result::SUCCESS);
|
||||
}
|
||||
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HealthStorageAidl);
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
HealthStorage, HealthStorageAidl,
|
||||
testing::ValuesIn(::android::getAidlHalInstanceNames(IStorage::descriptor)),
|
||||
::android::PrintInstanceNameToString);
|
||||
|
||||
} // namespace aidl::android::hardware::health::storage
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(1);
|
||||
ABinderProcess_startThreadPool();
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2021 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 VtsHalHealthStorageTargetTest.">
|
||||
<option name="test-suite-tag" value="apct" />
|
||||
<option name="test-suite-tag" value="apct-native" />
|
||||
|
||||
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
|
||||
</target_preparer>
|
||||
|
||||
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
|
||||
<option name="cleanup" value="true" />
|
||||
<option name="push" value="VtsHalHealthStorageTargetTest->/data/local/tmp/VtsHalHealthStorageTargetTest" />
|
||||
</target_preparer>
|
||||
|
||||
<test class="com.android.tradefed.testtype.GTest" >
|
||||
<option name="native-test-device-path" value="/data/local/tmp" />
|
||||
<option name="module-name" value="VtsHalHealthStorageTargetTest" />
|
||||
<option name="native-test-timeout" value="3m" />
|
||||
</test>
|
||||
</configuration>
|
||||
47
health/storage/impl_common/Android.bp
Normal file
47
health/storage/impl_common/Android.bp
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
// Common implementation between HIDL and AIDL HAL.
|
||||
cc_library_static {
|
||||
name: "libhealth_storage_impl_common",
|
||||
vendor: true,
|
||||
srcs: [
|
||||
"impl_common.cpp",
|
||||
],
|
||||
export_include_dirs: [
|
||||
"include",
|
||||
],
|
||||
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
],
|
||||
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libhidlbase",
|
||||
"liblog",
|
||||
"android.hardware.health.storage@1.0",
|
||||
],
|
||||
|
||||
static_libs: [
|
||||
"libfstab",
|
||||
],
|
||||
|
||||
export_shared_lib_headers: [
|
||||
"android.hardware.health.storage@1.0",
|
||||
],
|
||||
}
|
||||
118
health/storage/impl_common/impl_common.cpp
Normal file
118
health/storage/impl_common/impl_common.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 <health-storage-impl/common.h>
|
||||
|
||||
#include <android-base/chrono_utils.h>
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <fstab/fstab.h>
|
||||
|
||||
using ::android::base::ReadFileToString;
|
||||
using ::android::base::Timer;
|
||||
using ::android::base::Trim;
|
||||
using ::android::base::WriteStringToFd;
|
||||
using ::android::base::WriteStringToFile;
|
||||
using ::android::fs_mgr::Fstab;
|
||||
using ::android::fs_mgr::ReadDefaultFstab;
|
||||
using ::android::hardware::health::storage::V1_0::Result;
|
||||
|
||||
namespace android::hardware::health::storage {
|
||||
|
||||
static std::string GetGarbageCollectPath() {
|
||||
Fstab fstab;
|
||||
ReadDefaultFstab(&fstab);
|
||||
|
||||
for (const auto& entry : fstab) {
|
||||
if (!entry.sysfs_path.empty()) {
|
||||
return entry.sysfs_path + "/manual_gc";
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
Result GarbageCollect(uint64_t timeout_seconds) {
|
||||
std::string path = GetGarbageCollectPath();
|
||||
|
||||
if (path.empty()) {
|
||||
LOG(WARNING) << "Cannot find Dev GC path";
|
||||
return Result::UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
Result result = Result::SUCCESS;
|
||||
Timer timer;
|
||||
LOG(INFO) << "Start Dev GC on " << path;
|
||||
while (1) {
|
||||
std::string require;
|
||||
if (!ReadFileToString(path, &require)) {
|
||||
PLOG(WARNING) << "Reading manual_gc failed in " << path;
|
||||
result = Result::IO_ERROR;
|
||||
break;
|
||||
}
|
||||
require = Trim(require);
|
||||
if (require == "" || require == "off" || require == "disabled") {
|
||||
LOG(DEBUG) << "No more to do Dev GC";
|
||||
break;
|
||||
}
|
||||
LOG(DEBUG) << "Trigger Dev GC on " << path;
|
||||
if (!WriteStringToFile("1", path)) {
|
||||
PLOG(WARNING) << "Start Dev GC failed on " << path;
|
||||
result = Result::IO_ERROR;
|
||||
break;
|
||||
}
|
||||
if (timer.duration() >= std::chrono::seconds(timeout_seconds)) {
|
||||
LOG(WARNING) << "Dev GC timeout";
|
||||
// Timeout is not treated as an error. Try next time.
|
||||
break;
|
||||
}
|
||||
sleep(2);
|
||||
}
|
||||
LOG(INFO) << "Stop Dev GC on " << path;
|
||||
if (!WriteStringToFile("0", path)) {
|
||||
PLOG(WARNING) << "Stop Dev GC failed on " << path;
|
||||
result = Result::IO_ERROR;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void DebugDump(int fd) {
|
||||
std::stringstream output;
|
||||
|
||||
std::string path = GetGarbageCollectPath();
|
||||
if (path.empty()) {
|
||||
output << "Cannot find Dev GC path";
|
||||
} else {
|
||||
std::string require;
|
||||
|
||||
if (ReadFileToString(path, &require)) {
|
||||
output << path << ":" << require << std::endl;
|
||||
}
|
||||
|
||||
if (WriteStringToFile("0", path)) {
|
||||
output << "stop success" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WriteStringToFd(output.str(), fd)) {
|
||||
PLOG(WARNING) << "debug: cannot write to fd";
|
||||
}
|
||||
|
||||
fsync(fd);
|
||||
}
|
||||
|
||||
} // namespace android::hardware::health::storage
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <android/hardware/health/storage/1.0/types.h>
|
||||
#include <string>
|
||||
|
||||
namespace android::hardware::health::storage {
|
||||
|
||||
// Run debug on fd
|
||||
void DebugDump(int fd);
|
||||
|
||||
// Run garbage collection on GetGarbageCollectPath(). Blocks until garbage
|
||||
// collect finishes or |timeout_seconds| has reached.
|
||||
V1_0::Result GarbageCollect(uint64_t timeout_seconds);
|
||||
|
||||
} // namespace android::hardware::health::storage
|
||||
20
health/storage/test_common/Android.bp
Normal file
20
health/storage/test_common/Android.bp
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
cc_library_headers {
|
||||
name: "libhealth_storage_test_common_headers",
|
||||
export_include_dirs: ["include"],
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
|
||||
namespace android::hardware::health::storage::test {
|
||||
|
||||
// Dev GC timeout. This is the timeout used by vold.
|
||||
const uint64_t kDevGcTimeoutSec = 120;
|
||||
const std::chrono::seconds kDevGcTimeout{kDevGcTimeoutSec};
|
||||
// Dev GC timeout tolerance. The HAL may not immediately return after the
|
||||
// timeout, so include an acceptable tolerance.
|
||||
const std::chrono::seconds kDevGcTolerance{3};
|
||||
// Time accounted for RPC calls.
|
||||
const std::chrono::milliseconds kRpcTime{1000};
|
||||
|
||||
template <typename R>
|
||||
std::string to_string(std::chrono::duration<R, std::milli> time) {
|
||||
return std::to_string(time.count()) + "ms";
|
||||
}
|
||||
|
||||
/** An atomic boolean flag that indicates whether a task has finished. */
|
||||
class Flag {
|
||||
public:
|
||||
void OnFinish() {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
OnFinishLocked(&lock);
|
||||
}
|
||||
template <typename R, typename P>
|
||||
bool Wait(std::chrono::duration<R, P> duration) {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
return WaitLocked(&lock, duration);
|
||||
}
|
||||
|
||||
protected:
|
||||
/** Will unlock. */
|
||||
void OnFinishLocked(std::unique_lock<std::mutex>* lock) {
|
||||
finished_ = true;
|
||||
lock->unlock();
|
||||
cv_.notify_all();
|
||||
}
|
||||
template <typename R, typename P>
|
||||
bool WaitLocked(std::unique_lock<std::mutex>* lock, std::chrono::duration<R, P> duration) {
|
||||
cv_.wait_for(*lock, duration, [this] { return finished_; });
|
||||
return finished_;
|
||||
}
|
||||
|
||||
bool finished_{false};
|
||||
std::mutex mutex_;
|
||||
std::condition_variable cv_;
|
||||
};
|
||||
|
||||
} // namespace android::hardware::health::storage::test
|
||||
Reference in New Issue
Block a user