Merge "Revert "Add command to pass oem commands to HAL""
diff --git a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
index 9c9b749..836e150 100644
--- a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
@@ -29,6 +29,8 @@
#include <fcntl.h>
#include <unistd.h>
+#include <hwbinder/IPCThreadState.h>
+
#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
@@ -55,13 +57,14 @@
using std::list;
using ::android::sp;
-using ::android::hardware::Return;
using ::android::hardware::hidl_bitfield;
using ::android::hardware::hidl_enum_range;
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
+using ::android::hardware::IPCThreadState;
using ::android::hardware::MQDescriptorSync;
+using ::android::hardware::Return;
using ::android::hardware::audio::V4_0::AudioDrain;
using ::android::hardware::audio::V4_0::DeviceAddress;
using ::android::hardware::audio::V4_0::IDevice;
@@ -164,15 +167,25 @@
TEST_F(AudioHidlTest, OpenPrimaryDeviceUsingGetDevice) {
doc::test("Calling openDevice(\"primary\") should return the primary device.");
- Result result;
- sp<IDevice> baseDevice;
- ASSERT_OK(devicesFactory->openDevice("primary", returnIn(result, baseDevice)));
- ASSERT_OK(result);
- ASSERT_TRUE(baseDevice != nullptr);
+ {
+ Result result;
+ sp<IDevice> baseDevice;
+ ASSERT_OK(devicesFactory->openDevice("primary", returnIn(result, baseDevice)));
+ ASSERT_OK(result);
+ ASSERT_TRUE(baseDevice != nullptr);
- Return<sp<IPrimaryDevice>> primaryDevice = IPrimaryDevice::castFrom(baseDevice);
- ASSERT_TRUE(primaryDevice.isOk());
- ASSERT_TRUE(sp<IPrimaryDevice>(primaryDevice) != nullptr);
+ Return<sp<IPrimaryDevice>> primaryDevice = IPrimaryDevice::castFrom(baseDevice);
+ ASSERT_TRUE(primaryDevice.isOk());
+ ASSERT_TRUE(sp<IPrimaryDevice>(primaryDevice) != nullptr);
+ } // Destroy local IDevice proxy
+ // FIXME: there is no way to know when the remote IDevice is being destroyed
+ // Binder does not support testing if an object is alive, thus
+ // wait for 100ms to let the binder destruction propagates and
+ // the remote device has the time to be destroyed.
+ // flushCommand makes sure all local command are sent, thus should reduce
+ // the latency between local and remote destruction.
+ IPCThreadState::self()->flushCommands();
+ usleep(100);
}
//////////////////////////////////////////////////////////////////////////////
@@ -1402,6 +1415,7 @@
"Make sure setBtHfpVolume is either not supported or "
"only succeed if volume is in [0,1]");
auto ret = device->setBtHfpVolume(0.0);
+ ASSERT_TRUE(ret.isOk());
if (ret == Result::NOT_SUPPORTED) {
doc::partialTest("setBtHfpVolume is not supported");
return;
diff --git a/drm/1.0/default/DrmFactory.cpp b/drm/1.0/default/DrmFactory.cpp
index 7e5d998..05951d7 100644
--- a/drm/1.0/default/DrmFactory.cpp
+++ b/drm/1.0/default/DrmFactory.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2016 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
diff --git a/drm/1.0/default/LegacyPluginPath.cpp b/drm/1.0/default/LegacyPluginPath.cpp
index 369059d..d0a8f90 100644
--- a/drm/1.0/default/LegacyPluginPath.cpp
+++ b/drm/1.0/default/LegacyPluginPath.cpp
@@ -16,6 +16,8 @@
#include "LegacyPluginPath.h"
+#include <unistd.h>
+
#include <cutils/properties.h>
namespace android {
@@ -24,12 +26,16 @@
namespace V1_0 {
namespace implementation {
+// 64-bit DRM depends on OEM libraries that aren't
+// provided for all devices. If the drm hal service
+// is running as 64-bit use the 64-bit libs, otherwise
+// use the 32-bit libs.
const char* getDrmPluginPath() {
- if (property_get_bool("drm.64bit.enabled", false)) {
- return "/vendor/lib64/mediadrm";
- } else {
- return "/vendor/lib/mediadrm";
- }
+#if defined(__LP64__)
+ return "/vendor/lib64/mediadrm";
+#else
+ return "/vendor/lib/mediadrm";
+#endif
}
} // namespace implementation
diff --git a/drm/1.0/default/include/PluginLoader.h b/drm/1.0/default/include/PluginLoader.h
index f387b3c..0c45fb3 100644
--- a/drm/1.0/default/include/PluginLoader.h
+++ b/drm/1.0/default/include/PluginLoader.h
@@ -85,7 +85,10 @@
libraries.push(library);
T* result = createFactoryFunc();
return result;
- }
+ } else {
+ ALOGE("Failed to lookup symbol %s in library %s: %s",
+ entry, path, library->lastError());
+ }
}
return NULL;
}
diff --git a/health/filesystem/1.0/Android.bp b/health/storage/1.0/Android.bp
similarity index 72%
rename from health/filesystem/1.0/Android.bp
rename to health/storage/1.0/Android.bp
index 74b9bc3..35ee34f 100644
--- a/health/filesystem/1.0/Android.bp
+++ b/health/storage/1.0/Android.bp
@@ -1,14 +1,15 @@
// This file is autogenerated by hidl-gen -Landroidbp.
hidl_interface {
- name: "android.hardware.health.filesystem@1.0",
+ name: "android.hardware.health.storage@1.0",
root: "android.hardware",
vndk: {
enabled: true,
},
srcs: [
"types.hal",
- "IFileSystem.hal",
+ "IGarbageCollectCallback.hal",
+ "IStorage.hal",
],
interfaces: [
"android.hidl.base@1.0",
diff --git a/health/filesystem/1.0/IFileSystem.hal b/health/storage/1.0/IGarbageCollectCallback.hal
similarity index 63%
rename from health/filesystem/1.0/IFileSystem.hal
rename to health/storage/1.0/IGarbageCollectCallback.hal
index 33ea3ff..2c24ead 100644
--- a/health/filesystem/1.0/IFileSystem.hal
+++ b/health/storage/1.0/IGarbageCollectCallback.hal
@@ -13,21 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-package android.hardware.health.filesystem@1.0;
+package android.hardware.health.storage@1.0;
/**
- * IFileSystem is an interface that provides operations on underlying storage
- * devices, including flash memory.
+ * Callback interface to IStorage.garbageCollect.
*/
-interface IFileSystem {
+interface IGarbageCollectCallback {
/**
- * Start garbage collection on the driver of storage devices. This function
- * must be called at regular intervals when it is a good time for a
- * longer-running cleanup tasks.
+ * When garbage collection has finished, the implementation must
+ * invoke this function to indicate the result of the garbage collection.
*
* @return result Execution result. See documentation for Result for
* details.
*/
- garbageCollect() generates (Result result);
+ oneway onFinish(Result result);
};
diff --git a/health/storage/1.0/IStorage.hal b/health/storage/1.0/IStorage.hal
new file mode 100644
index 0000000..980cf45
--- /dev/null
+++ b/health/storage/1.0/IStorage.hal
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 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@1.0;
+
+import IGarbageCollectCallback;
+
+/**
+ * IStorage is an interface that provides operations on underlying storage
+ * devices, including flash memory.
+ */
+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 garbageCollect(uint64_t timeoutSeconds,
+ IGarbageCollectCallback callback);
+};
diff --git a/health/storage/1.0/default/Android.bp b/health/storage/1.0/default/Android.bp
new file mode 100644
index 0000000..4723443
--- /dev/null
+++ b/health/storage/1.0/default/Android.bp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 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_binary {
+ name: "android.hardware.health.storage@1.0-service",
+ vendor: true,
+ defaults: ["hidl_defaults"],
+ relative_install_path: "hw",
+ init_rc: ["android.hardware.health.storage@1.0-service.rc"],
+ srcs: [
+ "Storage.cpp",
+ "service.cpp",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libhidlbase",
+ "libhidltransport",
+ "libutils",
+ "android.hardware.health.storage@1.0",
+ ],
+
+ static_libs: [
+ "libfstab",
+ ],
+
+ vintf_fragments: [
+ "manifest_android.hardware.health.storage@1.0.xml",
+ ],
+}
diff --git a/health/storage/1.0/default/Storage.cpp b/health/storage/1.0/default/Storage.cpp
new file mode 100644
index 0000000..2e53c50
--- /dev/null
+++ b/health/storage/1.0/default/Storage.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2018 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/chrono_utils.h>
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <fstab/fstab.h>
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace storage {
+namespace V1_0 {
+namespace implementation {
+
+using base::ReadFileToString;
+using base::Timer;
+using base::Trim;
+using base::WriteStringToFd;
+using base::WriteStringToFile;
+
+std::string getGarbageCollectPath() {
+ std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
+ fs_mgr_free_fstab);
+ struct fstab_rec* rec = NULL;
+
+ for (int i = 0; i < fstab->num_entries; i++) {
+ if (fs_mgr_has_sysfs_path(&fstab->recs[i])) {
+ rec = &fstab->recs[i];
+ break;
+ }
+ }
+ if (!rec) {
+ return "";
+ }
+
+ std::string path;
+ path.append(rec->sysfs_path);
+ path = path + "/manual_gc";
+
+ return path;
+}
+
+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;
+ }
+ }
+
+ if (cb != nullptr) {
+ auto ret = cb->onFinish(result);
+ if (!ret.isOk()) {
+ LOG(WARNING) << "Cannot return result to callback: " << ret.description();
+ }
+ }
+ return Void();
+}
+
+Return<void> Storage::debug(const hidl_handle& handle, const hidl_vec<hidl_string>&) {
+ if (handle == nullptr || handle->numFds < 1) {
+ return Void();
+ }
+
+ 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);
+
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace storage
+} // namespace health
+} // namespace hardware
+} // namespace android
diff --git a/health/storage/1.0/default/Storage.h b/health/storage/1.0/default/Storage.h
new file mode 100644
index 0000000..8c57ddb
--- /dev/null
+++ b/health/storage/1.0/default/Storage.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 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 ANDROID_HARDWARE_HEALTH_FILESYSTEM_V1_0_FILESYSTEM_H
+#define ANDROID_HARDWARE_HEALTH_FILESYSTEM_V1_0_FILESYSTEM_H
+
+#include <android/hardware/health/storage/1.0/IStorage.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace storage {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+
+struct Storage : public IStorage {
+ Return<void> garbageCollect(uint64_t timeoutSeconds,
+ const sp<IGarbageCollectCallback>& cb) override;
+ Return<void> debug(const hidl_handle& handle, const hidl_vec<hidl_string>&) override;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace storage
+} // namespace health
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_HEALTH_FILESYSTEM_V1_0_FILESYSTEM_H
diff --git a/health/storage/1.0/default/android.hardware.health.storage@1.0-service.rc b/health/storage/1.0/default/android.hardware.health.storage@1.0-service.rc
new file mode 100644
index 0000000..c6a1425
--- /dev/null
+++ b/health/storage/1.0/default/android.hardware.health.storage@1.0-service.rc
@@ -0,0 +1,5 @@
+service vendor.health-storage-hal-1-0 /vendor/bin/hw/android.hardware.health.storage@1.0-service
+ interface android.hardware.health.storage@1.0::IStorage default
+ class hal
+ user system
+ group system
diff --git a/health/storage/1.0/default/manifest_android.hardware.health.storage@1.0.xml b/health/storage/1.0/default/manifest_android.hardware.health.storage@1.0.xml
new file mode 100644
index 0000000..ffe854e
--- /dev/null
+++ b/health/storage/1.0/default/manifest_android.hardware.health.storage@1.0.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+ <hal>
+ <name>android.hardware.health.storage</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IStorage</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/health/storage/1.0/default/service.cpp b/health/storage/1.0/default/service.cpp
new file mode 100644
index 0000000..a945033
--- /dev/null
+++ b/health/storage/1.0/default/service.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2018 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 <hidl/HidlTransportSupport.h>
+#include "Storage.h"
+
+using android::OK;
+using android::sp;
+using android::status_t;
+using android::UNKNOWN_ERROR;
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::health::storage::V1_0::IStorage;
+using android::hardware::health::storage::V1_0::implementation::Storage;
+
+int main() {
+ configureRpcThreadpool(1, true);
+
+ sp<IStorage> service = new Storage();
+ status_t result = service->registerAsService();
+
+ if (result != OK) {
+ return result;
+ }
+
+ joinRpcThreadpool();
+ return UNKNOWN_ERROR;
+}
diff --git a/health/filesystem/1.0/types.hal b/health/storage/1.0/types.hal
similarity index 88%
rename from health/filesystem/1.0/types.hal
rename to health/storage/1.0/types.hal
index 00431f7..2da0871 100644
--- a/health/filesystem/1.0/types.hal
+++ b/health/storage/1.0/types.hal
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.hardware.health.filesystem@1.0;
+package android.hardware.health.storage@1.0;
/**
* Status values for HAL methods.
@@ -25,10 +25,6 @@
*/
SUCCESS = 0,
/**
- * Execution of the method timed out.
- */
- TIMEOUT,
- /**
* An IO error is encountered when the HAL communicates with the device.
*/
IO_ERROR,
diff --git a/health/storage/1.0/vts/functional/Android.bp b/health/storage/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..63591cf
--- /dev/null
+++ b/health/storage/1.0/vts/functional/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2018 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: "VtsHalHealthStorageV1_0TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: ["VtsHalHealthStorageV1_0TargetTest.cpp"],
+ static_libs: ["android.hardware.health.storage@1.0"],
+ shared_libs: [
+ "libhidltransport"
+ ],
+}
+
diff --git a/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp b/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp
new file mode 100644
index 0000000..5ad561c
--- /dev/null
+++ b/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2018 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 <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/health/storage/1.0/IStorage.h>
+#include <hidl/HidlTransportSupport.h>
+#include <unistd.h>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace storage {
+namespace V1_0 {
+
+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};
+// Time accounted for RPC calls.
+const std::chrono::milliseconds kRpcTime{100};
+
+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:
+ Return<void> onFinish(Result result) override {
+ std::unique_lock<std::mutex> lock(mMutex);
+ mResult = result;
+ Flag::onFinishLocked(&lock);
+ return Void();
+ }
+
+ /**
+ * 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(mMutex);
+ if (waitLocked(&lock, timeout)) {
+ EXPECT_EQ(expected, mResult);
+ } else {
+ LOG(INFO) << "timeout after " << toString(timeout);
+ }
+ }
+
+ private:
+ Result mResult{Result::UNKNOWN_ERROR};
+};
+
+/** Test environment for Health Storage HIDL HAL. */
+class HealthStorageHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+ public:
+ /** get the test environment singleton */
+ static HealthStorageHidlEnvironment* Instance() {
+ static HealthStorageHidlEnvironment* instance = new HealthStorageHidlEnvironment();
+ return instance;
+ }
+ virtual void registerTestServices() override { registerTestService<IStorage>(); }
+
+ private:
+ HealthStorageHidlEnvironment() {}
+};
+
+class HealthStorageHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+ virtual void SetUp() override {
+ fs = ::testing::VtsHalHidlTargetTestBase::getService<IStorage>(
+ HealthStorageHidlEnvironment::Instance()->getServiceName<IStorage>());
+
+ ASSERT_NE(fs, nullptr);
+ LOG(INFO) << "Service is remote " << fs->isRemote();
+ }
+
+ 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.
+ sp<IStorage> service = fs;
+ auto pingFlag = std::make_shared<Flag>();
+ std::thread([service, pingFlag] {
+ service->ping();
+ pingFlag->onFinish();
+ })
+ .detach();
+ return pingFlag->wait(timeout);
+ }
+
+ sp<IStorage> fs;
+};
+
+/**
+ * Ensure garbage collection works on null callback.
+ */
+TEST_F(HealthStorageHidlTest, GcNullCallback) {
+ auto ret = fs->garbageCollect(kDevGcTimeoutSec, nullptr);
+
+ ASSERT_OK(ret);
+
+ // Hold test process because HAL can be single-threaded and doing GC.
+ ASSERT_TRUE(ping(kDevGcTimeout + kRpcTime))
+ << "Service must be available after " << toString(kDevGcTimeout + kRpcTime);
+}
+
+/**
+ * Ensure garbage collection works on non-null callback.
+ */
+TEST_F(HealthStorageHidlTest, GcNonNullCallback) {
+ sp<GcCallback> cb = new GcCallback();
+ auto ret = fs->garbageCollect(kDevGcTimeoutSec, cb);
+ ASSERT_OK(ret);
+ cb->waitForResult(kDevGcTimeout + kRpcTime, Result::SUCCESS);
+}
+
+} // namespace V1_0
+} // namespace storage
+} // namespace health
+} // namespace hardware
+} // namespace android
+
+int main(int argc, char** argv) {
+ using ::android::hardware::configureRpcThreadpool;
+ using ::android::hardware::health::storage::V1_0::HealthStorageHidlEnvironment;
+
+ configureRpcThreadpool(1, false /* callerWillJoin*/);
+ ::testing::AddGlobalTestEnvironment(HealthStorageHidlEnvironment::Instance());
+ ::testing::InitGoogleTest(&argc, argv);
+ HealthStorageHidlEnvironment::Instance()->init(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ LOG(INFO) << "Test result = " << status;
+ return status;
+}
diff --git a/radio/1.3/Android.bp b/radio/1.3/Android.bp
index 042df6c..5ac38cd 100644
--- a/radio/1.3/Android.bp
+++ b/radio/1.3/Android.bp
@@ -20,8 +20,10 @@
],
types: [
"AccessNetwork",
+ "DataRegStateResult",
"EmergencyNumber",
"EmergencyServiceCategory",
+ "LteVopsInfo",
],
gen_java: true,
}
diff --git a/radio/1.3/IRadioResponse.hal b/radio/1.3/IRadioResponse.hal
index 6912d0a..3604953 100644
--- a/radio/1.3/IRadioResponse.hal
+++ b/radio/1.3/IRadioResponse.hal
@@ -71,4 +71,18 @@
* RadioError:CANCELLED
*/
oneway emergencyDialResponse(RadioResponseInfo info);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param dataRegResponse Current Data registration response as defined by DataRegStateResult in
+ * types.hal
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ * RadioError:NOT_PROVISIONED
+ */
+ oneway getDataRegistrationStateResponse_1_3(RadioResponseInfo info,
+ DataRegStateResult dataRegResponse);
};
diff --git a/radio/1.3/types.hal b/radio/1.3/types.hal
index c04451f..d472ca7 100644
--- a/radio/1.3/types.hal
+++ b/radio/1.3/types.hal
@@ -16,7 +16,10 @@
package android.hardware.radio@1.3;
+import @1.0::RegState;
import @1.2::AccessNetwork;
+import @1.2::CellIdentity;
+import @1.2::DataRegStateResult;
enum AccessNetwork : @1.2::AccessNetwork {
/**
@@ -81,3 +84,39 @@
MIEC = 1 << 5, // Manually Initiated eCall (MIeC)
AIEC = 1 << 6, // Automatically Initiated eCall (AIeC)
};
+
+/**
+ * Type to define the LTE specific network capabilities for voice over PS including
+ * emergency and normal voice calls.
+ */
+struct LteVopsInfo {
+ /**
+ * This indicates if camped network support VoLTE services. This information is received
+ * from LTE network during LTE NAS registration procedure through LTE ATTACH ACCEPT/TAU
+ * ACCEPT. Refer 3GPP 24.301 EPS network feature support -> IMS VoPS
+ */
+ bool isVopsSupported;
+ /**
+ * This indicates if camped network support VoLTE emergency bearers. This information
+ * is received from LTE network through two sources:
+ * a. During LTE NAS registration procedure through LTE ATTACH ACCEPT/TAU ACCEPT. Refer
+ * 3GPP 24.301 EPS network feature support -> EMC BS
+ * b. In case device is not registered on network. Refer 3GPP 25.331 LTE RRC
+ * SIB1 : ims-EmergencySupport-r9
+ * If device is registered on LTE, then this field indicates (a).
+ * In case of limited service on LTE this field indicates (b).
+ */
+ bool isEmcBearerSupported;
+};
+
+struct DataRegStateResult {
+ @1.2::DataRegStateResult base;
+ /**
+ * Network capabilities for voice over PS services. This info is valid only
+ * on LTE network and must be present when device is camped on LTE. vopsInfo
+ * will be empty when device is camped only on 2G/3G .
+ */
+ safe_union VopsInfo {
+ LteVopsInfo lteVopsInfo; // LTE network capability
+ } vopsInfo;
+};
diff --git a/tests/safeunion/1.0/ISafeUnion.hal b/tests/safeunion/1.0/ISafeUnion.hal
index c38777a..f48248b 100644
--- a/tests/safeunion/1.0/ISafeUnion.hal
+++ b/tests/safeunion/1.0/ISafeUnion.hal
@@ -60,6 +60,9 @@
} k;
SmallSafeUnion l;
+
+ BitField m;
+ bitfield<BitField> n;
};
safe_union InterfaceTypeSafeUnion {
@@ -91,6 +94,8 @@
setJ(LargeSafeUnion myUnion, J j) generates (LargeSafeUnion myUnion);
setK(LargeSafeUnion myUnion, LargeSafeUnion.K k) generates (LargeSafeUnion myUnion);
setL(LargeSafeUnion myUnion, SmallSafeUnion l) generates (LargeSafeUnion myUnion);
+ setM(LargeSafeUnion myUnion, BitField m) generates (LargeSafeUnion myUnion);
+ setN(LargeSafeUnion myUnion, bitfield<BitField> m) generates (LargeSafeUnion myUnion);
newInterfaceTypeSafeUnion() generates (InterfaceTypeSafeUnion myUnion);
setInterfaceA(InterfaceTypeSafeUnion myUnion, uint32_t a) generates (InterfaceTypeSafeUnion myUnion);
diff --git a/tests/safeunion/1.0/default/SafeUnion.cpp b/tests/safeunion/1.0/default/SafeUnion.cpp
index c395664..4fb0974 100644
--- a/tests/safeunion/1.0/default/SafeUnion.cpp
+++ b/tests/safeunion/1.0/default/SafeUnion.cpp
@@ -153,6 +153,27 @@
return Void();
}
+Return<void> SafeUnion::setM(const LargeSafeUnion& myUnion, BitField m, setL_cb _hidl_cb) {
+ LOG(INFO) << "SERVER(SafeUnion) setM(myUnion, " << toString(m) << ")";
+
+ LargeSafeUnion myNewUnion = myUnion;
+ myNewUnion.m(m);
+
+ _hidl_cb(myNewUnion);
+ return Void();
+}
+
+Return<void> SafeUnion::setN(const LargeSafeUnion& myUnion, hidl_bitfield<BitField> n,
+ setL_cb _hidl_cb) {
+ LOG(INFO) << "SERVER(SafeUnion) setN(myUnion, " << n << ")";
+
+ LargeSafeUnion myNewUnion = myUnion;
+ myNewUnion.n(n);
+
+ _hidl_cb(myNewUnion);
+ return Void();
+}
+
Return<void> SafeUnion::newInterfaceTypeSafeUnion(newInterfaceTypeSafeUnion_cb _hidl_cb) {
LOG(INFO) << "SERVER(SafeUnion) newInterfaceTypeSafeUnion()";
diff --git a/tests/safeunion/1.0/default/SafeUnion.h b/tests/safeunion/1.0/default/SafeUnion.h
index e774e09..ee3a954 100644
--- a/tests/safeunion/1.0/default/SafeUnion.h
+++ b/tests/safeunion/1.0/default/SafeUnion.h
@@ -47,6 +47,9 @@
Return<void> setJ(const LargeSafeUnion& myUnion, const J& j, setJ_cb _hidl_cb) override;
Return<void> setK(const LargeSafeUnion& myUnion, const LargeSafeUnion::K& k, setK_cb _hidl_cb) override;
Return<void> setL(const LargeSafeUnion& myUnion, const SmallSafeUnion& l, setL_cb _hidl_cb) override;
+ Return<void> setM(const LargeSafeUnion& myUnion, BitField m, setL_cb _hidl_cb) override;
+ Return<void> setN(const LargeSafeUnion& myUnion, hidl_bitfield<BitField> n,
+ setL_cb _hidl_cb) override;
Return<void> newInterfaceTypeSafeUnion(newInterfaceTypeSafeUnion_cb _hidl_cb) override;
Return<void> setInterfaceA(const InterfaceTypeSafeUnion& myUnion, uint32_t a, setInterfaceA_cb _hidl_cb) override;