Merge "Add OWNERS for broadcast radio HAL 1.1." into oc-mr1-dev
diff --git a/broadcastradio/1.1/types.hal b/broadcastradio/1.1/types.hal
index 3e616c8..8b8fc6f 100644
--- a/broadcastradio/1.1/types.hal
+++ b/broadcastradio/1.1/types.hal
@@ -128,11 +128,14 @@
/**
* Type of a radio technology.
*
+ * VENDOR program types must be opaque to the framework.
+ *
* There are multiple VENDOR program types just to make vendor implementation
* easier with multiple properitary radio technologies. They are treated the
* same by the framework.
*
* All other values are reserved for future use.
+ * Values not matching any enumerated constant must be ignored.
*/
enum ProgramType : uint32_t {
AM = 1, // analogue AM radio (with or without RDS)
@@ -142,10 +145,10 @@
DAB, // Digital audio broadcasting
DRMO, // Digital Radio Mondiale
SXM, // SiriusXM Satellite Radio
- VENDOR1, // Vendor-specific, not synced across devices.
- VENDOR2, // Vendor-specific, not synced across devices.
- VENDOR3, // Vendor-specific, not synced across devices.
- VENDOR4, // Vendor-specific, not synced across devices.
+
+ // Vendor-specific, not synced across devices.
+ VENDOR_START = 1000,
+ VENDOR_END = 1999,
};
/**
@@ -155,10 +158,13 @@
* it for secondary IDs. For example, a satellite program may set AM/FM fallback
* frequency, if a station broadcasts both via satellite and AM/FM.
*
+ * VENDOR identifier types must be opaque to the framework.
+ *
* The value format for each (but VENDOR_PRIMARY) identifier is strictly defined
* to maintain interoperability between devices made by different vendors.
*
* All other values are reserved for future use.
+ * Values not matching any enumerated constant must be ignored.
*/
enum IdentifierType : uint32_t {
AMFM_FREQUENCY = 1, // kHz
@@ -208,12 +214,12 @@
* Primary identifier for vendor-specific radio technology.
* The value format is determined by a vendor.
*
- * It must not be used in any other programType than VENDORx.
+ * It must not be used in any other programType than corresponding VENDOR
+ * type between VENDOR_START and VENDOR_END (eg. identifier type 1015 must
+ * not be used in any program type other than 1015).
*/
- VENDOR1_PRIMARY,
- VENDOR2_PRIMARY,
- VENDOR3_PRIMARY,
- VENDOR4_PRIMARY,
+ VENDOR_PRIMARY_START = ProgramType:VENDOR_START,
+ VENDOR_PRIMARY_END = ProgramType:VENDOR_END,
};
/**
diff --git a/broadcastradio/1.1/utils/Utils.cpp b/broadcastradio/1.1/utils/Utils.cpp
index 50a407c..8ccd98e 100644
--- a/broadcastradio/1.1/utils/Utils.cpp
+++ b/broadcastradio/1.1/utils/Utils.cpp
@@ -93,11 +93,7 @@
return haveEqualIds(a, b, IdentifierType::SXM_SERVICE_ID);
}
return haveEqualIds(a, b, IdentifierType::SXM_CHANNEL);
- case ProgramType::VENDOR1:
- case ProgramType::VENDOR2:
- case ProgramType::VENDOR3:
- case ProgramType::VENDOR4:
- default:
+ default: // includes all vendor types
ALOGW("Unsupported program type: %s", toString(type).c_str());
return false;
}
diff --git a/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp b/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
index 55abe9b..a46378e 100644
--- a/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
+++ b/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
@@ -69,10 +69,6 @@
ProgramType::AM, ProgramType::FM, ProgramType::AM_HD, ProgramType::FM_HD,
ProgramType::DAB, ProgramType::DRMO, ProgramType::SXM};
-static constexpr IdentifierType kVendorPrimartIds[] = {
- IdentifierType::VENDOR1_PRIMARY, IdentifierType::VENDOR2_PRIMARY,
- IdentifierType::VENDOR3_PRIMARY, IdentifierType::VENDOR4_PRIMARY};
-
static void printSkipped(std::string msg) {
std::cout << "[ SKIPPED ] " << msg << std::endl;
}
@@ -382,15 +378,12 @@
for (auto ptype : kStandardProgramTypes) {
ALOGD("Checking %s...", toString(ptype).c_str());
- for (auto idtype : kVendorPrimartIds) {
- ALOGD("...with %s", toString(idtype).c_str());
- ProgramSelector sel = {};
- sel.programType = static_cast<uint32_t>(ptype);
- sel.primaryId.type = static_cast<uint32_t>(idtype);
+ ProgramSelector sel = {};
+ sel.programType = static_cast<uint32_t>(ptype);
+ sel.primaryId.type = static_cast<uint32_t>(IdentifierType::VENDOR_PRIMARY_START);
- auto tuneResult = mTuner->tuneByProgramSelector(sel);
- ASSERT_NE(Result::OK, tuneResult);
- }
+ auto tuneResult = mTuner->tuneByProgramSelector(sel);
+ ASSERT_NE(Result::OK, tuneResult);
}
}
diff --git a/current.txt b/current.txt
index 2017df5..bb5f2ac 100644
--- a/current.txt
+++ b/current.txt
@@ -193,6 +193,7 @@
dc7e6d4f537b9943e27edc4f86c5a03bb643b18f18f866f8c3c71c0ac4ea8cbc android.hardware.broadcastradio@1.0::types
760485232f6cce07f8bb05e3475509956996b702f77415ee5bff05e2ec5a5bcc android.hardware.dumpstate@1.0::IDumpstateDevice
e822cb7f4a1bdd45689c5e92ccd19a2201c20b771bd4b2ec1ae627e324591f9d android.hardware.radio@1.0::IRadioResponse
+6e69adb24d7c0b0ca3a54a38c49a5625b161b3f5d5f7d6fda0befdbbfc8e9e06 android.hardware.radio@1.0::IRadioResponse
28e929b453df3d9f5060af2764e6cdb123ddb893e3e86923c877f6ff7e5f02c9 android.hardware.wifi@1.0::types
# HALs released in Android O MR1
diff --git a/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp b/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp
index eeee3c0..5564513 100644
--- a/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp
+++ b/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp
@@ -1064,8 +1064,6 @@
AES_set_encrypt_key(&key[0], 128, &decryptionKey);
size_t offset = 0;
- size_t num = 0;
- size_t ecount_buf = 0;
for (size_t i = 0; i < subSamples.size(); i++) {
memcpy(dest + offset, src + offset, subSamples[i].numBytesOfClearData);
offset += subSamples[i].numBytesOfClearData;
@@ -1106,7 +1104,6 @@
Status status = cryptoPlugin->setMediaDrmSession(sessionId);
EXPECT_EQ(Status::OK, status);
- const bool kNotSecure = false;
uint32_t byteCount = decrypt(Mode::UNENCRYPTED, &iv[0], subSamples,
noPattern, Status::OK);
EXPECT_EQ(kByteCount, byteCount);
@@ -1133,7 +1130,6 @@
Status status = cryptoPlugin->setMediaDrmSession(sessionId);
EXPECT_EQ(Status::OK, status);
- const bool kNotSecure = false;
uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples,
noPattern, Status::OK);
EXPECT_EQ(kClearBytes + kEncryptedBytes, byteCount);
@@ -1154,7 +1150,6 @@
Status status = cryptoPlugin->setMediaDrmSession(sessionId);
EXPECT_EQ(Status::OK, status);
- const bool kNotSecure = false;
uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples,
noPattern, Status::ERROR_DRM_NO_LICENSE);
EXPECT_EQ(0u, byteCount);
diff --git a/drm/1.0/vts/functional/drm_hal_vendor_test.cpp b/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
index 6ce465f..61f3014 100644
--- a/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
+++ b/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
@@ -1406,8 +1406,6 @@
AES_set_encrypt_key(&key[0], 128, &decryptionKey);
size_t offset = 0;
- size_t num = 0;
- size_t ecount_buf = 0;
for (size_t i = 0; i < subSamples.size(); i++) {
const SubSample& subSample = subSamples[i];
diff --git a/graphics/composer/2.1/default/Hwc.cpp b/graphics/composer/2.1/default/Hwc.cpp
index 8ca0eb3..862dff1 100644
--- a/graphics/composer/2.1/default/Hwc.cpp
+++ b/graphics/composer/2.1/default/Hwc.cpp
@@ -18,6 +18,7 @@
#include "Hwc.h"
+#include <chrono>
#include <type_traits>
#include <log/log.h>
@@ -25,6 +26,8 @@
#include "hardware/hwcomposer.h"
#include "hwc2on1adapter/HWC2On1Adapter.h"
+using namespace std::chrono_literals;
+
namespace android {
namespace hardware {
namespace graphics {
@@ -218,7 +221,24 @@
sp<ComposerClient> client;
{
- std::lock_guard<std::mutex> lock(mClientMutex);
+ std::unique_lock<std::mutex> lock(mClientMutex);
+
+ if (mClient != nullptr) {
+ // In surface flinger we delete a composer client on one thread and
+ // then create a new client on another thread. Although surface
+ // flinger ensures the calls are made in that sequence (destroy and
+ // then create), sometimes the calls land in the composer service
+ // inverted (create and then destroy). Wait for a brief period to
+ // see if the existing client is destroyed.
+ ALOGI("HwcHal::createClient: Client already exists. Waiting for"
+ " it to be destroyed.");
+ mClientDestroyedWait.wait_for(lock, 1s,
+ [this] { return mClient == nullptr; });
+ std::string doneMsg = mClient == nullptr ?
+ "Existing client was destroyed." :
+ "Existing client was never destroyed!";
+ ALOGI("HwcHal::createClient: Done waiting. %s", doneMsg.c_str());
+ }
// only one client is allowed
if (mClient == nullptr) {
@@ -245,6 +265,7 @@
{
std::lock_guard<std::mutex> lock(mClientMutex);
mClient = nullptr;
+ mClientDestroyedWait.notify_all();
}
void HwcHal::hotplugHook(hwc2_callback_data_t callbackData,
diff --git a/graphics/composer/2.1/default/Hwc.h b/graphics/composer/2.1/default/Hwc.h
index b45389a..7561327 100644
--- a/graphics/composer/2.1/default/Hwc.h
+++ b/graphics/composer/2.1/default/Hwc.h
@@ -17,8 +17,9 @@
#ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
-#include <mutex>
+#include <condition_variable>
#include <memory>
+#include <mutex>
#include <unordered_set>
#include <vector>
@@ -211,6 +212,7 @@
} mDispatch;
std::mutex mClientMutex;
+ std::condition_variable mClientDestroyedWait;
wp<ComposerClient> mClient;
// If the HWC implementation version is < 2.0, use an adapter to interface
diff --git a/radio/1.0/IRadioResponse.hal b/radio/1.0/IRadioResponse.hal
index a94aac3..94b304a 100644
--- a/radio/1.0/IRadioResponse.hal
+++ b/radio/1.0/IRadioResponse.hal
@@ -161,6 +161,7 @@
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:SIM_ABSENT
*/
oneway supplyNetworkDepersonalizationResponse(RadioResponseInfo info, int32_t remainingRetries);
@@ -544,6 +545,7 @@
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
*/
oneway sendSmsResponse(RadioResponseInfo info, SendSmsResult sms);
@@ -574,6 +576,7 @@
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
*/
oneway sendSMSExpectMoreResponse(RadioResponseInfo info, SendSmsResult sms);
@@ -594,6 +597,7 @@
* RadioError:NO_MEMORY
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
*/
oneway setupDataCallResponse(RadioResponseInfo info, SetupDataCallResult dcResponse);
@@ -860,6 +864,7 @@
* RadioError:NO_MEMORY
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
*/
oneway deactivateDataCallResponse(RadioResponseInfo info);
@@ -1166,6 +1171,7 @@
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:SIM_ABSENT
*/
oneway getDataCallListResponse(RadioResponseInfo info, vec<SetupDataCallResult> dcResponse);
@@ -1210,6 +1216,7 @@
* RadioError:REQUEST_NOT_SUPPORTED
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
+ * RadioError:SIM_ABSENT
*/
oneway writeSmsToSimResponse(RadioResponseInfo info, int32_t index);
@@ -1231,6 +1238,7 @@
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
+ * RadioError:SIM_ABSENT
*/
oneway deleteSmsOnSimResponse(RadioResponseInfo info);
@@ -1615,6 +1623,7 @@
* RadioError:ENCODING_ERR
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
*/
oneway sendCdmaSmsResponse(RadioResponseInfo info, SendSmsResult sms);
@@ -1819,6 +1828,7 @@
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
+ * RadioError:SIM_ABSENT
*/
oneway writeSmsToRuimResponse(RadioResponseInfo info, uint32_t index);
@@ -1839,6 +1849,8 @@
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
+ * RadioError:OPERATION_NOT_ALLOWED
+ * RadioError:SIM_ABSENT
*/
oneway deleteSmsOnRuimResponse(RadioResponseInfo info);
@@ -1906,6 +1918,7 @@
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
*/
oneway getSmscAddressResponse(RadioResponseInfo info, string smsc);
@@ -1927,6 +1940,7 @@
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
*/
oneway setSmscAddressResponse(RadioResponseInfo info);
@@ -1946,6 +1960,7 @@
* RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
*/
oneway reportSmsMemoryStatusResponse(RadioResponseInfo info);
@@ -2024,6 +2039,7 @@
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:SIM_ABSENT
*/
oneway sendEnvelopeWithStatusResponse(RadioResponseInfo info, IccIoResult iccIo);
@@ -2328,6 +2344,7 @@
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:SIM_ABSENT
*/
oneway setDataProfileResponse(RadioResponseInfo info);
@@ -2414,6 +2431,7 @@
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:SIM_ABSENT
*/
oneway stopLceServiceResponse(RadioResponseInfo info, LceStatusInfo statusInfo);
@@ -2430,6 +2448,7 @@
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:SIM_ABSENT
*/
oneway pullLceDataResponse(RadioResponseInfo info, LceDataInfo lceInfo);
diff --git a/tetheroffload/Android.bp b/tetheroffload/Android.bp
index 4b50f11..f3c7021 100644
--- a/tetheroffload/Android.bp
+++ b/tetheroffload/Android.bp
@@ -1,5 +1,7 @@
// This is an autogenerated file, do not edit.
subdirs = [
"config/1.0",
+ "config/1.0/vts/functional",
"control/1.0",
+ "control/1.0/vts/functional",
]
diff --git a/tetheroffload/config/1.0/vts/functional/Android.bp b/tetheroffload/config/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..2e720c6
--- /dev/null
+++ b/tetheroffload/config/1.0/vts/functional/Android.bp
@@ -0,0 +1,33 @@
+// 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.
+
+cc_test {
+ name: "VtsHalTetheroffloadConfigV1_0TargetTest",
+ defaults: ["hidl_defaults"],
+ srcs: ["VtsHalTetheroffloadConfigV1_0TargetTest.cpp"],
+ shared_libs: [
+ "android.hardware.tetheroffload.config@1.0",
+ "libbase",
+ "libcutils",
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+ "libutils",
+ ],
+ static_libs: ["VtsHalHidlTargetTestBase"],
+ cflags: [
+ "-O0",
+ "-g",
+ ],
+}
diff --git a/tetheroffload/config/1.0/vts/functional/VtsHalTetheroffloadConfigV1_0TargetTest.cpp b/tetheroffload/config/1.0/vts/functional/VtsHalTetheroffloadConfigV1_0TargetTest.cpp
new file mode 100644
index 0000000..fc61e1c
--- /dev/null
+++ b/tetheroffload/config/1.0/vts/functional/VtsHalTetheroffloadConfigV1_0TargetTest.cpp
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "VtsOffloadConfigV1_0TargetTest"
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <android/hardware/tetheroffload/config/1.0/IOffloadConfig.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <log/log.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <set>
+
+using android::base::StringPrintf;
+using android::base::unique_fd;
+using android::hardware::hidl_handle;
+using android::hardware::hidl_string;
+using android::hardware::Return;
+using android::hardware::tetheroffload::config::V1_0::IOffloadConfig;
+using android::hardware::Void;
+using android::sp;
+
+#define ASSERT_TRUE_CALLBACK \
+ [&](bool success, const hidl_string& errMsg) { ASSERT_TRUE(success) << errMsg.c_str(); }
+
+#define ASSERT_FALSE_CALLBACK \
+ [&](bool success, const hidl_string& errMsg) { ASSERT_FALSE(success) << errMsg.c_str(); }
+
+const unsigned kFd1Groups = NFNLGRP_CONNTRACK_NEW | NFNLGRP_CONNTRACK_DESTROY;
+const unsigned kFd2Groups = NFNLGRP_CONNTRACK_UPDATE | NFNLGRP_CONNTRACK_DESTROY;
+
+inline const sockaddr* asSockaddr(const sockaddr_nl* nladdr) {
+ return reinterpret_cast<const sockaddr*>(nladdr);
+}
+
+int netlinkSocket(int protocol, unsigned groups) {
+ unique_fd s(socket(AF_NETLINK, SOCK_DGRAM, protocol));
+ if (s.get() < 0) {
+ return -errno;
+ }
+
+ const struct sockaddr_nl bind_addr = {
+ .nl_family = AF_NETLINK, .nl_pad = 0, .nl_pid = 0, .nl_groups = groups,
+ };
+ if (::bind(s.get(), asSockaddr(&bind_addr), sizeof(bind_addr)) != 0) {
+ return -errno;
+ }
+
+ const struct sockaddr_nl kernel_addr = {
+ .nl_family = AF_NETLINK, .nl_pad = 0, .nl_pid = 0, .nl_groups = groups,
+ };
+ if (::connect(s.get(), asSockaddr(&kernel_addr), sizeof(kernel_addr)) != 0) {
+ return -errno;
+ }
+
+ return s.release();
+}
+
+int netlinkSocket(unsigned groups) {
+ return netlinkSocket(NETLINK_NETFILTER, groups);
+}
+
+class OffloadConfigHidlTest : public testing::VtsHalHidlTargetTestBase {
+ public:
+ virtual void SetUp() override {
+ config = testing::VtsHalHidlTargetTestBase::getService<IOffloadConfig>();
+ ASSERT_NE(nullptr, config.get()) << "Could not get HIDL instance";
+ }
+
+ virtual void TearDown() override {}
+
+ sp<IOffloadConfig> config;
+};
+
+// Ensure handles can be set with correct socket options.
+TEST_F(OffloadConfigHidlTest, TestSetHandles) {
+ unique_fd fd1(netlinkSocket(kFd1Groups));
+ if (fd1.get() < 0) {
+ ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
+ FAIL();
+ }
+ native_handle_t* const nativeHandle1 = native_handle_create(1, 0);
+ nativeHandle1->data[0] = fd1.release();
+ const hidl_handle h1 = hidl_handle(nativeHandle1);
+
+ unique_fd fd2(netlinkSocket(kFd2Groups));
+ if (fd2.get() < 0) {
+ ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
+ FAIL();
+ }
+ native_handle_t* const nativeHandle2 = native_handle_create(1, 0);
+ nativeHandle2->data[0] = fd2.release();
+ const hidl_handle h2 = hidl_handle(nativeHandle2);
+
+ const Return<void> ret = config->setHandles(h1, h2, ASSERT_TRUE_CALLBACK);
+ ASSERT_TRUE(ret.isOk());
+}
+
+// Passing a handle without an associated file descriptor should return an error
+// (e.g. "Failed Input Checks"). Check that this occurs when both FDs are empty.
+TEST_F(OffloadConfigHidlTest, TestSetHandleNone) {
+ native_handle_t* const nativeHandle1 = native_handle_create(0, 0);
+ const hidl_handle h1 = hidl_handle(nativeHandle1);
+ native_handle_t* const nativeHandle2 = native_handle_create(0, 0);
+ const hidl_handle h2 = hidl_handle(nativeHandle2);
+
+ const Return<void> ret = config->setHandles(h1, h2, ASSERT_FALSE_CALLBACK);
+ ASSERT_TRUE(ret.isOk());
+}
+
+// Passing a handle without an associated file descriptor should return an error
+// (e.g. "Failed Input Checks"). Check that this occurs when FD2 is empty.
+TEST_F(OffloadConfigHidlTest, TestSetHandle1Only) {
+ unique_fd fd1(netlinkSocket(kFd1Groups));
+ if (fd1.get() < 0) {
+ ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
+ FAIL();
+ }
+ native_handle_t* const nativeHandle1 = native_handle_create(1, 0);
+ nativeHandle1->data[0] = fd1.release();
+ const hidl_handle h1 = hidl_handle(nativeHandle1);
+
+ native_handle_t* const nativeHandle2 = native_handle_create(0, 0);
+ const hidl_handle h2 = hidl_handle(nativeHandle2);
+
+ const Return<void> ret = config->setHandles(h1, h2, ASSERT_FALSE_CALLBACK);
+ ASSERT_TRUE(ret.isOk());
+}
+
+// Passing a handle without an associated file descriptor should return an error
+// (e.g. "Failed Input Checks"). Check that this occurs when FD1 is empty.
+TEST_F(OffloadConfigHidlTest, TestSetHandle2OnlyNotOk) {
+ native_handle_t* const nativeHandle1 = native_handle_create(0, 0);
+ const hidl_handle h1 = hidl_handle(nativeHandle1);
+
+ unique_fd fd2(netlinkSocket(kFd2Groups));
+ if (fd2.get() < 0) {
+ ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
+ FAIL();
+ }
+ native_handle_t* const nativeHandle2 = native_handle_create(1, 0);
+ nativeHandle2->data[0] = fd2.release();
+ const hidl_handle h2 = hidl_handle(nativeHandle2);
+
+ const Return<void> ret = config->setHandles(h1, h2, ASSERT_FALSE_CALLBACK);
+ ASSERT_TRUE(ret.isOk());
+}
+
+int main(int argc, char** argv) {
+ testing::InitGoogleTest(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ ALOGE("Test result with status=%d", status);
+ return status;
+}
diff --git a/tetheroffload/control/1.0/vts/functional/Android.bp b/tetheroffload/control/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..69fac6e
--- /dev/null
+++ b/tetheroffload/control/1.0/vts/functional/Android.bp
@@ -0,0 +1,34 @@
+// 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.
+
+cc_test {
+ name: "VtsHalTetheroffloadControlV1_0TargetTest",
+ defaults: ["hidl_defaults"],
+ srcs: ["VtsHalTetheroffloadControlV1_0TargetTest.cpp"],
+ shared_libs: [
+ "android.hardware.tetheroffload.config@1.0",
+ "android.hardware.tetheroffload.control@1.0",
+ "libbase",
+ "libcutils",
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+ "libutils",
+ ],
+ static_libs: ["VtsHalHidlTargetTestBase"],
+ cflags: [
+ "-O0",
+ "-g",
+ ],
+}
diff --git a/tetheroffload/control/1.0/vts/functional/VtsHalTetheroffloadControlV1_0TargetTest.cpp b/tetheroffload/control/1.0/vts/functional/VtsHalTetheroffloadControlV1_0TargetTest.cpp
new file mode 100644
index 0000000..3d5cc81
--- /dev/null
+++ b/tetheroffload/control/1.0/vts/functional/VtsHalTetheroffloadControlV1_0TargetTest.cpp
@@ -0,0 +1,625 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "VtsOffloadControlV1_0TargetTest"
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <VtsHalHidlTargetTestBase.h>
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <android/hardware/tetheroffload/config/1.0/IOffloadConfig.h>
+#include <android/hardware/tetheroffload/control/1.0/IOffloadControl.h>
+#include <android/hardware/tetheroffload/control/1.0/types.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netlink.h>
+#include <log/log.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <set>
+
+using android::base::StringPrintf;
+using android::base::unique_fd;
+using android::hardware::hidl_handle;
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::tetheroffload::config::V1_0::IOffloadConfig;
+using android::hardware::tetheroffload::control::V1_0::IOffloadControl;
+using android::hardware::tetheroffload::control::V1_0::IPv4AddrPortPair;
+using android::hardware::tetheroffload::control::V1_0::ITetheringOffloadCallback;
+using android::hardware::tetheroffload::control::V1_0::OffloadCallbackEvent;
+using android::hardware::tetheroffload::control::V1_0::NatTimeoutUpdate;
+using android::hardware::tetheroffload::control::V1_0::NetworkProtocol;
+using android::hardware::Void;
+using android::sp;
+
+// We use #defines here so as to get local lamba captures and error message line numbers
+#define ASSERT_TRUE_CALLBACK \
+ [&](bool success, std::string errMsg) { \
+ if (!success) { \
+ ALOGI("Error message: %s", errMsg.c_str()); \
+ } \
+ ASSERT_TRUE(success); \
+ }
+
+#define ASSERT_FALSE_CALLBACK \
+ [&](bool success, std::string errMsg) { \
+ if (!success) { \
+ ALOGI("Error message: %s", errMsg.c_str()); \
+ } \
+ ASSERT_FALSE(success); \
+ }
+
+#define ASSERT_ZERO_BYTES_CALLBACK \
+ [&](uint64_t rxBytes, uint64_t txBytes) { \
+ EXPECT_EQ(0ULL, rxBytes); \
+ EXPECT_EQ(0ULL, txBytes); \
+ }
+
+inline const sockaddr* asSockaddr(const sockaddr_nl* nladdr) {
+ return reinterpret_cast<const sockaddr*>(nladdr);
+}
+
+int conntrackSocket(unsigned groups) {
+ unique_fd s(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_NETFILTER));
+ if (s.get() < 0) {
+ return -errno;
+ }
+
+ const struct sockaddr_nl bind_addr = {
+ .nl_family = AF_NETLINK, .nl_pad = 0, .nl_pid = 0, .nl_groups = groups,
+ };
+ if (::bind(s.get(), asSockaddr(&bind_addr), sizeof(bind_addr)) < 0) {
+ return -errno;
+ }
+
+ const struct sockaddr_nl kernel_addr = {
+ .nl_family = AF_NETLINK, .nl_pad = 0, .nl_pid = 0, .nl_groups = groups,
+ };
+ if (connect(s.get(), asSockaddr(&kernel_addr), sizeof(kernel_addr)) != 0) {
+ return -errno;
+ }
+
+ return s.release();
+}
+
+constexpr char kCallbackOnEvent[] = "onEvent";
+constexpr char kCallbackUpdateTimeout[] = "updateTimeout";
+
+class TetheringOffloadCallbackArgs {
+ public:
+ OffloadCallbackEvent last_event;
+ NatTimeoutUpdate last_params;
+};
+
+class OffloadControlHidlTestBase : public testing::VtsHalHidlTargetTestBase {
+ public:
+ virtual void SetUp() override {
+ setupConfigHal();
+ prepareControlHal();
+ }
+
+ virtual void TearDown() override { stopOffload(false); }
+
+ // The IOffloadConfig HAL is tested more thoroughly elsewhere. He we just
+ // setup everything correctly and verify basic readiness.
+ void setupConfigHal() {
+ config = testing::VtsHalHidlTargetTestBase::getService<IOffloadConfig>();
+ ASSERT_NE(nullptr, config.get()) << "Could not get HIDL instance";
+
+ unique_fd fd1(conntrackSocket(NFNLGRP_CONNTRACK_NEW | NFNLGRP_CONNTRACK_DESTROY));
+ if (fd1.get() < 0) {
+ ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
+ FAIL();
+ }
+ native_handle_t* const nativeHandle1 = native_handle_create(1, 0);
+ nativeHandle1->data[0] = fd1.release();
+ hidl_handle h1 = hidl_handle(nativeHandle1);
+
+ unique_fd fd2(conntrackSocket(NFNLGRP_CONNTRACK_UPDATE | NFNLGRP_CONNTRACK_DESTROY));
+ if (fd2.get() < 0) {
+ ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
+ FAIL();
+ }
+ native_handle_t* const nativeHandle2 = native_handle_create(1, 0);
+ nativeHandle2->data[0] = fd2.release();
+ hidl_handle h2 = hidl_handle(nativeHandle2);
+
+ const Return<void> ret = config->setHandles(h1, h2, ASSERT_TRUE_CALLBACK);
+ ASSERT_TRUE(ret.isOk());
+ }
+
+ void prepareControlHal() {
+ control = testing::VtsHalHidlTargetTestBase::getService<IOffloadControl>();
+ ASSERT_NE(nullptr, control.get()) << "Could not get HIDL instance";
+
+ control_cb = new TetheringOffloadCallback();
+ ASSERT_NE(nullptr, control_cb.get()) << "Could not get get offload callback";
+ }
+
+ void initOffload(const bool expected_result) {
+ auto init_cb = [&](bool success, std::string errMsg) {
+ if (!success) {
+ ALOGI("Error message: %s", errMsg.c_str());
+ }
+ ASSERT_EQ(expected_result, success);
+ };
+ const Return<void> ret = control->initOffload(control_cb, init_cb);
+ ASSERT_TRUE(ret.isOk());
+ }
+
+ void setupControlHal() {
+ prepareControlHal();
+ initOffload(true);
+ }
+
+ void stopOffload(const bool expected_result) {
+ auto cb = [&](bool success, const hidl_string& errMsg) {
+ if (!success) {
+ ALOGI("Error message: %s", errMsg.c_str());
+ }
+ ASSERT_EQ(expected_result, success);
+ };
+ const Return<void> ret = control->stopOffload(cb);
+ ASSERT_TRUE(ret.isOk());
+ }
+
+ // Callback class for both events and NAT timeout updates.
+ class TetheringOffloadCallback
+ : public testing::VtsHalHidlTargetCallbackBase<TetheringOffloadCallbackArgs>,
+ public ITetheringOffloadCallback {
+ public:
+ TetheringOffloadCallback() = default;
+ virtual ~TetheringOffloadCallback() = default;
+
+ Return<void> onEvent(OffloadCallbackEvent event) override {
+ const TetheringOffloadCallbackArgs args{.last_event = event};
+ NotifyFromCallback(kCallbackOnEvent, args);
+ return Void();
+ };
+
+ Return<void> updateTimeout(const NatTimeoutUpdate& params) override {
+ const TetheringOffloadCallbackArgs args{.last_params = params};
+ NotifyFromCallback(kCallbackUpdateTimeout, args);
+ return Void();
+ };
+ };
+
+ sp<IOffloadConfig> config;
+ sp<IOffloadControl> control;
+ sp<TetheringOffloadCallback> control_cb;
+};
+
+// Call initOffload() multiple times. Check that non-first initOffload() calls return false.
+TEST_F(OffloadControlHidlTestBase, AdditionalInitsWithoutStopReturnFalse) {
+ initOffload(true);
+ initOffload(false);
+ initOffload(false);
+ initOffload(false);
+ stopOffload(true); // balance out initOffload(true)
+}
+
+// Check that calling stopOffload() without first having called initOffload() returns false.
+TEST_F(OffloadControlHidlTestBase, MultipleStopsWithoutInitReturnFalse) {
+ stopOffload(false);
+ stopOffload(false);
+ stopOffload(false);
+}
+
+// Check that calling stopOffload() after a complete init/stop cycle returns false.
+TEST_F(OffloadControlHidlTestBase, AdditionalStopsWithInitReturnFalse) {
+ initOffload(true);
+ stopOffload(true); // balance out initOffload(true)
+ stopOffload(false);
+ stopOffload(false);
+}
+
+// Check that calling setLocalPrefixes() without first having called initOffload() returns false.
+TEST_F(OffloadControlHidlTestBase, SetLocalPrefixesWithoutInitReturnsFalse) {
+ const vector<hidl_string> prefixes{hidl_string("2001:db8::/64")};
+ const Return<void> ret = control->setLocalPrefixes(prefixes, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Check that calling getForwardedStats() without first having called initOffload()
+// returns zero bytes statistics.
+TEST_F(OffloadControlHidlTestBase, GetForwardedStatsWithoutInitReturnsZeroValues) {
+ const hidl_string upstream("rmnet_data0");
+ const Return<void> ret = control->getForwardedStats(upstream, ASSERT_ZERO_BYTES_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Check that calling setDataLimit() without first having called initOffload() returns false.
+TEST_F(OffloadControlHidlTestBase, SetDataLimitWithoutInitReturnsFalse) {
+ const hidl_string upstream("rmnet_data0");
+ const uint64_t limit = 5000ULL;
+ const Return<void> ret = control->setDataLimit(upstream, limit, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Check that calling setUpstreamParameters() without first having called initOffload()
+// returns false.
+TEST_F(OffloadControlHidlTestBase, SetUpstreamParametersWithoutInitReturnsFalse) {
+ const hidl_string iface("rmnet_data0");
+ const hidl_string v4Addr("192.0.2.0/24");
+ const hidl_string v4Gw("192.0.2.1");
+ const vector<hidl_string> v6Gws{hidl_string("fe80::db8:1")};
+ const Return<void> ret =
+ control->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Check that calling addDownstream() with an IPv4 prefix without first having called
+// initOffload() returns false.
+TEST_F(OffloadControlHidlTestBase, AddIPv4DownstreamWithoutInitReturnsFalse) {
+ const hidl_string iface("rmnet_data0");
+ const hidl_string prefix("192.0.2.0/24");
+ const Return<void> ret = control->addDownstream(iface, prefix, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Check that calling addDownstream() with an IPv6 prefix without first having called
+// initOffload() returns false.
+TEST_F(OffloadControlHidlTestBase, AddIPv6DownstreamWithoutInitReturnsFalse) {
+ const hidl_string iface("rmnet_data0");
+ const hidl_string prefix("2001:db8::/64");
+ const Return<void> ret = control->addDownstream(iface, prefix, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Check that calling removeDownstream() with an IPv4 prefix without first having called
+// initOffload() returns false.
+TEST_F(OffloadControlHidlTestBase, RemoveIPv4DownstreamWithoutInitReturnsFalse) {
+ const hidl_string iface("rmnet_data0");
+ const hidl_string prefix("192.0.2.0/24");
+ const Return<void> ret = control->removeDownstream(iface, prefix, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Check that calling removeDownstream() with an IPv6 prefix without first having called
+// initOffload() returns false.
+TEST_F(OffloadControlHidlTestBase, RemoveIPv6DownstreamWithoutInitReturnsFalse) {
+ const hidl_string iface("rmnet_data0");
+ const hidl_string prefix("2001:db8::/64");
+ const Return<void> ret = control->removeDownstream(iface, prefix, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+class OffloadControlHidlTest : public OffloadControlHidlTestBase {
+ public:
+ virtual void SetUp() override {
+ setupConfigHal();
+ setupControlHal();
+ }
+
+ virtual void TearDown() override { stopOffload(true); }
+};
+
+/*
+ * Tests for IOffloadControl::setLocalPrefixes().
+ */
+
+// Test setLocalPrefixes() accepts an IPv4 address.
+TEST_F(OffloadControlHidlTest, SetLocalPrefixesIPv4AddressOk) {
+ const vector<hidl_string> prefixes{hidl_string("192.0.2.1")};
+ const Return<void> ret = control->setLocalPrefixes(prefixes, ASSERT_TRUE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Test setLocalPrefixes() accepts an IPv6 address.
+TEST_F(OffloadControlHidlTest, SetLocalPrefixesIPv6AddressOk) {
+ const vector<hidl_string> prefixes{hidl_string("fe80::1")};
+ const Return<void> ret = control->setLocalPrefixes(prefixes, ASSERT_TRUE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Test setLocalPrefixes() accepts both IPv4 and IPv6 prefixes.
+TEST_F(OffloadControlHidlTest, SetLocalPrefixesIPv4v6PrefixesOk) {
+ const vector<hidl_string> prefixes{hidl_string("192.0.2.0/24"), hidl_string("fe80::/64")};
+ const Return<void> ret = control->setLocalPrefixes(prefixes, ASSERT_TRUE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Test that setLocalPrefixes() fails given empty input. There is always
+// a non-empty set of local prefixes; when all networking interfaces are down
+// we still apply {127.0.0.0/8, ::1/128, fe80::/64} here.
+TEST_F(OffloadControlHidlTest, SetLocalPrefixesEmptyFails) {
+ const vector<hidl_string> prefixes{};
+ const Return<void> ret = control->setLocalPrefixes(prefixes, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Test setLocalPrefixes() fails on incorrectly formed input strings.
+TEST_F(OffloadControlHidlTest, SetLocalPrefixesInvalidFails) {
+ const vector<hidl_string> prefixes{hidl_string("192.0.2.0/24"), hidl_string("invalid")};
+ const Return<void> ret = control->setLocalPrefixes(prefixes, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+/*
+ * Tests for IOffloadControl::getForwardedStats().
+ */
+
+// Test that getForwardedStats() for a non-existent upstream yields zero bytes statistics.
+TEST_F(OffloadControlHidlTest, GetForwardedStatsInvalidUpstreamIface) {
+ const hidl_string upstream("invalid");
+ const Return<void> ret = control->getForwardedStats(upstream, ASSERT_ZERO_BYTES_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// The "rmnet_data0" is presumed to exist on the device and be up. No packets
+// are ever actually caused to be forwarded.
+TEST_F(OffloadControlHidlTest, GetForwardedStatsDummyIface) {
+ const hidl_string upstream("rmnet_data0");
+ const Return<void> ret = control->getForwardedStats(upstream, ASSERT_ZERO_BYTES_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+/*
+ * Tests for IOffloadControl::setDataLimit().
+ */
+
+// Test that setDataLimit() for an empty interface name fails.
+TEST_F(OffloadControlHidlTest, SetDataLimitEmptyUpstreamIfaceFails) {
+ const hidl_string upstream("");
+ const uint64_t limit = 5000ULL;
+ const Return<void> ret = control->setDataLimit(upstream, limit, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// The "rmnet_data0" is presumed to exist on the device and be up. No packets
+// are ever actually caused to be forwarded.
+TEST_F(OffloadControlHidlTest, SetDataLimitNonZeroOk) {
+ const hidl_string upstream("rmnet_data0");
+ const uint64_t limit = 5000ULL;
+ const Return<void> ret = control->setDataLimit(upstream, limit, ASSERT_TRUE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// The "rmnet_data0" is presumed to exist on the device and be up. No packets
+// are ever actually caused to be forwarded.
+TEST_F(OffloadControlHidlTest, SetDataLimitZeroOk) {
+ const hidl_string upstream("rmnet_data0");
+ const uint64_t limit = 0ULL;
+ const Return<void> ret = control->setDataLimit(upstream, limit, ASSERT_TRUE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+/*
+ * Tests for IOffloadControl::setUpstreamParameters().
+ */
+
+// The "rmnet_data0" is presumed to exist on the device and be up. No packets
+// are ever actually caused to be forwarded.
+TEST_F(OffloadControlHidlTest, SetUpstreamParametersIPv6OnlyOk) {
+ const hidl_string iface("rmnet_data0");
+ const hidl_string v4Addr("");
+ const hidl_string v4Gw("");
+ const vector<hidl_string> v6Gws{hidl_string("fe80::db8:1"), hidl_string("fe80::db8:2")};
+ const Return<void> ret =
+ control->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws, ASSERT_TRUE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// The "rmnet_data0" is presumed to exist on the device and be up. No packets
+// are ever actually caused to be forwarded.
+TEST_F(OffloadControlHidlTest, SetUpstreamParametersAlternateIPv6OnlyOk) {
+ const hidl_string iface("rmnet_data0");
+ const hidl_string v4Addr;
+ const hidl_string v4Gw;
+ const vector<hidl_string> v6Gws{hidl_string("fe80::db8:1"), hidl_string("fe80::db8:3")};
+ const Return<void> ret =
+ control->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws, ASSERT_TRUE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// The "rmnet_data0" is presumed to exist on the device and be up. No packets
+// are ever actually caused to be forwarded.
+TEST_F(OffloadControlHidlTest, SetUpstreamParametersIPv4OnlyOk) {
+ const hidl_string iface("rmnet_data0");
+ const hidl_string v4Addr("192.0.2.2");
+ const hidl_string v4Gw("192.0.2.1");
+ const vector<hidl_string> v6Gws{};
+ const Return<void> ret =
+ control->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws, ASSERT_TRUE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// The "rmnet_data0" is presumed to exist on the device and be up. No packets
+// are ever actually caused to be forwarded.
+TEST_F(OffloadControlHidlTest, SetUpstreamParametersIPv4v6Ok) {
+ const hidl_string iface("rmnet_data0");
+ const hidl_string v4Addr("192.0.2.2");
+ const hidl_string v4Gw("192.0.2.1");
+ const vector<hidl_string> v6Gws{hidl_string("fe80::db8:1"), hidl_string("fe80::db8::2")};
+ const Return<void> ret =
+ control->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws, ASSERT_TRUE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Test that setUpstreamParameters() fails when all parameters are empty.
+TEST_F(OffloadControlHidlTest, SetUpstreamParametersEmptyFails) {
+ const hidl_string iface("");
+ const hidl_string v4Addr("");
+ const hidl_string v4Gw("");
+ const vector<hidl_string> v6Gws{};
+ const Return<void> ret =
+ control->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Test that setUpstreamParameters() fails when given empty or non-existent interface names.
+TEST_F(OffloadControlHidlTest, SetUpstreamParametersBogusIfaceFails) {
+ const hidl_string v4Addr("192.0.2.2");
+ const hidl_string v4Gw("192.0.2.1");
+ const vector<hidl_string> v6Gws{hidl_string("fe80::db8:1")};
+ for (const auto& bogus : {"", "invalid"}) {
+ SCOPED_TRACE(StringPrintf("iface='%s'", bogus));
+ const hidl_string iface(bogus);
+ const Return<void> ret =
+ control->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+ }
+}
+
+// Test that setUpstreamParameters() fails when given unparseable IPv4 addresses.
+TEST_F(OffloadControlHidlTest, SetUpstreamParametersInvalidIPv4AddrFails) {
+ const hidl_string iface("rmnet_data0");
+ const hidl_string v4Gw("192.0.2.1");
+ const vector<hidl_string> v6Gws{hidl_string("fe80::db8:1")};
+ for (const auto& bogus : {"invalid", "192.0.2"}) {
+ SCOPED_TRACE(StringPrintf("v4addr='%s'", bogus));
+ const hidl_string v4Addr(bogus);
+ const Return<void> ret =
+ control->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+ }
+}
+
+// Test that setUpstreamParameters() fails when given unparseable IPv4 gateways.
+TEST_F(OffloadControlHidlTest, SetUpstreamParametersInvalidIPv4GatewayFails) {
+ const hidl_string iface("rmnet_data0");
+ const hidl_string v4Addr("192.0.2.2");
+ const vector<hidl_string> v6Gws{hidl_string("fe80::db8:1")};
+ for (const auto& bogus : {"invalid", "192.0.2"}) {
+ SCOPED_TRACE(StringPrintf("v4gateway='%s'", bogus));
+ const hidl_string v4Gw(bogus);
+ const Return<void> ret =
+ control->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+ }
+}
+
+// Test that setUpstreamParameters() fails when given unparseable IPv6 gateways.
+TEST_F(OffloadControlHidlTest, SetUpstreamParametersBadIPv6GatewaysFail) {
+ const hidl_string iface("rmnet_data0");
+ const hidl_string v4Addr("192.0.2.2");
+ const hidl_string v4Gw("192.0.2.1");
+ for (const auto& bogus : {"", "invalid", "fe80::bogus", "192.0.2.66"}) {
+ SCOPED_TRACE(StringPrintf("v6gateway='%s'", bogus));
+ const vector<hidl_string> v6Gws{hidl_string("fe80::1"), hidl_string(bogus)};
+ const Return<void> ret =
+ control->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+ }
+}
+
+/*
+ * Tests for IOffloadControl::addDownstream().
+ */
+
+// Test addDownstream() works given an IPv4 prefix.
+TEST_F(OffloadControlHidlTest, AddDownstreamIPv4) {
+ const hidl_string iface("dummy0");
+ const hidl_string prefix("192.0.2.0/24");
+ const Return<void> ret = control->addDownstream(iface, prefix, ASSERT_TRUE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Test addDownstream() works given an IPv6 prefix.
+TEST_F(OffloadControlHidlTest, AddDownstreamIPv6) {
+ const hidl_string iface("dummy0");
+ const hidl_string prefix("2001:db8::/64");
+ const Return<void> ret = control->addDownstream(iface, prefix, ASSERT_TRUE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Test addDownstream() fails given all empty parameters.
+TEST_F(OffloadControlHidlTest, AddDownstreamEmptyFails) {
+ const hidl_string iface("");
+ const hidl_string prefix("");
+ const Return<void> ret = control->addDownstream(iface, prefix, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Test addDownstream() fails given empty or non-existent interface names.
+TEST_F(OffloadControlHidlTest, AddDownstreamInvalidIfaceFails) {
+ const hidl_string prefix("192.0.2.0/24");
+ for (const auto& bogus : {"", "invalid"}) {
+ SCOPED_TRACE(StringPrintf("iface='%s'", bogus));
+ const hidl_string iface(bogus);
+ const Return<void> ret = control->addDownstream(iface, prefix, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+ }
+}
+
+// Test addDownstream() fails given unparseable prefix arguments.
+TEST_F(OffloadControlHidlTest, AddDownstreamBogusPrefixFails) {
+ const hidl_string iface("dummy0");
+ for (const auto& bogus : {"", "192.0.2/24", "2001:db8/64"}) {
+ SCOPED_TRACE(StringPrintf("prefix='%s'", bogus));
+ const hidl_string prefix(bogus);
+ const Return<void> ret = control->addDownstream(iface, prefix, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+ }
+}
+
+/*
+ * Tests for IOffloadControl::removeDownstream().
+ */
+
+// Test removeDownstream() works given an IPv4 prefix.
+TEST_F(OffloadControlHidlTest, RemoveDownstreamIPv4) {
+ const hidl_string iface("dummy0");
+ const hidl_string prefix("192.0.2.0/24");
+ const Return<void> ret = control->removeDownstream(iface, prefix, ASSERT_TRUE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Test removeDownstream() works given an IPv6 prefix.
+TEST_F(OffloadControlHidlTest, RemoveDownstreamIPv6) {
+ const hidl_string iface("dummy0");
+ const hidl_string prefix("2001:db8::/64");
+ const Return<void> ret = control->removeDownstream(iface, prefix, ASSERT_TRUE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Test removeDownstream() fails given all empty parameters.
+TEST_F(OffloadControlHidlTest, RemoveDownstreamEmptyFails) {
+ const hidl_string iface("");
+ const hidl_string prefix("");
+ const Return<void> ret = control->removeDownstream(iface, prefix, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+}
+
+// Test removeDownstream() fails given empty or non-existent interface names.
+TEST_F(OffloadControlHidlTest, RemoveDownstreamBogusIfaceFails) {
+ const hidl_string prefix("192.0.2.0/24");
+ for (const auto& bogus : {"", "invalid"}) {
+ SCOPED_TRACE(StringPrintf("iface='%s'", bogus));
+ const hidl_string iface(bogus);
+ const Return<void> ret = control->removeDownstream(iface, prefix, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+ }
+}
+
+// Test removeDownstream() fails given unparseable prefix arguments.
+TEST_F(OffloadControlHidlTest, RemoveDownstreamBogusPrefixFails) {
+ const hidl_string iface("dummy0");
+ for (const auto& bogus : {"", "192.0.2/24", "2001:db8/64"}) {
+ SCOPED_TRACE(StringPrintf("prefix='%s'", bogus));
+ const hidl_string prefix(bogus);
+ const Return<void> ret = control->removeDownstream(iface, prefix, ASSERT_FALSE_CALLBACK);
+ EXPECT_TRUE(ret.isOk());
+ }
+}
+
+int main(int argc, char** argv) {
+ testing::InitGoogleTest(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ ALOGE("Test result with status=%d", status);
+ return status;
+}
diff --git a/thermal/1.1/Android.bp b/thermal/1.1/Android.bp
new file mode 100644
index 0000000..833f219
--- /dev/null
+++ b/thermal/1.1/Android.bp
@@ -0,0 +1,68 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+ name: "android.hardware.thermal@1.1_hal",
+ srcs: [
+ "IThermal.hal",
+ "IThermalCallback.hal",
+ ],
+}
+
+genrule {
+ name: "android.hardware.thermal@1.1_genc++",
+ tools: ["hidl-gen"],
+ cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.thermal@1.1",
+ srcs: [
+ ":android.hardware.thermal@1.1_hal",
+ ],
+ out: [
+ "android/hardware/thermal/1.1/ThermalAll.cpp",
+ "android/hardware/thermal/1.1/ThermalCallbackAll.cpp",
+ ],
+}
+
+genrule {
+ name: "android.hardware.thermal@1.1_genc++_headers",
+ tools: ["hidl-gen"],
+ cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.thermal@1.1",
+ srcs: [
+ ":android.hardware.thermal@1.1_hal",
+ ],
+ out: [
+ "android/hardware/thermal/1.1/IThermal.h",
+ "android/hardware/thermal/1.1/IHwThermal.h",
+ "android/hardware/thermal/1.1/BnHwThermal.h",
+ "android/hardware/thermal/1.1/BpHwThermal.h",
+ "android/hardware/thermal/1.1/BsThermal.h",
+ "android/hardware/thermal/1.1/IThermalCallback.h",
+ "android/hardware/thermal/1.1/IHwThermalCallback.h",
+ "android/hardware/thermal/1.1/BnHwThermalCallback.h",
+ "android/hardware/thermal/1.1/BpHwThermalCallback.h",
+ "android/hardware/thermal/1.1/BsThermalCallback.h",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.thermal@1.1",
+ defaults: ["hidl-module-defaults"],
+ generated_sources: ["android.hardware.thermal@1.1_genc++"],
+ generated_headers: ["android.hardware.thermal@1.1_genc++_headers"],
+ export_generated_headers: ["android.hardware.thermal@1.1_genc++_headers"],
+ vendor_available: true,
+ shared_libs: [
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "liblog",
+ "libutils",
+ "libcutils",
+ "android.hardware.thermal@1.0",
+ ],
+ export_shared_lib_headers: [
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "libutils",
+ "android.hardware.thermal@1.0",
+ ],
+}
diff --git a/thermal/1.1/Android.mk b/thermal/1.1/Android.mk
new file mode 100644
index 0000000..082d65b
--- /dev/null
+++ b/thermal/1.1/Android.mk
@@ -0,0 +1,120 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.thermal-V1.1-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(call local-generated-sources-dir, COMMON)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+ android.hardware.thermal-V1.0-java \
+ android.hidl.base-V1.0-java \
+
+
+#
+# Build IThermal.hal
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_1/IThermal.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IThermal.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IThermalCallback.hal
+$(GEN): $(LOCAL_PATH)/IThermalCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+ $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+ -Ljava \
+ -randroid.hardware:hardware/interfaces \
+ -randroid.hidl:system/libhidl/transport \
+ android.hardware.thermal@1.1::IThermal
+
+$(GEN): $(LOCAL_PATH)/IThermal.hal
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IThermalCallback.hal
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_1/IThermalCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IThermalCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+ $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+ -Ljava \
+ -randroid.hardware:hardware/interfaces \
+ -randroid.hidl:system/libhidl/transport \
+ android.hardware.thermal@1.1::IThermalCallback
+
+$(GEN): $(LOCAL_PATH)/IThermalCallback.hal
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.thermal-V1.1-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(call local-generated-sources-dir, COMMON)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android.hardware.thermal-V1.0-java-static \
+ android.hidl.base-V1.0-java-static \
+
+
+#
+# Build IThermal.hal
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_1/IThermal.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IThermal.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IThermalCallback.hal
+$(GEN): $(LOCAL_PATH)/IThermalCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+ $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+ -Ljava \
+ -randroid.hardware:hardware/interfaces \
+ -randroid.hidl:system/libhidl/transport \
+ android.hardware.thermal@1.1::IThermal
+
+$(GEN): $(LOCAL_PATH)/IThermal.hal
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IThermalCallback.hal
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_1/IThermalCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IThermalCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+ $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+ -Ljava \
+ -randroid.hardware:hardware/interfaces \
+ -randroid.hidl:system/libhidl/transport \
+ android.hardware.thermal@1.1::IThermalCallback
+
+$(GEN): $(LOCAL_PATH)/IThermalCallback.hal
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/thermal/1.1/IThermal.hal b/thermal/1.1/IThermal.hal
new file mode 100644
index 0000000..14f35ba
--- /dev/null
+++ b/thermal/1.1/IThermal.hal
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+package android.hardware.thermal@1.1;
+
+import android.hardware.thermal@1.0::IThermal;
+import IThermalCallback;
+
+interface IThermal extends @1.0::IThermal {
+ /**
+ * Register an IThermalCallback, used by the Thermal HAL
+ * to send thermal events to the framework thermal service.
+ *
+ * @param callback the IThermalCallback to use for sending
+ * thermal events, or nullptr to set no callback
+ */
+ registerThermalCallback(IThermalCallback callback);
+};
diff --git a/thermal/1.1/IThermalCallback.hal b/thermal/1.1/IThermalCallback.hal
new file mode 100644
index 0000000..f418ec3
--- /dev/null
+++ b/thermal/1.1/IThermalCallback.hal
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+package android.hardware.thermal@1.1;
+
+import android.hardware.thermal@1.0::Temperature;
+
+/**
+ * IThermalCallback connects vendor code to the framework binder ThermalService.
+ */
+interface IThermalCallback {
+ /**
+ * Send a thermal throttling start/stop event to all ThermalService
+ * thermal event listeners.
+ * @param isThrottling true if device is currently throttling
+ * @param temperature The temperature associated with the throttling
+ * start/stop event
+ */
+ oneway notifyThrottling(bool isThrottling, Temperature temperature);
+};
diff --git a/thermal/1.1/vts/functional/Android.bp b/thermal/1.1/vts/functional/Android.bp
new file mode 100644
index 0000000..cea5bf8
--- /dev/null
+++ b/thermal/1.1/vts/functional/Android.bp
@@ -0,0 +1,35 @@
+//
+// 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.
+//
+
+cc_test {
+ name: "VtsHalThermalV1_1TargetTest",
+ defaults: ["hidl_defaults"],
+ srcs: ["VtsHalThermalV1_1TargetTest.cpp"],
+ shared_libs: [
+ "liblog",
+ "libhidlbase",
+ "libhidltransport",
+ "libutils",
+ "android.hardware.thermal@1.0",
+ "android.hardware.thermal@1.1",
+ ],
+ static_libs: ["VtsHalHidlTargetTestBase"],
+ cflags: [
+ "-O0",
+ "-g",
+ ],
+}
+
diff --git a/thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp b/thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp
new file mode 100644
index 0000000..6c1599b
--- /dev/null
+++ b/thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp
@@ -0,0 +1,106 @@
+/*
+ * 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 <android/hardware/thermal/1.1/IThermal.h>
+#include <android/hardware/thermal/1.1/IThermalCallback.h>
+#include <android/hardware/thermal/1.0/types.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <VtsHalHidlTargetTestBase.h>
+
+using ::android::hardware::thermal::V1_0::Temperature;
+using ::android::hardware::thermal::V1_0::TemperatureType;
+using ::android::hardware::thermal::V1_1::IThermal;
+using ::android::hardware::thermal::V1_1::IThermalCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+constexpr char kCallbackNameNotifyThrottling[] = "notifyThrottling";
+static const Temperature kThrottleTemp = {
+ .type = TemperatureType::CPU,
+ .name = "test temperature sensor",
+ .currentValue = 98.6,
+ .throttlingThreshold = 58,
+ .shutdownThreshold = 60,
+ .vrThrottlingThreshold = 59,
+};
+
+class ThermalCallbackArgs {
+ public:
+ bool isThrottling;
+ Temperature temperature;
+};
+
+// Callback class for receiving thermal event notifications from main class
+class ThermalCallback
+ : public ::testing::VtsHalHidlTargetCallbackBase<ThermalCallbackArgs>,
+ public IThermalCallback {
+ public:
+ virtual ~ThermalCallback() = default;
+
+ Return<void> notifyThrottling(bool isThrottling,
+ const Temperature& temperature) override {
+ ThermalCallbackArgs args;
+ args.isThrottling = isThrottling;
+ args.temperature = temperature;
+ NotifyFromCallback(kCallbackNameNotifyThrottling, args);
+ return Void();
+ }
+};
+
+// The main test class for THERMAL HIDL HAL 1.1.
+class ThermalHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+ virtual void SetUp() override {
+ mThermal = ::testing::VtsHalHidlTargetTestBase::getService<IThermal>();
+ ASSERT_NE(mThermal, nullptr);
+ mThermalCallback = new(std::nothrow) ThermalCallback();
+ ASSERT_NE(mThermalCallback, nullptr);
+ auto ret = mThermal->registerThermalCallback(mThermalCallback);
+ ASSERT_TRUE(ret.isOk());
+ }
+
+ virtual void TearDown() override {
+ auto ret = mThermal->registerThermalCallback(nullptr);
+ ASSERT_TRUE(ret.isOk());
+ }
+
+ protected:
+ sp<IThermal> mThermal;
+ sp<ThermalCallback> mThermalCallback;
+}; // class ThermalHidlTest
+
+// Test ThermalCallback::notifyThrottling().
+// This just calls into and back from our local ThermalCallback impl.
+// Note: a real thermal throttling event from the Thermal HAL could be
+// inadvertently received here.
+TEST_F(ThermalHidlTest, NotifyThrottlingTest) {
+ auto ret = mThermalCallback->notifyThrottling(true, kThrottleTemp);
+ ASSERT_TRUE(ret.isOk());
+ auto res = mThermalCallback->WaitForCallback(kCallbackNameNotifyThrottling);
+ EXPECT_TRUE(res.no_timeout);
+ ASSERT_TRUE(res.args);
+ EXPECT_EQ(true, res.args->isThrottling);
+ EXPECT_EQ(kThrottleTemp, res.args->temperature);
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ cout << "Test result = " << status << std::endl;
+ return status;
+}
diff --git a/thermal/Android.bp b/thermal/Android.bp
index ed19a37..a5415df 100644
--- a/thermal/Android.bp
+++ b/thermal/Android.bp
@@ -3,4 +3,6 @@
"1.0",
"1.0/default",
"1.0/vts/functional",
+ "1.1",
+ "1.1/vts/functional",
]
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
index e4382bc..0851cb2 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
@@ -206,5 +206,7 @@
void stopWifi() {
sp<IWifi> wifi = getWifi();
ASSERT_NE(wifi, nullptr);
- ASSERT_EQ(HIDL_INVOKE(wifi, stop).code, WifiStatusCode::SUCCESS);
+ const auto status = HIDL_INVOKE(wifi, stop);
+ ASSERT_TRUE((status.code == WifiStatusCode::SUCCESS) ||
+ (status.code == WifiStatusCode::ERROR_NOT_AVAILABLE));
}
diff --git a/wifi/1.1/default/service.cpp b/wifi/1.1/default/service.cpp
index b3fcd50..b4aed6c 100644
--- a/wifi/1.1/default/service.cpp
+++ b/wifi/1.1/default/service.cpp
@@ -27,7 +27,7 @@
int main(int /*argc*/, char** argv) {
android::base::InitLogging(argv,
android::base::LogdLogger(android::base::SYSTEM));
- LOG(INFO) << "Wifi Hal is starting up...";
+ LOG(INFO) << "Wifi Hal is booting up...";
configureRpcThreadpool(1, true /* callerWillJoin */);
diff --git a/wifi/1.1/default/wifi.cpp b/wifi/1.1/default/wifi.cpp
index fe4f642..8456b90 100644
--- a/wifi/1.1/default/wifi.cpp
+++ b/wifi/1.1/default/wifi.cpp
@@ -108,14 +108,15 @@
LOG(ERROR) << "Failed to invoke onStart callback";
};
}
+ LOG(INFO) << "Wifi HAL started";
} else {
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onFailure(wifi_status).isOk()) {
LOG(ERROR) << "Failed to invoke onFailure callback";
}
}
+ LOG(ERROR) << "Wifi HAL start failed";
}
- LOG(INFO) << "Wifi HAL started";
return wifi_status;
}
@@ -139,14 +140,15 @@
LOG(ERROR) << "Failed to invoke onStop callback";
};
}
+ LOG(INFO) << "Wifi HAL stopped";
} else {
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onFailure(wifi_status).isOk()) {
LOG(ERROR) << "Failed to invoke onFailure callback";
}
}
+ LOG(ERROR) << "Wifi HAL stop failed";
}
- LOG(INFO) << "Wifi HAL stopped";
return wifi_status;
}