Merge "Convert VtsHalContexthubV1_0Target to be parameterized test"
diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp
index 21dab00..c6c9464 100644
--- a/audio/core/all-versions/default/Device.cpp
+++ b/audio/core/all-versions/default/Device.cpp
@@ -84,26 +84,29 @@
ALOGW("Can not set a master volume (%f) outside [0,1]", volume);
return Result::INVALID_ARGUMENTS;
}
- return analyzeStatus("set_master_volume", mDevice->set_master_volume(mDevice, volume));
+ return analyzeStatus("set_master_volume", mDevice->set_master_volume(mDevice, volume),
+ {ENOSYS} /*ignore*/);
}
Return<void> Device::getMasterVolume(getMasterVolume_cb _hidl_cb) {
Result retval(Result::NOT_SUPPORTED);
float volume = 0;
if (mDevice->get_master_volume != NULL) {
- retval = analyzeStatus("get_master_volume", mDevice->get_master_volume(mDevice, &volume));
+ retval = analyzeStatus("get_master_volume", mDevice->get_master_volume(mDevice, &volume),
+ {ENOSYS} /*ignore*/);
}
_hidl_cb(retval, volume);
return Void();
}
Return<Result> Device::setMicMute(bool mute) {
- return analyzeStatus("set_mic_mute", mDevice->set_mic_mute(mDevice, mute));
+ return analyzeStatus("set_mic_mute", mDevice->set_mic_mute(mDevice, mute), {ENOSYS} /*ignore*/);
}
Return<void> Device::getMicMute(getMicMute_cb _hidl_cb) {
bool mute = false;
- Result retval = analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute));
+ Result retval = analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute),
+ {ENOSYS} /*ignore*/);
_hidl_cb(retval, mute);
return Void();
}
@@ -111,7 +114,8 @@
Return<Result> Device::setMasterMute(bool mute) {
Result retval(Result::NOT_SUPPORTED);
if (mDevice->set_master_mute != NULL) {
- retval = analyzeStatus("set_master_mute", mDevice->set_master_mute(mDevice, mute));
+ retval = analyzeStatus("set_master_mute", mDevice->set_master_mute(mDevice, mute),
+ {ENOSYS} /*ignore*/);
}
return retval;
}
@@ -120,7 +124,8 @@
Result retval(Result::NOT_SUPPORTED);
bool mute = false;
if (mDevice->get_master_mute != NULL) {
- retval = analyzeStatus("get_master_mute", mDevice->get_master_mute(mDevice, &mute));
+ retval = analyzeStatus("get_master_mute", mDevice->get_master_mute(mDevice, &mute),
+ {ENOSYS} /*ignore*/);
}
_hidl_cb(retval, mute);
return Void();
diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp
index 396d354..1a2a764 100644
--- a/audio/core/all-versions/default/StreamOut.cpp
+++ b/audio/core/all-versions/default/StreamOut.cpp
@@ -318,7 +318,8 @@
ALOGW("Can not set a stream output volume {%f, %f} outside [0,1]", left, right);
return Result::INVALID_ARGUMENTS;
}
- return Stream::analyzeStatus("set_volume", mStream->set_volume(mStream, left, right));
+ return Stream::analyzeStatus("set_volume", mStream->set_volume(mStream, left, right),
+ {ENOSYS} /*ignore*/);
}
Return<void> StreamOut::prepareForWriting(uint32_t frameSize, uint32_t framesCount,
@@ -403,7 +404,8 @@
Return<void> StreamOut::getRenderPosition(getRenderPosition_cb _hidl_cb) {
uint32_t halDspFrames;
Result retval = Stream::analyzeStatus("get_render_position",
- mStream->get_render_position(mStream, &halDspFrames));
+ mStream->get_render_position(mStream, &halDspFrames),
+ {ENOSYS} /*ignore*/);
_hidl_cb(retval, halDspFrames);
return Void();
}
@@ -413,7 +415,8 @@
int64_t timestampUs = 0;
if (mStream->get_next_write_timestamp != NULL) {
retval = Stream::analyzeStatus("get_next_write_timestamp",
- mStream->get_next_write_timestamp(mStream, ×tampUs));
+ mStream->get_next_write_timestamp(mStream, ×tampUs),
+ {ENOSYS} /*ignore*/);
}
_hidl_cb(retval, timestampUs);
return Void();
@@ -427,7 +430,7 @@
if (result == 0) {
mCallback = callback;
}
- return Stream::analyzeStatus("set_callback", result);
+ return Stream::analyzeStatus("set_callback", result, {ENOSYS} /*ignore*/);
}
Return<Result> StreamOut::clearCallback() {
@@ -473,13 +476,15 @@
}
Return<Result> StreamOut::pause() {
- return mStream->pause != NULL ? Stream::analyzeStatus("pause", mStream->pause(mStream))
- : Result::NOT_SUPPORTED;
+ return mStream->pause != NULL
+ ? Stream::analyzeStatus("pause", mStream->pause(mStream), {ENOSYS} /*ignore*/)
+ : Result::NOT_SUPPORTED;
}
Return<Result> StreamOut::resume() {
- return mStream->resume != NULL ? Stream::analyzeStatus("resume", mStream->resume(mStream))
- : Result::NOT_SUPPORTED;
+ return mStream->resume != NULL
+ ? Stream::analyzeStatus("resume", mStream->resume(mStream), {ENOSYS} /*ignore*/)
+ : Result::NOT_SUPPORTED;
}
Return<bool> StreamOut::supportsDrain() {
@@ -488,14 +493,17 @@
Return<Result> StreamOut::drain(AudioDrain type) {
return mStream->drain != NULL
- ? Stream::analyzeStatus(
- "drain", mStream->drain(mStream, static_cast<audio_drain_type_t>(type)))
- : Result::NOT_SUPPORTED;
+ ? Stream::analyzeStatus(
+ "drain",
+ mStream->drain(mStream, static_cast<audio_drain_type_t>(type)),
+ {ENOSYS} /*ignore*/)
+ : Result::NOT_SUPPORTED;
}
Return<Result> StreamOut::flush() {
- return mStream->flush != NULL ? Stream::analyzeStatus("flush", mStream->flush(mStream))
- : Result::NOT_SUPPORTED;
+ return mStream->flush != NULL
+ ? Stream::analyzeStatus("flush", mStream->flush(mStream), {ENOSYS} /*ignore*/)
+ : Result::NOT_SUPPORTED;
}
// static
@@ -505,7 +513,7 @@
// to return it sometimes. EAGAIN may be returned by A2DP audio HAL
// implementation. ENODATA can also be reported while the writer is
// continuously querying it, but the stream has been stopped.
- static const std::vector<int> ignoredErrors{EINVAL, EAGAIN, ENODATA};
+ static const std::vector<int> ignoredErrors{EINVAL, EAGAIN, ENODATA, ENOSYS};
Result retval(Result::NOT_SUPPORTED);
if (stream->get_presentation_position == NULL) return retval;
struct timespec halTimeStamp;
diff --git a/broadcastradio/2.0/vts/OWNERS b/broadcastradio/2.0/vts/OWNERS
index 12adf57..1ff7407 100644
--- a/broadcastradio/2.0/vts/OWNERS
+++ b/broadcastradio/2.0/vts/OWNERS
@@ -3,5 +3,4 @@
twasilczyk@google.com
# VTS team
-yuexima@google.com
-yim@google.com
+dshi@google.com
diff --git a/broadcastradio/2.0/vts/functional/Android.bp b/broadcastradio/2.0/vts/functional/Android.bp
index 3e18a54..49bb665 100644
--- a/broadcastradio/2.0/vts/functional/Android.bp
+++ b/broadcastradio/2.0/vts/functional/Android.bp
@@ -17,9 +17,6 @@
cc_test {
name: "VtsHalBroadcastradioV2_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
- cppflags: [
- "-std=c++1z",
- ],
srcs: ["VtsHalBroadcastradioV2_0TargetTest.cpp"],
static_libs: [
"android.hardware.broadcastradio@2.0",
@@ -28,5 +25,8 @@
"android.hardware.broadcastradio@vts-utils-lib",
"libgmock",
],
- test_suites: ["general-tests"],
+ test_suites: [
+ "general-tests",
+ "vts-core",
+ ],
}
diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
index e36f4d9..d170a6d 100644
--- a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
+++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
@@ -16,7 +16,6 @@
#define EGMOCK_VERBOSE 1
-#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include <android-base/strings.h>
#include <android/hardware/broadcastradio/2.0/IBroadcastRadio.h>
@@ -25,11 +24,13 @@
#include <android/hardware/broadcastradio/2.0/types.h>
#include <broadcastradio-utils-2x/Utils.h>
#include <broadcastradio-vts-utils/call-barrier.h>
-#include <broadcastradio-vts-utils/environment-utils.h>
#include <broadcastradio-vts-utils/mock-timeout.h>
#include <broadcastradio-vts-utils/pointer-utils.h>
#include <cutils/bitops.h>
#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
#include <chrono>
#include <optional>
@@ -52,7 +53,6 @@
using testing::Invoke;
using testing::SaveArg;
-using broadcastradio::vts::BroadcastRadioHidlEnvironment;
using broadcastradio::vts::CallBarrier;
using broadcastradio::vts::clearAndWait;
using utils::make_identifier;
@@ -100,10 +100,8 @@
MOCK_METHOD1(onListUpdated, Return<void>(const hidl_vec<Announcement>&));
};
-static BroadcastRadioHidlEnvironment<IBroadcastRadio>* gEnv = nullptr;
-
-class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase {
- protected:
+class BroadcastRadioHalTest : public ::testing::TestWithParam<std::string> {
+ protected:
virtual void SetUp() override;
virtual void TearDown() override;
@@ -185,7 +183,7 @@
EXPECT_EQ(nullptr, mModule.get()) << "Module is already open";
// lookup HIDL service (radio module)
- mModule = getService<IBroadcastRadio>(gEnv->getServiceName<IBroadcastRadio>());
+ mModule = IBroadcastRadio::getService(GetParam());
ASSERT_NE(nullptr, mModule.get()) << "Couldn't find broadcast radio HAL implementation";
// get module properties
@@ -243,10 +241,10 @@
auto startResult = mSession->startProgramListUpdates({});
if (startResult == Result::NOT_SUPPORTED) {
printSkipped("Program list not supported");
- return nullopt;
+ return std::nullopt;
}
EXPECT_EQ(Result::OK, startResult);
- if (startResult != Result::OK) return nullopt;
+ if (startResult != Result::OK) return std::nullopt;
EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onProgramListReady, timeout::programListScan);
@@ -264,7 +262,7 @@
* - the method succeeds when called for the second time without
* closing previous session.
*/
-TEST_F(BroadcastRadioHalTest, OpenSession) {
+TEST_P(BroadcastRadioHalTest, OpenSession) {
// simply open session for the first time
ASSERT_TRUE(openSession());
@@ -308,7 +306,7 @@
* - all channel grids (frequency ranges and spacings) are valid;
* - seek spacing is a multiple of the manual spacing value.
*/
-TEST_F(BroadcastRadioHalTest, GetAmFmRegionConfig) {
+TEST_P(BroadcastRadioHalTest, GetAmFmRegionConfig) {
AmFmRegionConfig config;
bool supported = getAmFmRegionConfig(false, &config);
if (!supported) {
@@ -341,7 +339,7 @@
* - all channel grids (frequency ranges and spacings) are valid;
* - seek spacing is not set.
*/
-TEST_F(BroadcastRadioHalTest, GetAmFmRegionConfigCapabilities) {
+TEST_P(BroadcastRadioHalTest, GetAmFmRegionConfigCapabilities) {
AmFmRegionConfig config;
bool supported = getAmFmRegionConfig(true, &config);
if (!supported) {
@@ -369,7 +367,7 @@
* - all channel labels match correct format;
* - all channel frequencies are in correct range.
*/
-TEST_F(BroadcastRadioHalTest, GetDabRegionConfig) {
+TEST_P(BroadcastRadioHalTest, GetDabRegionConfig) {
Result halResult;
hidl_vec<DabTableEntry> config;
auto cb = [&](Result result, hidl_vec<DabTableEntry> configCb) {
@@ -411,7 +409,7 @@
* invoked carrying a proper selector;
* - program changes exactly to what was requested.
*/
-TEST_F(BroadcastRadioHalTest, FmTune) {
+TEST_P(BroadcastRadioHalTest, FmTune) {
ASSERT_TRUE(openSession());
uint64_t freq = 100100; // 100.1 FM
@@ -458,7 +456,7 @@
* - if the selector is not supported, it's ignored;
* - if it is supported, an invalid value results with INVALID_ARGUMENTS;
*/
-TEST_F(BroadcastRadioHalTest, TuneFailsWithInvalid) {
+TEST_P(BroadcastRadioHalTest, TuneFailsWithInvalid) {
ASSERT_TRUE(openSession());
vector<ProgramIdentifier> invalid = {
@@ -489,7 +487,7 @@
* Verifies that:
* - tune fails with NOT_SUPPORTED when program selector is not initialized.
*/
-TEST_F(BroadcastRadioHalTest, TuneFailsWithEmpty) {
+TEST_P(BroadcastRadioHalTest, TuneFailsWithEmpty) {
ASSERT_TRUE(openSession());
// Program type is 1-based, so 0 will always be invalid.
@@ -506,7 +504,7 @@
* - the program info is changed within timeout::tune;
* - works both directions and with or without skipping sub-channel.
*/
-TEST_F(BroadcastRadioHalTest, Seek) {
+TEST_P(BroadcastRadioHalTest, Seek) {
ASSERT_TRUE(openSession());
// TODO(b/69958777): see FmTune workaround
@@ -531,7 +529,7 @@
* - the program info is changed within timeout::tune if the method succeeded;
* - works both directions.
*/
-TEST_F(BroadcastRadioHalTest, Step) {
+TEST_P(BroadcastRadioHalTest, Step) {
ASSERT_TRUE(openSession());
// TODO(b/69958777): see FmTune workaround
@@ -558,7 +556,7 @@
* Verifies that:
* - the method does not crash after being invoked multiple times.
*/
-TEST_F(BroadcastRadioHalTest, Cancel) {
+TEST_P(BroadcastRadioHalTest, Cancel) {
ASSERT_TRUE(openSession());
for (int i = 0; i < 10; i++) {
@@ -576,7 +574,7 @@
* Verifies that:
* - callback is called for empty parameters set.
*/
-TEST_F(BroadcastRadioHalTest, NoParameters) {
+TEST_P(BroadcastRadioHalTest, NoParameters) {
ASSERT_TRUE(openSession());
hidl_vec<VendorKeyValue> halResults = {};
@@ -605,7 +603,7 @@
* - unknown parameters are ignored;
* - callback is called also for empty results set.
*/
-TEST_F(BroadcastRadioHalTest, UnknownParameters) {
+TEST_P(BroadcastRadioHalTest, UnknownParameters) {
ASSERT_TRUE(openSession());
hidl_vec<VendorKeyValue> halResults = {};
@@ -633,7 +631,7 @@
* Verifies that:
* - the method does not crash after being invoked multiple times.
*/
-TEST_F(BroadcastRadioHalTest, Close) {
+TEST_P(BroadcastRadioHalTest, Close) {
ASSERT_TRUE(openSession());
for (int i = 0; i < 10; i++) {
@@ -648,7 +646,7 @@
* Verifies that:
* - getImage call handles argument 0 gracefully.
*/
-TEST_F(BroadcastRadioHalTest, GetNoImage) {
+TEST_P(BroadcastRadioHalTest, GetNoImage) {
size_t len = 0;
auto result = mModule->getImage(0, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
@@ -663,7 +661,7 @@
* - isConfigFlagSet either succeeds or ends with NOT_SUPPORTED or INVALID_STATE;
* - call success or failure is consistent with setConfigFlag.
*/
-TEST_F(BroadcastRadioHalTest, FetchConfigFlags) {
+TEST_P(BroadcastRadioHalTest, FetchConfigFlags) {
ASSERT_TRUE(openSession());
for (auto flag : gConfigFlagValues) {
@@ -691,7 +689,7 @@
* - setConfigFlag either succeeds or ends with NOT_SUPPORTED or INVALID_STATE;
* - isConfigFlagSet reflects the state requested immediately after the set call.
*/
-TEST_F(BroadcastRadioHalTest, SetConfigFlags) {
+TEST_P(BroadcastRadioHalTest, SetConfigFlags) {
ASSERT_TRUE(openSession());
auto get = [&](ConfigFlag flag) {
@@ -743,7 +741,7 @@
* - the complete list is fetched within timeout::programListScan;
* - stopProgramListUpdates does not crash.
*/
-TEST_F(BroadcastRadioHalTest, GetProgramList) {
+TEST_P(BroadcastRadioHalTest, GetProgramList) {
ASSERT_TRUE(openSession());
getProgramList();
@@ -757,7 +755,7 @@
* - the identifier matches the name;
* - there is only one identifier of that type.
*/
-TEST_F(BroadcastRadioHalTest, HdRadioStationNameId) {
+TEST_P(BroadcastRadioHalTest, HdRadioStationNameId) {
ASSERT_TRUE(openSession());
auto list = getProgramList();
@@ -785,7 +783,7 @@
* - if it succeeds, it returns a valid close handle (which is a nullptr otherwise);
* - closing handle does not crash.
*/
-TEST_F(BroadcastRadioHalTest, AnnouncementListenerRegistration) {
+TEST_P(BroadcastRadioHalTest, AnnouncementListenerRegistration) {
sp<AnnouncementListenerMock> listener = new AnnouncementListenerMock();
Result halResult = Result::UNKNOWN_ERROR;
@@ -811,6 +809,11 @@
closeHandle->close();
}
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, BroadcastRadioHalTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(IBroadcastRadio::descriptor)),
+ android::hardware::PrintInstanceNameToString);
+
} // namespace vts
} // namespace V2_0
} // namespace broadcastradio
@@ -818,14 +821,8 @@
} // namespace android
int main(int argc, char** argv) {
- using android::hardware::broadcastradio::V2_0::vts::gEnv;
- using android::hardware::broadcastradio::V2_0::IBroadcastRadio;
- using android::hardware::broadcastradio::vts::BroadcastRadioHidlEnvironment;
android::base::SetDefaultTag("BcRadio.vts");
android::base::SetMinimumLogSeverity(android::base::VERBOSE);
- gEnv = new BroadcastRadioHidlEnvironment<IBroadcastRadio>;
- ::testing::AddGlobalTestEnvironment(gEnv);
::testing::InitGoogleTest(&argc, argv);
- gEnv->init(&argc, argv);
return RUN_ALL_TESTS();
}
diff --git a/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/pointer-utils.h b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/pointer-utils.h
index 0b6f5eb..1d76008 100644
--- a/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/pointer-utils.h
+++ b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/pointer-utils.h
@@ -19,6 +19,8 @@
#include <chrono>
#include <thread>
+using namespace std::chrono_literals;
+
namespace android {
namespace hardware {
namespace broadcastradio {
diff --git a/current.txt b/current.txt
index 57c6f69..a0864da 100644
--- a/current.txt
+++ b/current.txt
@@ -604,10 +604,10 @@
619fc9839ec6e369cfa9b28e3e9412e6885720ff8f9b5750c1b6ffb905120391 android.hardware.wifi.supplicant@1.3::ISupplicantStaIfaceCallback
c9273429fcf98d797d3bb07fdba6f1be95bf960f9255cde169fd1ca4db85f856 android.hardware.wifi.supplicant@1.3::ISupplicantStaNetwork
9b0a3ab6f4f74b971ed094426d8a443e29b512ff03e1ab50c07156396cdb2483 android.hardware.wifi.supplicant@1.3::types
-eaf870a7439838c66127a74e1896c4a2346979c116eb1931785ebb4d353230ae android.hardware.radio@1.5::types
-ae2fd16a80caff9cb6e3f91875c7f68f7ff76c75334056549d38496673eafe5b android.hardware.radio@1.5::IRadio
+0e3c23f1c815469fdcdc39bc33a486817771c7c6b6e5303f2f25569499fc6c69 android.hardware.radio@1.5::types
+52abfa4c94104189fa4b2bc3132fc7c9852b7428283463b020d1a3671a4f374c android.hardware.radio@1.5::IRadio
3afac66f21a33bc9c4b80481c7d5540038348651d9a7d8af64ea13610af138da android.hardware.radio@1.5::IRadioIndication
-e7268d32bedcf7d98324ffc808ec3dc45248d47ff4d04519d09e3c71767a7ad1 android.hardware.radio@1.5::IRadioResponse
+957ffbaf195aa046431ebe05a5906d215e80650e8e4933b394d6454b217ef3a9 android.hardware.radio@1.5::IRadioResponse
55f0a15642869ec98a55ea0a5ac049d3e1a6245ff7750deb6bcb7182057eee83 android.hardware.radio.config@1.3::types
b27ab0cd40b0b078cdcd024bfe1061c4c4c065f3519eeb9347fa359a3268a5ae android.hardware.radio.config@1.3::IRadioConfig
742360c775313438b0f82256eac62fb5bbc76a6ae6f388573f3aa142fb2c1eea android.hardware.radio.config@1.3::IRadioConfigIndication
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp b/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
index 5a75ae1..3702171 100644
--- a/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
@@ -2590,13 +2590,6 @@
std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
- // If the HWC2-side callback hasn't been registered yet, buffer this until
- // it is registered
- if (mCallbacks.count(Callback::Hotplug) == 0) {
- mPendingHotplugs.emplace_back(hwc1DisplayId, connected);
- return;
- }
-
hwc2_display_t displayId = UINT64_MAX;
if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
if (connected == 0) {
@@ -2625,6 +2618,13 @@
mDisplays.erase(displayId);
}
+ // If the HWC2-side callback hasn't been registered yet, buffer this until
+ // it is registered
+ if (mCallbacks.count(Callback::Hotplug) == 0) {
+ mPendingHotplugs.emplace_back(hwc1DisplayId, connected);
+ return;
+ }
+
const auto& callbackInfo = mCallbacks[Callback::Hotplug];
// Call back without the state lock held
diff --git a/radio/1.5/IRadio.hal b/radio/1.5/IRadio.hal
index a4eb93c..a3a3d90 100644
--- a/radio/1.5/IRadio.hal
+++ b/radio/1.5/IRadio.hal
@@ -16,8 +16,10 @@
package android.hardware.radio@1.5;
+import @1.2::DataRequestReason;
import @1.4::IRadio;
import @1.5::AccessNetwork;
+import @1.5::DataProfileInfo;
import @1.5::NetworkScanRequest;
import @1.5::RadioAccessSpecifier;
import @1.5::SignalThresholdInfo;
@@ -118,4 +120,78 @@
* 1.5 version of NetworkScanRequest
*/
oneway startNetworkScan_1_5(int32_t serial, NetworkScanRequest request);
+
+ /**
+ * Setup a packet data connection. If DataCallResponse.status returns DataCallFailCause:NONE,
+ * the data connection must be added to data calls and a unsolDataCallListChanged() must be
+ * sent. The call remains until removed by subsequent unsolDataCallIstChanged(). It may be
+ * lost due to many factors, including deactivateDataCall() being issued, the radio powered
+ * off, reception lost or even transient factors like congestion. This data call list is
+ * returned by getDataCallList() and dataCallListChanged().
+ *
+ * The Radio is expected to:
+ * - Create one data call context.
+ * - Create and configure a dedicated interface for the context.
+ * - The interface must be point to point.
+ * - The interface is configured with one or more addresses and is capable of sending and
+ * receiving packets. The prefix length of the addresses must be /32 for IPv4 and /128
+ * for IPv6.
+ * - Must not modify routing configuration related to this interface; routing management is
+ * exclusively within the purview of the Android OS.
+ * - Support simultaneous data call contexts up to DataRegStateResult.maxDataCalls specified
+ * in the response of getDataRegistrationState.
+ *
+ * @param serial Serial number of request.
+ * @param accessNetwork The access network to setup the data call. If the data connection cannot
+ * be established on the specified access network, the setup request must be failed.
+ * @param dataProfileInfo Data profile info.
+ * @param roamingAllowed Indicates whether or not data roaming is allowed by the user.
+ * @param reason The request reason. Must be DataRequestReason.NORMAL or
+ * DataRequestReason.HANDOVER.
+ * @param addresses If the reason is DataRequestReason.HANDOVER, this indicates the list of link
+ * addresses of the existing data connection. The format is IP address with optional "/"
+ * prefix length (The format is defined in RFC-4291 section 2.3). For example, "192.0.1.3",
+ * "192.0.1.11/16", or "2001:db8::1/64". Typically one IPv4 or one IPv6 or one of each. If
+ * the prefix length is absent, then the addresses are assumed to be point to point with
+ * IPv4 with prefix length 32 or IPv6 with prefix length 128. This parameter must be ignored
+ * unless reason is DataRequestReason.HANDOVER.
+ * @param dnses If the reason is DataRequestReason.HANDOVER, this indicates the list of DNS
+ * addresses of the existing data connection. The format is defined in RFC-4291 section
+ * 2.2. For example, "192.0.1.3" or "2001:db8::1". This parameter must be ignored unless
+ * reason is DataRequestReason.HANDOVER.
+ *
+ * Response function is IRadioResponse.setupDataCallResponse_1_5()
+ *
+ * Note this API is the same as the 1.4 version except using the
+ * 1.5 AccessNetwork and DataProfileInto as the input param.
+ */
+ oneway setupDataCall_1_5(int32_t serial, AccessNetwork accessNetwork,
+ DataProfileInfo dataProfileInfo, bool roamingAllowed,
+ DataRequestReason reason, vec<string> addresses, vec<string> dnses);
+
+ /**
+ * Set an apn to initial attach network
+ *
+ * @param serial Serial number of request.
+ * @param dataProfileInfo data profile containing APN settings
+ *
+ * Response callback is IRadioResponse.setInitialAttachApnResponse_1_5()
+ *
+ * Note this API is the same as the 1.4 version except using the 1.5 DataProfileInfo
+ * as the input param.
+ */
+ oneway setInitialAttachApn_1_5(int32_t serial, DataProfileInfo dataProfileInfo);
+
+ /**
+ * Send data profiles of the current carrier to the modem.
+ *
+ * @param serial Serial number of request.
+ * @param profiles Array of DataProfile to set.
+ *
+ * Response callback is IRadioResponse.setDataProfileResponse_1_5()
+ *
+ * Note this API is the same as the 1.4 version except using the 1.5 DataProfileInfo
+ * as the input param.
+ */
+ oneway setDataProfile_1_5(int32_t serial, vec<DataProfileInfo> profiles);
};
diff --git a/radio/1.5/IRadioResponse.hal b/radio/1.5/IRadioResponse.hal
index 505c595..11ec265 100644
--- a/radio/1.5/IRadioResponse.hal
+++ b/radio/1.5/IRadioResponse.hal
@@ -18,6 +18,7 @@
import @1.0::RadioResponseInfo;
import @1.4::IRadioResponse;
+import @1.4::SetupDataCallResult;
/**
* Interface declaring response functions to solicited radio requests.
@@ -80,4 +81,58 @@
* RadioError:INVALID_ARGUMENTS
*/
oneway startNetworkScanResponse_1_5(RadioResponseInfo info);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param dcResponse SetupDataCallResult defined in types.hal
+ *
+ * Valid errors returned:
+ * RadioError:NONE must be returned on both success and failure of setup with the
+ * DataCallResponse.status containing the actual status
+ * For all other errors the DataCallResponse is ignored.
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:OP_NOT_ALLOWED_BEFORE_REG_TO_NW
+ * RadioError:OP_NOT_ALLOWED_DURING_VOICE_CALL
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:INTERNAL_ERR
+ * RadioError:NO_RESOURCES
+ * RadioError:SIM_ABSENT
+ */
+ oneway setupDataCallResponse_1_5(RadioResponseInfo info, SetupDataCallResult dcResponse);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:SUBSCRIPTION_NOT_AVAILABLE
+ * RadioError:NO_MEMORY
+ * RadioError:INTERNAL_ERR
+ * RadioError:SYSTEM_ERR
+ * RadioError:MODEM_ERR
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:NOT_PROVISIONED
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:NO_RESOURCES
+ * RadioError:CANCELLED
+ */
+ oneway setInitialAttachApnResponse_1_5(RadioResponseInfo info);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:SUBSCRIPTION_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ * RadioError:NO_MEMORY
+ * RadioError:NO_RESOURCES
+ * RadioError:CANCELLED
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:SIM_ABSENT
+ */
+ oneway setDataProfileResponse_1_5(RadioResponseInfo info);
};
diff --git a/radio/1.5/types.hal b/radio/1.5/types.hal
index 04a9bcf..5795f7b 100644
--- a/radio/1.5/types.hal
+++ b/radio/1.5/types.hal
@@ -24,6 +24,8 @@
import @1.1::UtranBands;
import @1.2::NetworkScanRequest;
import @1.4::AccessNetwork;
+import @1.4::ApnTypes;
+import @1.4::DataProfileInfo;
/**
* Defining signal strength type.
@@ -268,3 +270,22 @@
*/
vec<string> mccMncs;
};
+
+enum ApnTypes : @1.4::ApnTypes {
+ /**
+ * APN type for XCAP
+ * NOTE: Due to the addition of this new value, the value ALL defined in
+ * 1.0::ApnTypes is deprecated and should not be used.
+ */
+ XCAP = 1 << 11,
+};
+
+/**
+ * Extended from @1.4::DataProfileInfo to update ApnTypes to 1.5 version
+ */
+struct DataProfileInfo {
+ @1.4::DataProfileInfo base;
+
+ /** Supported APN types bitmap. See ApnTypes for the value of each bit. */
+ bitfield<ApnTypes> supportedApnTypesBitmap;
+};
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
index 67438ae..1243bed 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
@@ -821,3 +821,140 @@
RadioError::REQUEST_NOT_SUPPORTED}));
}
}
+
+/*
+ * Test IRadio.setupDataCall_1_5() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_5, setupDataCall_1_5) {
+ serial = GetRandomSerialNumber();
+
+ ::android::hardware::radio::V1_5::AccessNetwork accessNetwork =
+ ::android::hardware::radio::V1_5::AccessNetwork::EUTRAN;
+
+ android::hardware::radio::V1_5::DataProfileInfo dataProfileInfo;
+ memset(&dataProfileInfo, 0, sizeof(dataProfileInfo));
+ dataProfileInfo.base.profileId = DataProfileId::DEFAULT;
+ dataProfileInfo.base.apn = hidl_string("internet");
+ dataProfileInfo.base.protocol = PdpProtocolType::IP;
+ dataProfileInfo.base.roamingProtocol = PdpProtocolType::IP;
+ dataProfileInfo.base.authType = ApnAuthType::NO_PAP_NO_CHAP;
+ dataProfileInfo.base.user = hidl_string("username");
+ dataProfileInfo.base.password = hidl_string("password");
+ dataProfileInfo.base.type = DataProfileInfoType::THREE_GPP;
+ dataProfileInfo.base.maxConnsTime = 300;
+ dataProfileInfo.base.maxConns = 20;
+ dataProfileInfo.base.waitTime = 0;
+ dataProfileInfo.base.enabled = true;
+ dataProfileInfo.supportedApnTypesBitmap = 320;
+ dataProfileInfo.base.bearerBitmap = 161543;
+ dataProfileInfo.base.mtu = 0;
+ dataProfileInfo.base.preferred = true;
+ dataProfileInfo.base.persistent = false;
+
+ bool roamingAllowed = false;
+
+ ::android::hardware::radio::V1_2::DataRequestReason reason =
+ ::android::hardware::radio::V1_2::DataRequestReason::NORMAL;
+ std::vector<hidl_string> addresses = {""};
+ std::vector<hidl_string> dnses = {""};
+
+ Return<void> res = radio_v1_5->setupDataCall_1_5(serial, accessNetwork, dataProfileInfo,
+ roamingAllowed, reason, addresses, dnses);
+ ASSERT_OK(res);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
+ }
+}
+
+TEST_F(RadioHidlTest_v1_5, setInitialAttachApn_1_5) {
+ serial = GetRandomSerialNumber();
+
+ // Create a dataProfileInfo
+ android::hardware::radio::V1_5::DataProfileInfo dataProfileInfo;
+ memset(&dataProfileInfo, 0, sizeof(dataProfileInfo));
+ dataProfileInfo.base.profileId = DataProfileId::DEFAULT;
+ dataProfileInfo.base.apn = hidl_string("internet");
+ dataProfileInfo.base.protocol = PdpProtocolType::IPV4V6;
+ dataProfileInfo.base.roamingProtocol = PdpProtocolType::IPV4V6;
+ dataProfileInfo.base.authType = ApnAuthType::NO_PAP_NO_CHAP;
+ dataProfileInfo.base.user = hidl_string("username");
+ dataProfileInfo.base.password = hidl_string("password");
+ dataProfileInfo.base.type = DataProfileInfoType::THREE_GPP;
+ dataProfileInfo.base.maxConnsTime = 300;
+ dataProfileInfo.base.maxConns = 20;
+ dataProfileInfo.base.waitTime = 0;
+ dataProfileInfo.base.enabled = true;
+ dataProfileInfo.supportedApnTypesBitmap = 320;
+ dataProfileInfo.base.bearerBitmap = 161543;
+ dataProfileInfo.base.mtu = 0;
+ dataProfileInfo.base.preferred = true;
+ dataProfileInfo.base.persistent = false;
+
+ radio_v1_5->setInitialAttachApn_1_5(serial, dataProfileInfo);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE}));
+ }
+}
+
+TEST_F(RadioHidlTest_v1_5, setDataProfile_1_5) {
+ serial = GetRandomSerialNumber();
+
+ // Create a dataProfileInfo
+ android::hardware::radio::V1_5::DataProfileInfo dataProfileInfo;
+ memset(&dataProfileInfo, 0, sizeof(dataProfileInfo));
+ dataProfileInfo.base.profileId = DataProfileId::DEFAULT;
+ dataProfileInfo.base.apn = hidl_string("internet");
+ dataProfileInfo.base.protocol = PdpProtocolType::IPV4V6;
+ dataProfileInfo.base.roamingProtocol = PdpProtocolType::IPV4V6;
+ dataProfileInfo.base.authType = ApnAuthType::NO_PAP_NO_CHAP;
+ dataProfileInfo.base.user = hidl_string("username");
+ dataProfileInfo.base.password = hidl_string("password");
+ dataProfileInfo.base.type = DataProfileInfoType::THREE_GPP;
+ dataProfileInfo.base.maxConnsTime = 300;
+ dataProfileInfo.base.maxConns = 20;
+ dataProfileInfo.base.waitTime = 0;
+ dataProfileInfo.base.enabled = true;
+ dataProfileInfo.supportedApnTypesBitmap = 320;
+ dataProfileInfo.base.bearerBitmap = 161543;
+ dataProfileInfo.base.mtu = 0;
+ dataProfileInfo.base.preferred = true;
+ dataProfileInfo.base.persistent = true;
+
+ // Create a dataProfileInfoList
+ android::hardware::hidl_vec<android::hardware::radio::V1_5::DataProfileInfo>
+ dataProfileInfoList = {dataProfileInfo};
+
+ radio_v1_5->setDataProfile_1_5(serial, dataProfileInfoList);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE}));
+ }
+}
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h b/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
index 01bda69..f7526d9 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
+++ b/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
@@ -541,6 +541,14 @@
Return<void> setSystemSelectionChannelsResponse_1_5(const RadioResponseInfo& info);
Return<void> startNetworkScanResponse_1_5(const RadioResponseInfo& info);
+
+ Return<void> setupDataCallResponse_1_5(
+ const RadioResponseInfo& info,
+ const android::hardware::radio::V1_4::SetupDataCallResult& dcResponse);
+
+ Return<void> setInitialAttachApnResponse_1_5(const RadioResponseInfo& info);
+
+ Return<void> setDataProfileResponse_1_5(const RadioResponseInfo& info);
};
/* Callback class for radio indication */
diff --git a/radio/1.5/vts/functional/radio_response.cpp b/radio/1.5/vts/functional/radio_response.cpp
index 5964c96..5dee191 100644
--- a/radio/1.5/vts/functional/radio_response.cpp
+++ b/radio/1.5/vts/functional/radio_response.cpp
@@ -928,3 +928,23 @@
parent_v1_5.notify(info.serial);
return Void();
}
+
+Return<void> RadioResponse_v1_5::setupDataCallResponse_1_5(
+ const RadioResponseInfo& info,
+ const android::hardware::radio::V1_4::SetupDataCallResult& /* dcResponse */) {
+ rspInfo = info;
+ parent_v1_5.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_5::setInitialAttachApnResponse_1_5(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_5.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_5::setDataProfileResponse_1_5(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_5.notify(info.serial);
+ return Void();
+}
diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
index ebf5faa..f553664 100644
--- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
@@ -48,6 +48,10 @@
* Whether compose is supported.
*/
const int CAP_COMPOSE_EFFECTS = 1 << 5;
+ /**
+ * Whether alwaysOnEnable/alwaysOnDisable is supported.
+ */
+ const int CAP_ALWAYS_ON_CONTROL = 1 << 6;
/**
* Determine capabilities of the vibrator HAL (CAP_* mask)
@@ -165,4 +169,31 @@
*/
void compose(in CompositeEffect[] composite, in IVibratorCallback callback);
+ /**
+ * List of supported always-on effects.
+ *
+ * Return the effects which are supported by the alwaysOnEnable (an effect
+ * is expected to be supported at every strength level.
+ */
+ Effect[] getSupportedAlwaysOnEffects();
+
+ /**
+ * Enable an always-on haptic source, assigning a specific effect. An
+ * always-on haptic source is a source that can be triggered externally
+ * once enabled and assigned an effect to play. This may not be supported
+ * and this support is reflected in getCapabilities (CAP_ALWAYS_ON_CONTROL).
+ *
+ * @param id The device-specific always-on source ID to enable.
+ * @param effect The type of haptic event to trigger.
+ * @param strength The intensity of haptic event to trigger.
+ */
+ void alwaysOnEnable(in int id, in Effect effect, in EffectStrength strength);
+
+ /**
+ * Disable an always-on haptic source. This may not be supported and this
+ * support is reflected in getCapabilities (CAP_ALWAYS_ON_CONTROL).
+ *
+ * @param id The device-specific always-on source ID to disable.
+ */
+ void alwaysOnDisable(in int id);
}
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index befdeab..cedd9cb 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -31,7 +31,8 @@
LOG(INFO) << "Vibrator reporting capabilities";
*_aidl_return = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK |
IVibrator::CAP_AMPLITUDE_CONTROL | IVibrator::CAP_EXTERNAL_CONTROL |
- IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL | IVibrator::CAP_COMPOSE_EFFECTS;
+ IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL | IVibrator::CAP_COMPOSE_EFFECTS |
+ IVibrator::CAP_ALWAYS_ON_CONTROL;
return ndk::ScopedAStatus::ok();
}
@@ -151,6 +152,28 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus Vibrator::getSupportedAlwaysOnEffects(std::vector<Effect>* _aidl_return) {
+ return getSupportedEffects(_aidl_return);
+}
+
+ndk::ScopedAStatus Vibrator::alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) {
+ std::vector<Effect> effects;
+ getSupportedAlwaysOnEffects(&effects);
+
+ if (std::find(effects.begin(), effects.end(), effect) == effects.end()) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ } else {
+ LOG(INFO) << "Enabling always-on ID " << id << " with " << toString(effect) << "/"
+ << toString(strength);
+ return ndk::ScopedAStatus::ok();
+ }
+}
+
+ndk::ScopedAStatus Vibrator::alwaysOnDisable(int32_t id) {
+ LOG(INFO) << "Disabling always-on ID " << id;
+ return ndk::ScopedAStatus::ok();
+}
+
} // namespace vibrator
} // namespace hardware
} // namespace android
diff --git a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
index 817ec80..0eb957d 100644
--- a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
+++ b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
@@ -38,6 +38,9 @@
ndk::ScopedAStatus getCompositionSizeMax(int32_t* maxSize);
ndk::ScopedAStatus compose(const std::vector<CompositeEffect>& composite,
const std::shared_ptr<IVibratorCallback>& callback) override;
+ ndk::ScopedAStatus getSupportedAlwaysOnEffects(std::vector<Effect>* _aidl_return) override;
+ ndk::ScopedAStatus alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) override;
+ ndk::ScopedAStatus alwaysOnDisable(int32_t id) override;
};
} // namespace vibrator
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index 6f9ba1a..f47b10d 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -370,6 +370,32 @@
}
}
+TEST_P(VibratorAidl, AlwaysOn) {
+ if (capabilities & IVibrator::CAP_ALWAYS_ON_CONTROL) {
+ std::vector<Effect> supported;
+ ASSERT_TRUE(vibrator->getSupportedAlwaysOnEffects(&supported).isOk());
+
+ for (Effect effect : kEffects) {
+ bool isEffectSupported =
+ std::find(supported.begin(), supported.end(), effect) != supported.end();
+
+ for (EffectStrength strength : kEffectStrengths) {
+ Status status = vibrator->alwaysOnEnable(0, effect, strength);
+
+ if (isEffectSupported) {
+ EXPECT_EQ(Status::EX_NONE, status.exceptionCode())
+ << toString(effect) << " " << toString(strength);
+ } else {
+ EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode())
+ << toString(effect) << " " << toString(strength);
+ }
+ }
+ }
+
+ EXPECT_EQ(Status::EX_NONE, vibrator->alwaysOnDisable(0).exceptionCode());
+ }
+}
+
INSTANTIATE_TEST_SUITE_P(Vibrator, VibratorAidl,
testing::ValuesIn(android::getAidlHalInstanceNames(IVibrator::descriptor)),
android::PrintInstanceNameToString);