Merge "Move android.hardware.health@2.0-impl to hardware/interfaces"
diff --git a/broadcastradio/1.1/vts/functional/Android.bp b/broadcastradio/1.1/vts/functional/Android.bp
index c016c16..27ae4e9 100644
--- a/broadcastradio/1.1/vts/functional/Android.bp
+++ b/broadcastradio/1.1/vts/functional/Android.bp
@@ -22,7 +22,7 @@
"android.hardware.broadcastradio@1.0",
"android.hardware.broadcastradio@1.1",
"android.hardware.broadcastradio@1.2", // common-utils-lib dependency
- "android.hardware.broadcastradio@common-utils-lib",
+ "android.hardware.broadcastradio@common-utils-1x-lib",
"android.hardware.broadcastradio@vts-utils-lib",
"libgmock",
],
diff --git a/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp b/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
index bb490c9..823d14c 100644
--- a/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
+++ b/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
@@ -17,15 +17,16 @@
#define LOG_TAG "broadcastradio.vts"
#include <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
#include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
#include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
#include <android/hardware/broadcastradio/1.1/ITuner.h>
#include <android/hardware/broadcastradio/1.1/ITunerCallback.h>
#include <android/hardware/broadcastradio/1.1/types.h>
-#include <android-base/logging.h>
-#include <broadcastradio-utils/Utils.h>
+#include <broadcastradio-utils-1x/Utils.h>
#include <broadcastradio-vts-utils/call-barrier.h>
#include <broadcastradio-vts-utils/mock-timeout.h>
+#include <broadcastradio-vts-utils/pointer-utils.h>
#include <cutils/native_handle.h>
#include <cutils/properties.h>
#include <gmock/gmock.h>
@@ -56,8 +57,7 @@
using V1_0::MetadataKey;
using V1_0::MetadataType;
-using std::chrono::steady_clock;
-using std::this_thread::sleep_for;
+using broadcastradio::vts::clearAndWait;
static constexpr auto kConfigTimeout = 10s;
static constexpr auto kConnectModuleTimeout = 1s;
@@ -115,27 +115,6 @@
hidl_vec<BandConfig> mBands;
};
-/**
- * Clears strong pointer and waits until the object gets destroyed.
- *
- * @param ptr The pointer to get cleared.
- * @param timeout Time to wait for other references.
- */
-template <typename T>
-static void clearAndWait(sp<T>& ptr, std::chrono::milliseconds timeout) {
- wp<T> wptr = ptr;
- ptr.clear();
- auto limit = steady_clock::now() + timeout;
- while (wptr.promote() != nullptr) {
- constexpr auto step = 10ms;
- if (steady_clock::now() + step > limit) {
- FAIL() << "Pointer was not released within timeout";
- break;
- }
- sleep_for(step);
- }
-}
-
void BroadcastRadioHalTest::SetUp() {
radioClass = GetParam();
diff --git a/broadcastradio/1.2/default/Android.bp b/broadcastradio/1.2/default/Android.bp
index e42cb1e..bd4be77 100644
--- a/broadcastradio/1.2/default/Android.bp
+++ b/broadcastradio/1.2/default/Android.bp
@@ -33,6 +33,7 @@
"service.cpp"
],
static_libs: [
+ "android.hardware.broadcastradio@common-utils-1x-lib",
"android.hardware.broadcastradio@common-utils-lib",
],
shared_libs: [
diff --git a/broadcastradio/1.2/default/Tuner.cpp b/broadcastradio/1.2/default/Tuner.cpp
index 6209dc1..f589332 100644
--- a/broadcastradio/1.2/default/Tuner.cpp
+++ b/broadcastradio/1.2/default/Tuner.cpp
@@ -20,7 +20,7 @@
#include "BroadcastRadio.h"
#include "Tuner.h"
-#include <broadcastradio-utils/Utils.h>
+#include <broadcastradio-utils-1x/Utils.h>
#include <log/log.h>
namespace android {
diff --git a/broadcastradio/1.2/default/VirtualProgram.cpp b/broadcastradio/1.2/default/VirtualProgram.cpp
index 3284bd1..3594f64 100644
--- a/broadcastradio/1.2/default/VirtualProgram.cpp
+++ b/broadcastradio/1.2/default/VirtualProgram.cpp
@@ -15,7 +15,7 @@
*/
#include "VirtualProgram.h"
-#include <broadcastradio-utils/Utils.h>
+#include <broadcastradio-utils-1x/Utils.h>
#include "resources.h"
@@ -83,13 +83,6 @@
if (l.primaryId.type != r.primaryId.type) return l.primaryId.type < r.primaryId.type;
if (l.primaryId.value != r.primaryId.value) return l.primaryId.value < r.primaryId.value;
- // A little exception for HD Radio subchannel - we check secondary ID too.
- if (utils::hasId(l, IdentifierType::HD_SUBCHANNEL) &&
- utils::hasId(r, IdentifierType::HD_SUBCHANNEL)) {
- return utils::getId(l, IdentifierType::HD_SUBCHANNEL) <
- utils::getId(r, IdentifierType::HD_SUBCHANNEL);
- }
-
return false;
}
diff --git a/broadcastradio/1.2/default/VirtualProgram.h b/broadcastradio/1.2/default/VirtualProgram.h
index 5342c84..c0b20f0 100644
--- a/broadcastradio/1.2/default/VirtualProgram.h
+++ b/broadcastradio/1.2/default/VirtualProgram.h
@@ -17,7 +17,7 @@
#define ANDROID_HARDWARE_BROADCASTRADIO_V1_2_VIRTUALPROGRAM_H
#include <android/hardware/broadcastradio/1.2/types.h>
-#include <broadcastradio-utils/Utils.h>
+#include <broadcastradio-utils-1x/Utils.h>
namespace android {
namespace hardware {
diff --git a/broadcastradio/1.2/default/VirtualRadio.cpp b/broadcastradio/1.2/default/VirtualRadio.cpp
index 867726d..8988080 100644
--- a/broadcastradio/1.2/default/VirtualRadio.cpp
+++ b/broadcastradio/1.2/default/VirtualRadio.cpp
@@ -18,7 +18,7 @@
#include "VirtualRadio.h"
-#include <broadcastradio-utils/Utils.h>
+#include <broadcastradio-utils-1x/Utils.h>
#include <log/log.h>
namespace android {
diff --git a/broadcastradio/1.2/vts/functional/Android.bp b/broadcastradio/1.2/vts/functional/Android.bp
index 12da14e..fd1c254 100644
--- a/broadcastradio/1.2/vts/functional/Android.bp
+++ b/broadcastradio/1.2/vts/functional/Android.bp
@@ -22,7 +22,6 @@
"android.hardware.broadcastradio@1.0",
"android.hardware.broadcastradio@1.1",
"android.hardware.broadcastradio@1.2",
- "android.hardware.broadcastradio@common-utils-lib",
"android.hardware.broadcastradio@vts-utils-lib",
"libgmock",
],
diff --git a/broadcastradio/1.2/vts/functional/VtsHalBroadcastradioV1_2TargetTest.cpp b/broadcastradio/1.2/vts/functional/VtsHalBroadcastradioV1_2TargetTest.cpp
index f3552a8..085206b 100644
--- a/broadcastradio/1.2/vts/functional/VtsHalBroadcastradioV1_2TargetTest.cpp
+++ b/broadcastradio/1.2/vts/functional/VtsHalBroadcastradioV1_2TargetTest.cpp
@@ -17,15 +17,15 @@
#define LOG_TAG "broadcastradio.vts"
#include <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
#include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
#include <android/hardware/broadcastradio/1.2/IBroadcastRadioFactory.h>
#include <android/hardware/broadcastradio/1.2/ITuner.h>
#include <android/hardware/broadcastradio/1.2/ITunerCallback.h>
#include <android/hardware/broadcastradio/1.2/types.h>
-#include <android-base/logging.h>
-#include <broadcastradio-utils/Utils.h>
#include <broadcastradio-vts-utils/call-barrier.h>
#include <broadcastradio-vts-utils/mock-timeout.h>
+#include <broadcastradio-vts-utils/pointer-utils.h>
#include <cutils/native_handle.h>
#include <cutils/properties.h>
#include <gmock/gmock.h>
@@ -61,8 +61,7 @@
using V1_1::ProgramSelector;
using V1_1::Properties;
-using std::chrono::steady_clock;
-using std::this_thread::sleep_for;
+using broadcastradio::vts::clearAndWait;
static constexpr auto kConfigTimeout = 10s;
static constexpr auto kConnectModuleTimeout = 1s;
@@ -111,27 +110,6 @@
hidl_vec<BandConfig> mBands;
};
-/**
- * Clears strong pointer and waits until the object gets destroyed.
- *
- * @param ptr The pointer to get cleared.
- * @param timeout Time to wait for other references.
- */
-template <typename T>
-static void clearAndWait(sp<T>& ptr, std::chrono::milliseconds timeout) {
- wp<T> wptr = ptr;
- ptr.clear();
- auto limit = steady_clock::now() + timeout;
- while (wptr.promote() != nullptr) {
- constexpr auto step = 10ms;
- if (steady_clock::now() + step > limit) {
- FAIL() << "Pointer was not released within timeout";
- break;
- }
- sleep_for(step);
- }
-}
-
void BroadcastRadioHalTest::SetUp() {
radioClass = GetParam();
diff --git a/broadcastradio/2.0/default/Android.bp b/broadcastradio/2.0/default/Android.bp
new file mode 100644
index 0000000..6d4effb
--- /dev/null
+++ b/broadcastradio/2.0/default/Android.bp
@@ -0,0 +1,46 @@
+//
+// 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_binary {
+ name: "android.hardware.broadcastradio@2.0-service",
+ init_rc: ["android.hardware.broadcastradio@2.0-service.rc"],
+ vendor: true,
+ relative_install_path: "hw",
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+ srcs: [
+ "BroadcastRadio.cpp",
+ "TunerSession.cpp",
+ "VirtualProgram.cpp",
+ "VirtualRadio.cpp",
+ "service.cpp"
+ ],
+ static_libs: [
+ "android.hardware.broadcastradio@common-utils-2x-lib",
+ "android.hardware.broadcastradio@common-utils-lib",
+ ],
+ shared_libs: [
+ "android.hardware.broadcastradio@2.0",
+ "libbase",
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+ "libutils",
+ ],
+}
diff --git a/broadcastradio/2.0/default/BroadcastRadio.cpp b/broadcastradio/2.0/default/BroadcastRadio.cpp
new file mode 100644
index 0000000..5ab517d
--- /dev/null
+++ b/broadcastradio/2.0/default/BroadcastRadio.cpp
@@ -0,0 +1,98 @@
+/*
+ * 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 "BcRadioDef.module"
+#define LOG_NDEBUG 0
+
+#include "BroadcastRadio.h"
+
+#include <log/log.h>
+
+#include "resources.h"
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V2_0 {
+namespace implementation {
+
+using std::lock_guard;
+using std::map;
+using std::mutex;
+using std::vector;
+
+static Properties initProperties(const VirtualRadio& virtualRadio) {
+ Properties prop = {};
+
+ prop.maker = "Google";
+ prop.product = virtualRadio.getName();
+ prop.supportedIdentifierTypes = hidl_vec<uint32_t>({
+ static_cast<uint32_t>(IdentifierType::AMFM_FREQUENCY),
+ static_cast<uint32_t>(IdentifierType::RDS_PI),
+ static_cast<uint32_t>(IdentifierType::HD_STATION_ID_EXT),
+ });
+ prop.vendorInfo = hidl_vec<VendorKeyValue>({
+ {"com.google.dummy", "dummy"},
+ });
+
+ return prop;
+}
+
+BroadcastRadio::BroadcastRadio(const VirtualRadio& virtualRadio)
+ : mVirtualRadio(virtualRadio), mProperties(initProperties(virtualRadio)) {}
+
+Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb) {
+ ALOGV("%s", __func__);
+ _hidl_cb(mProperties);
+ return {};
+}
+
+Return<void> BroadcastRadio::openSession(const sp<ITunerCallback>& callback,
+ openSession_cb _hidl_cb) {
+ ALOGV("%s", __func__);
+ lock_guard<mutex> lk(mMut);
+
+ auto oldSession = mSession.promote();
+ if (oldSession != nullptr) {
+ ALOGI("Closing previously opened tuner");
+ oldSession->close();
+ mSession = nullptr;
+ }
+
+ sp<TunerSession> newSession = new TunerSession(*this, callback);
+ mSession = newSession;
+
+ _hidl_cb(Result::OK, newSession);
+ return {};
+}
+
+Return<void> BroadcastRadio::getImage(uint32_t id, getImage_cb _hidl_cb) {
+ ALOGV("%s(%x)", __func__, id);
+
+ if (id == resources::demoPngId) {
+ _hidl_cb(std::vector<uint8_t>(resources::demoPng, std::end(resources::demoPng)));
+ return {};
+ }
+
+ ALOGI("Image %x doesn't exists", id);
+ _hidl_cb({});
+ return {};
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace broadcastradio
+} // namespace hardware
+} // namespace android
diff --git a/broadcastradio/2.0/default/BroadcastRadio.h b/broadcastradio/2.0/default/BroadcastRadio.h
new file mode 100644
index 0000000..fcf0615
--- /dev/null
+++ b/broadcastradio/2.0/default/BroadcastRadio.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V2_0_BROADCASTRADIO_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V2_0_BROADCASTRADIO_H
+
+#include "TunerSession.h"
+
+#include <android/hardware/broadcastradio/2.0/IBroadcastRadio.h>
+#include <android/hardware/broadcastradio/2.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V2_0 {
+namespace implementation {
+
+struct BroadcastRadio : public IBroadcastRadio {
+ BroadcastRadio(const VirtualRadio& virtualRadio);
+
+ // V2_0::IBroadcastRadio methods
+ Return<void> getProperties(getProperties_cb _hidl_cb) override;
+ Return<void> openSession(const sp<ITunerCallback>& callback, openSession_cb _hidl_cb) override;
+ Return<void> getImage(uint32_t id, getImage_cb _hidl_cb);
+
+ std::reference_wrapper<const VirtualRadio> mVirtualRadio;
+ Properties mProperties;
+
+ private:
+ std::mutex mMut;
+ wp<TunerSession> mSession;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace broadcastradio
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_BROADCASTRADIO_V2_0_BROADCASTRADIO_H
diff --git a/broadcastradio/common/utils/OWNERS b/broadcastradio/2.0/default/OWNERS
similarity index 100%
copy from broadcastradio/common/utils/OWNERS
copy to broadcastradio/2.0/default/OWNERS
diff --git a/broadcastradio/2.0/default/TunerSession.cpp b/broadcastradio/2.0/default/TunerSession.cpp
new file mode 100644
index 0000000..f0b98b8
--- /dev/null
+++ b/broadcastradio/2.0/default/TunerSession.cpp
@@ -0,0 +1,238 @@
+/*
+ * 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 "BcRadioDef.tuner"
+#define LOG_NDEBUG 0
+
+#include "TunerSession.h"
+
+#include "BroadcastRadio.h"
+
+#include <broadcastradio-utils-2x/Utils.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V2_0 {
+namespace implementation {
+
+using namespace std::chrono_literals;
+
+using utils::tunesTo;
+
+using std::lock_guard;
+using std::move;
+using std::mutex;
+using std::sort;
+using std::vector;
+
+namespace delay {
+
+static constexpr auto scan = 200ms;
+static constexpr auto step = 100ms;
+static constexpr auto tune = 150ms;
+
+} // namespace delay
+
+TunerSession::TunerSession(BroadcastRadio& module, const sp<ITunerCallback>& callback)
+ : mCallback(callback), mModule(module) {}
+
+// makes ProgramInfo that points to no program
+static ProgramInfo makeDummyProgramInfo(const ProgramSelector& selector) {
+ ProgramInfo info = {};
+ info.selector = selector;
+ return info;
+}
+
+void TunerSession::tuneInternalLocked(const ProgramSelector& sel) {
+ VirtualProgram virtualProgram;
+ ProgramInfo programInfo;
+ if (virtualRadio().getProgram(sel, virtualProgram)) {
+ mCurrentProgram = virtualProgram.selector;
+ programInfo = virtualProgram;
+ } else {
+ mCurrentProgram = sel;
+ programInfo = makeDummyProgramInfo(sel);
+ }
+ mIsTuneCompleted = true;
+
+ mCallback->onCurrentProgramInfoChanged(programInfo);
+}
+
+const VirtualRadio& TunerSession::virtualRadio() const {
+ return mModule.get().mVirtualRadio;
+}
+
+Return<Result> TunerSession::tune(const ProgramSelector& sel) {
+ ALOGV("%s(%s)", __func__, toString(sel).c_str());
+ lock_guard<mutex> lk(mMut);
+ if (mIsClosed) return Result::INVALID_STATE;
+
+ if (!utils::isSupported(mModule.get().mProperties, sel)) {
+ ALOGW("Selector not supported");
+ return Result::NOT_SUPPORTED;
+ }
+
+ if (!utils::isValid(sel)) {
+ ALOGE("ProgramSelector is not valid");
+ return Result::INVALID_ARGUMENTS;
+ }
+
+ mIsTuneCompleted = false;
+ auto task = [this, sel]() {
+ lock_guard<mutex> lk(mMut);
+ tuneInternalLocked(sel);
+ };
+ mThread.schedule(task, delay::tune);
+
+ return Result::OK;
+}
+
+Return<Result> TunerSession::scan(bool directionUp, bool /* skipSubChannel */) {
+ ALOGV("%s", __func__);
+ lock_guard<mutex> lk(mMut);
+ if (mIsClosed) return Result::INVALID_STATE;
+
+ auto list = virtualRadio().getProgramList();
+
+ if (list.empty()) {
+ mIsTuneCompleted = false;
+ auto task = [this, directionUp]() {
+ ALOGI("Performing failed scan up=%d", directionUp);
+
+ mCallback->onTuneFailed(Result::TIMEOUT, {});
+ };
+ mThread.schedule(task, delay::scan);
+
+ return Result::OK;
+ }
+
+ // Not optimal (O(sort) instead of O(n)), but not a big deal here;
+ // also, it's likely that list is already sorted (so O(n) anyway).
+ sort(list.begin(), list.end());
+ auto current = mCurrentProgram;
+ auto found = lower_bound(list.begin(), list.end(), VirtualProgram({current}));
+ if (directionUp) {
+ if (found < list.end() - 1) {
+ if (tunesTo(current, found->selector)) found++;
+ } else {
+ found = list.begin();
+ }
+ } else {
+ if (found > list.begin() && found != list.end()) {
+ found--;
+ } else {
+ found = list.end() - 1;
+ }
+ }
+ auto tuneTo = found->selector;
+
+ mIsTuneCompleted = false;
+ auto task = [this, tuneTo, directionUp]() {
+ ALOGI("Performing scan up=%d", directionUp);
+
+ lock_guard<mutex> lk(mMut);
+ tuneInternalLocked(tuneTo);
+ };
+ mThread.schedule(task, delay::scan);
+
+ return Result::OK;
+}
+
+Return<Result> TunerSession::step(bool directionUp) {
+ ALOGV("%s", __func__);
+ lock_guard<mutex> lk(mMut);
+ if (mIsClosed) return Result::INVALID_STATE;
+
+ if (!utils::hasId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY)) {
+ ALOGE("Can't step in anything else than AM/FM");
+ return Result::NOT_SUPPORTED;
+ }
+
+ mIsTuneCompleted = false;
+
+ auto stepTo = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY);
+#if 0
+ // TODO(b/69958423): handle regions
+ if (directionUp) {
+ stepTo += mAmfmConfig.spacings[0];
+ } else {
+ stepTo -= mAmfmConfig.spacings[0];
+ }
+
+ if (stepTo > mAmfmConfig.upperLimit) stepTo = mAmfmConfig.lowerLimit;
+ if (stepTo < mAmfmConfig.lowerLimit) stepTo = mAmfmConfig.upperLimit;
+#else
+ if (directionUp) {
+ stepTo += 100;
+ } else {
+ stepTo -= 100;
+ }
+#endif
+
+ auto task = [this, stepTo]() {
+ ALOGI("Performing step to %s", std::to_string(stepTo).c_str());
+
+ lock_guard<mutex> lk(mMut);
+
+ tuneInternalLocked(utils::make_selector_amfm(stepTo));
+ };
+ mThread.schedule(task, delay::step);
+
+ return Result::OK;
+}
+
+Return<void> TunerSession::cancel() {
+ ALOGV("%s", __func__);
+ lock_guard<mutex> lk(mMut);
+ if (mIsClosed) return {};
+
+ mThread.cancelAll();
+ return {};
+}
+
+Return<void> TunerSession::setParameters(const hidl_vec<VendorKeyValue>& /* parameters */,
+ setParameters_cb _hidl_cb) {
+ ALOGV("%s", __func__);
+
+ _hidl_cb({});
+ return {};
+}
+
+Return<void> TunerSession::getParameters(const hidl_vec<hidl_string>& /* keys */,
+ getParameters_cb _hidl_cb) {
+ ALOGV("%s", __func__);
+
+ _hidl_cb({});
+ return {};
+}
+
+Return<void> TunerSession::close() {
+ ALOGV("%s", __func__);
+ lock_guard<mutex> lk(mMut);
+ if (mIsClosed) return {};
+
+ mIsClosed = true;
+ mThread.cancelAll();
+ return {};
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace broadcastradio
+} // namespace hardware
+} // namespace android
diff --git a/broadcastradio/2.0/default/TunerSession.h b/broadcastradio/2.0/default/TunerSession.h
new file mode 100644
index 0000000..08a7588
--- /dev/null
+++ b/broadcastradio/2.0/default/TunerSession.h
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V2_0_TUNER_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V2_0_TUNER_H
+
+#include "VirtualRadio.h"
+
+#include <android/hardware/broadcastradio/2.0/ITunerCallback.h>
+#include <android/hardware/broadcastradio/2.0/ITunerSession.h>
+#include <broadcastradio-utils/WorkerThread.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V2_0 {
+namespace implementation {
+
+struct BroadcastRadio;
+
+struct TunerSession : public ITunerSession {
+ TunerSession(BroadcastRadio& module, const sp<ITunerCallback>& callback);
+
+ // V2_0::ITunerSession methods
+ virtual Return<Result> tune(const ProgramSelector& program) override;
+ virtual Return<Result> scan(bool directionUp, bool skipSubChannel) override;
+ virtual Return<Result> step(bool directionUp) override;
+ virtual Return<void> cancel() override;
+ virtual Return<void> setParameters(const hidl_vec<VendorKeyValue>& parameters,
+ setParameters_cb _hidl_cb) override;
+ virtual Return<void> getParameters(const hidl_vec<hidl_string>& keys,
+ getParameters_cb _hidl_cb) override;
+ virtual Return<void> close() override;
+
+ private:
+ std::mutex mMut;
+ WorkerThread mThread;
+ bool mIsClosed = false;
+
+ const sp<ITunerCallback> mCallback;
+
+ std::reference_wrapper<BroadcastRadio> mModule;
+ bool mIsTuneCompleted = false;
+ ProgramSelector mCurrentProgram = {};
+
+ void tuneInternalLocked(const ProgramSelector& sel);
+ const VirtualRadio& virtualRadio() const;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace broadcastradio
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_BROADCASTRADIO_V2_0_TUNER_H
diff --git a/broadcastradio/2.0/default/VirtualProgram.cpp b/broadcastradio/2.0/default/VirtualProgram.cpp
new file mode 100644
index 0000000..1acd4d3
--- /dev/null
+++ b/broadcastradio/2.0/default/VirtualProgram.cpp
@@ -0,0 +1,76 @@
+/*
+ * 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 "VirtualProgram.h"
+
+#include "resources.h"
+
+#include <broadcastradio-utils-2x/Utils.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V2_0 {
+namespace implementation {
+
+using utils::getType;
+using utils::make_metadata;
+
+using std::vector;
+
+VirtualProgram::operator ProgramInfo() const {
+ ProgramInfo info = {};
+
+ info.selector = selector;
+
+ auto pType = getType(selector.primaryId);
+ auto isDigital = (pType != IdentifierType::AMFM_FREQUENCY && pType != IdentifierType::RDS_PI);
+
+ info.infoFlags |= ProgramInfoFlags::TUNED;
+ info.infoFlags |= ProgramInfoFlags::STEREO;
+ info.signalQuality = isDigital ? 100 : 80;
+
+ info.metadata = hidl_vec<Metadata>({
+ make_metadata(MetadataKey::RDS_PS, programName),
+ make_metadata(MetadataKey::SONG_TITLE, songTitle),
+ make_metadata(MetadataKey::SONG_ARTIST, songArtist),
+ make_metadata(MetadataKey::STATION_ICON, resources::demoPngId),
+ make_metadata(MetadataKey::ALBUM_ART, resources::demoPngId),
+ });
+
+ info.vendorInfo = hidl_vec<VendorKeyValue>({
+ {"com.google.dummy", "dummy"},
+ {"com.google.dummy.VirtualProgram", std::to_string(reinterpret_cast<uintptr_t>(this))},
+ });
+
+ return info;
+}
+
+bool operator<(const VirtualProgram& lhs, const VirtualProgram& rhs) {
+ auto& l = lhs.selector;
+ auto& r = rhs.selector;
+
+ // Two programs with the same primaryId are considered the same.
+ if (l.primaryId.type != r.primaryId.type) return l.primaryId.type < r.primaryId.type;
+ if (l.primaryId.value != r.primaryId.value) return l.primaryId.value < r.primaryId.value;
+
+ return false;
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace broadcastradio
+} // namespace hardware
+} // namespace android
diff --git a/broadcastradio/2.0/default/VirtualProgram.h b/broadcastradio/2.0/default/VirtualProgram.h
new file mode 100644
index 0000000..e1c4f75
--- /dev/null
+++ b/broadcastradio/2.0/default/VirtualProgram.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V2_0_VIRTUALPROGRAM_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V2_0_VIRTUALPROGRAM_H
+
+#include <android/hardware/broadcastradio/2.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V2_0 {
+namespace implementation {
+
+/**
+ * A radio program mock.
+ *
+ * This represents broadcast waves flying over the air,
+ * not an entry for a captured station in the radio tuner memory.
+ */
+struct VirtualProgram {
+ ProgramSelector selector;
+
+ std::string programName = "";
+ std::string songArtist = "";
+ std::string songTitle = "";
+
+ operator ProgramInfo() const;
+
+ /**
+ * Defines order on how virtual programs appear on the "air" with
+ * ITunerSession::scan operation.
+ *
+ * It's for default implementation purposes, may not be complete or correct.
+ */
+ friend bool operator<(const VirtualProgram& lhs, const VirtualProgram& rhs);
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace broadcastradio
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_BROADCASTRADIO_V2_0_VIRTUALPROGRAM_H
diff --git a/broadcastradio/2.0/default/VirtualRadio.cpp b/broadcastradio/2.0/default/VirtualRadio.cpp
new file mode 100644
index 0000000..f601d41
--- /dev/null
+++ b/broadcastradio/2.0/default/VirtualRadio.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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 "BcRadioDef.VirtualRadio"
+//#define LOG_NDEBUG 0
+
+#include "VirtualRadio.h"
+
+#include <broadcastradio-utils-2x/Utils.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V2_0 {
+namespace implementation {
+
+using std::lock_guard;
+using std::move;
+using std::mutex;
+using std::vector;
+using utils::make_selector_amfm;
+
+VirtualRadio gAmFmRadio(
+ "AM/FM radio mock",
+ {
+ {make_selector_amfm(94900), "Wild 94.9", "Drake ft. Rihanna", "Too Good"},
+ {make_selector_amfm(96500), "KOIT", "Celine Dion", "All By Myself"},
+ {make_selector_amfm(97300), "Alice@97.3", "Drops of Jupiter", "Train"},
+ {make_selector_amfm(99700), "99.7 Now!", "The Chainsmokers", "Closer"},
+ {make_selector_amfm(101300), "101-3 KISS-FM", "Justin Timberlake", "Rock Your Body"},
+ {make_selector_amfm(103700), "iHeart80s @ 103.7", "Michael Jackson", "Billie Jean"},
+ {make_selector_amfm(106100), "106 KMEL", "Drake", "Marvins Room"},
+ });
+
+VirtualRadio::VirtualRadio(const std::string& name, const vector<VirtualProgram>& initialList)
+ : mName(name), mPrograms(initialList) {}
+
+std::string VirtualRadio::getName() const {
+ return mName;
+}
+
+vector<VirtualProgram> VirtualRadio::getProgramList() const {
+ lock_guard<mutex> lk(mMut);
+ return mPrograms;
+}
+
+bool VirtualRadio::getProgram(const ProgramSelector& selector, VirtualProgram& programOut) const {
+ lock_guard<mutex> lk(mMut);
+ for (auto&& program : mPrograms) {
+ if (utils::tunesTo(selector, program.selector)) {
+ programOut = program;
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace broadcastradio
+} // namespace hardware
+} // namespace android
diff --git a/broadcastradio/2.0/default/VirtualRadio.h b/broadcastradio/2.0/default/VirtualRadio.h
new file mode 100644
index 0000000..9c07816
--- /dev/null
+++ b/broadcastradio/2.0/default/VirtualRadio.h
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V2_0_VIRTUALRADIO_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V2_0_VIRTUALRADIO_H
+
+#include "VirtualProgram.h"
+
+#include <mutex>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V2_0 {
+namespace implementation {
+
+/**
+ * A radio frequency space mock.
+ *
+ * This represents all broadcast waves in the air for a given radio technology,
+ * not a captured station list in the radio tuner memory.
+ *
+ * It's meant to abstract out radio content from default tuner implementation.
+ */
+class VirtualRadio {
+ public:
+ VirtualRadio(const std::string& name, const std::vector<VirtualProgram>& initialList);
+
+ std::string getName() const;
+ std::vector<VirtualProgram> getProgramList() const;
+ bool getProgram(const ProgramSelector& selector, VirtualProgram& program) const;
+
+ private:
+ mutable std::mutex mMut;
+ std::string mName;
+ std::vector<VirtualProgram> mPrograms;
+};
+
+/** AM/FM virtual radio space. */
+extern VirtualRadio gAmFmRadio;
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace broadcastradio
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_BROADCASTRADIO_V2_0_VIRTUALRADIO_H
diff --git a/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc
new file mode 100644
index 0000000..7d68b6c
--- /dev/null
+++ b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc
@@ -0,0 +1,4 @@
+service broadcastradio-hal2 /vendor/bin/hw/android.hardware.broadcastradio@2.0-service
+ class hal
+ user audioserver
+ group audio
diff --git a/broadcastradio/2.0/default/resources.h b/broadcastradio/2.0/default/resources.h
new file mode 100644
index 0000000..97360dd
--- /dev/null
+++ b/broadcastradio/2.0/default/resources.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V2_0_RESOURCES_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V2_0_RESOURCES_H
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V2_0 {
+namespace implementation {
+namespace resources {
+
+constexpr int32_t demoPngId = 123456;
+constexpr uint8_t demoPng[] = {
+ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44,
+ 0x52, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25,
+ 0x0b, 0xe6, 0x89, 0x00, 0x00, 0x00, 0x5d, 0x49, 0x44, 0x41, 0x54, 0x68, 0xde, 0xed, 0xd9,
+ 0xc1, 0x09, 0x00, 0x30, 0x08, 0x04, 0xc1, 0x33, 0xfd, 0xf7, 0x6c, 0x6a, 0xc8, 0x23, 0x04,
+ 0xc9, 0x6c, 0x01, 0xc2, 0x20, 0xbe, 0x4c, 0x86, 0x57, 0x49, 0xba, 0xfb, 0xd6, 0xf4, 0xba,
+ 0x3e, 0x7f, 0x4d, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x8f, 0x00, 0xbd, 0xce, 0x7f,
+ 0xc0, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0xb8, 0x0d, 0x32, 0xd4, 0x0c, 0x77, 0xbd,
+ 0xfb, 0xc1, 0xce, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};
+
+} // namespace resources
+} // namespace implementation
+} // namespace V2_0
+} // namespace broadcastradio
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_BROADCASTRADIO_V2_0_RESOURCES_H
diff --git a/broadcastradio/2.0/default/service.cpp b/broadcastradio/2.0/default/service.cpp
new file mode 100644
index 0000000..7e677a1
--- /dev/null
+++ b/broadcastradio/2.0/default/service.cpp
@@ -0,0 +1,38 @@
+/*
+ * 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 "BcRadioDef.service"
+
+#include <android-base/logging.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "BroadcastRadio.h"
+#include "VirtualRadio.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::broadcastradio::V2_0::implementation::BroadcastRadio;
+using android::hardware::broadcastradio::V2_0::implementation::gAmFmRadio;
+
+int main(int /* argc */, char** /* argv */) {
+ configureRpcThreadpool(4, true);
+
+ BroadcastRadio broadcastRadio(gAmFmRadio);
+ auto status = broadcastRadio.registerAsService();
+ CHECK_EQ(status, android::OK) << "Failed to register Broadcast Radio HAL implementation";
+
+ joinRpcThreadpool();
+ return 1; // joinRpcThreadpool shouldn't exit
+}
diff --git a/broadcastradio/common/tests/OWNERS b/broadcastradio/2.0/vts/OWNERS
similarity index 100%
rename from broadcastradio/common/tests/OWNERS
rename to broadcastradio/2.0/vts/OWNERS
diff --git a/broadcastradio/2.0/vts/functional/Android.bp b/broadcastradio/2.0/vts/functional/Android.bp
new file mode 100644
index 0000000..6017b15
--- /dev/null
+++ b/broadcastradio/2.0/vts/functional/Android.bp
@@ -0,0 +1,28 @@
+//
+// 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: "VtsHalBroadcastradioV2_0TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: ["VtsHalBroadcastradioV2_0TargetTest.cpp"],
+ static_libs: [
+ "android.hardware.broadcastradio@2.0",
+ "android.hardware.broadcastradio@common-utils-2x-lib",
+ "android.hardware.broadcastradio@vts-utils-lib",
+ "android.hardware.broadcastradio@vts-utils-lib",
+ "libgmock",
+ ],
+}
diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
new file mode 100644
index 0000000..a12afd6
--- /dev/null
+++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
@@ -0,0 +1,392 @@
+/*
+ * 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 "BcRadio.vts"
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/broadcastradio/2.0/IBroadcastRadio.h>
+#include <android/hardware/broadcastradio/2.0/ITunerCallback.h>
+#include <android/hardware/broadcastradio/2.0/ITunerSession.h>
+#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/mock-timeout.h>
+#include <broadcastradio-vts-utils/pointer-utils.h>
+#include <gmock/gmock.h>
+
+#include <chrono>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V2_0 {
+namespace vts {
+
+using namespace std::chrono_literals;
+
+using std::vector;
+using testing::_;
+using testing::AnyNumber;
+using testing::ByMove;
+using testing::DoAll;
+using testing::Invoke;
+using testing::SaveArg;
+
+using broadcastradio::vts::CallBarrier;
+using broadcastradio::vts::clearAndWait;
+using utils::make_identifier;
+using utils::make_selector_amfm;
+
+namespace timeout {
+
+static constexpr auto tune = 30s;
+
+} // namespace timeout
+
+struct TunerCallbackMock : public ITunerCallback {
+ TunerCallbackMock() {
+ // we expect the antenna is connected through the whole test
+ EXPECT_CALL(*this, onAntennaStateChange(false)).Times(0);
+ }
+
+ MOCK_METHOD2(onTuneFailed, Return<void>(Result, const ProgramSelector&));
+ MOCK_TIMEOUT_METHOD1(onCurrentProgramInfoChanged, Return<void>(const ProgramInfo&));
+ MOCK_METHOD1(onAntennaStateChange, Return<void>(bool connected));
+ MOCK_METHOD1(onParametersUpdated, Return<void>(const hidl_vec<VendorKeyValue>& parameters));
+};
+
+class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase {
+ protected:
+ virtual void SetUp() override;
+ virtual void TearDown() override;
+
+ bool openSession();
+
+ sp<IBroadcastRadio> mModule;
+ Properties mProperties;
+ sp<ITunerSession> mSession;
+ sp<TunerCallbackMock> mCallback = new TunerCallbackMock();
+};
+
+void BroadcastRadioHalTest::SetUp() {
+ EXPECT_EQ(nullptr, mModule.get()) << "Module is already open";
+
+ // lookup HIDL service (radio module)
+ mModule = getService<IBroadcastRadio>();
+ ASSERT_NE(nullptr, mModule.get()) << "Couldn't find broadcast radio HAL implementation";
+
+ // get module properties
+ auto propResult = mModule->getProperties([&](const Properties& p) { mProperties = p; });
+ ASSERT_TRUE(propResult.isOk());
+
+ EXPECT_FALSE(mProperties.maker.empty());
+ EXPECT_FALSE(mProperties.product.empty());
+ EXPECT_GT(mProperties.supportedIdentifierTypes.size(), 0u);
+}
+
+void BroadcastRadioHalTest::TearDown() {
+ mSession.clear();
+ mModule.clear();
+ clearAndWait(mCallback, 1s);
+}
+
+bool BroadcastRadioHalTest::openSession() {
+ EXPECT_EQ(nullptr, mSession.get()) << "Session is already open";
+
+ Result halResult = Result::UNKNOWN_ERROR;
+ auto openCb = [&](Result result, const sp<ITunerSession>& session) {
+ halResult = result;
+ if (result != Result::OK) return;
+ mSession = session;
+ };
+ auto hidlResult = mModule->openSession(mCallback, openCb);
+
+ EXPECT_TRUE(hidlResult.isOk());
+ EXPECT_EQ(Result::OK, halResult);
+ EXPECT_NE(nullptr, mSession.get());
+
+ return nullptr != mSession.get();
+}
+
+/**
+ * Test session opening.
+ *
+ * Verifies that:
+ * - the method succeeds on a first and subsequent calls;
+ * - the method succeeds when called for the second time without
+ * closing previous session.
+ */
+TEST_F(BroadcastRadioHalTest, OpenSession) {
+ // simply open session for the first time
+ ASSERT_TRUE(openSession());
+
+ // drop (without explicit close) and re-open the session
+ mSession.clear();
+ ASSERT_TRUE(openSession());
+
+ // open the second session (the first one should be forcibly closed)
+ auto secondSession = mSession;
+ mSession.clear();
+ ASSERT_TRUE(openSession());
+}
+
+/**
+ * Test tuning with FM selector.
+ *
+ * Verifies that:
+ * - if AM/FM selector is not supported, the method returns NOT_SUPPORTED;
+ * - if it is supported, the method succeeds;
+ * - after a successful tune call, onCurrentProgramInfoChanged callback is
+ * invoked carrying a proper selector;
+ * - program changes exactly to what was requested.
+ */
+TEST_F(BroadcastRadioHalTest, FmTune) {
+ ASSERT_TRUE(openSession());
+
+ uint64_t freq = 100100; // 100.1 FM
+ auto sel = make_selector_amfm(freq);
+
+ // try tuning
+ ProgramInfo infoCb = {};
+ EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged, _)
+ .Times(AnyNumber())
+ .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))));
+ auto result = mSession->tune(sel);
+
+ // expect a failure if it's not supported
+ if (!utils::isSupported(mProperties, sel)) {
+ EXPECT_EQ(Result::NOT_SUPPORTED, result);
+ return;
+ }
+
+ // expect a callback if it succeeds
+ EXPECT_EQ(Result::OK, result);
+ EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged, timeout::tune);
+
+ // it should tune exactly to what was requested
+ auto freqs = utils::getAllIds(infoCb.selector, IdentifierType::AMFM_FREQUENCY);
+ EXPECT_NE(freqs.end(), find(freqs.begin(), freqs.end(), freq));
+}
+
+/**
+ * Test tuning with invalid selectors.
+ *
+ * Verifies that:
+ * - if the selector is not supported, it's ignored;
+ * - if it is supported, an invalid value results with INVALID_ARGUMENTS;
+ */
+TEST_F(BroadcastRadioHalTest, TuneFailsWithInvalid) {
+ ASSERT_TRUE(openSession());
+
+ vector<ProgramIdentifier> invalid = {
+ make_identifier(IdentifierType::AMFM_FREQUENCY, 0),
+ make_identifier(IdentifierType::RDS_PI, 0x10000),
+ make_identifier(IdentifierType::HD_STATION_ID_EXT, 0x100000000),
+ make_identifier(IdentifierType::DAB_SID_EXT, 0),
+ make_identifier(IdentifierType::DRMO_SERVICE_ID, 0x100000000),
+ make_identifier(IdentifierType::SXM_SERVICE_ID, 0x100000000),
+ };
+
+ for (auto&& id : invalid) {
+ ProgramSelector sel{id, {}};
+
+ auto result = mSession->tune(sel);
+
+ if (utils::isSupported(mProperties, sel)) {
+ EXPECT_EQ(Result::INVALID_ARGUMENTS, result);
+ } else {
+ EXPECT_EQ(Result::NOT_SUPPORTED, result);
+ }
+ }
+}
+
+/**
+ * Test tuning with empty program selector.
+ *
+ * Verifies that:
+ * - tune fails with NOT_SUPPORTED when program selector is not initialized.
+ */
+TEST_F(BroadcastRadioHalTest, TuneFailsWithEmpty) {
+ ASSERT_TRUE(openSession());
+
+ // Program type is 1-based, so 0 will always be invalid.
+ ProgramSelector sel = {};
+ auto result = mSession->tune(sel);
+ ASSERT_EQ(Result::NOT_SUPPORTED, result);
+}
+
+/**
+ * Test scanning to next/prev station.
+ *
+ * Verifies that:
+ * - the method succeeds;
+ * - the program info is changed within timeout::tune;
+ * - works both directions and with or without skipping sub-channel.
+ */
+TEST_F(BroadcastRadioHalTest, Scan) {
+ ASSERT_TRUE(openSession());
+
+ EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged, _);
+ auto result = mSession->scan(true /* up */, true /* skip subchannel */);
+ EXPECT_EQ(Result::OK, result);
+ EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged, timeout::tune);
+
+ EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged, _);
+ result = mSession->scan(false /* down */, false /* don't skip subchannel */);
+ EXPECT_EQ(Result::OK, result);
+ EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged, timeout::tune);
+}
+
+/**
+ * Test step operation.
+ *
+ * Verifies that:
+ * - the method succeeds or returns NOT_SUPPORTED;
+ * - the program info is changed within timeout::tune if the method succeeded;
+ * - works both directions.
+ */
+TEST_F(BroadcastRadioHalTest, Step) {
+ ASSERT_TRUE(openSession());
+
+ EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged, _).Times(AnyNumber());
+ auto result = mSession->step(true /* up */);
+ if (result == Result::NOT_SUPPORTED) return;
+ EXPECT_EQ(Result::OK, result);
+ EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged, timeout::tune);
+
+ EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged, _);
+ result = mSession->step(false /* down */);
+ EXPECT_EQ(Result::OK, result);
+ EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged, timeout::tune);
+}
+
+/**
+ * Test tune cancellation.
+ *
+ * Verifies that:
+ * - the method does not crash after being invoked multiple times.
+ */
+TEST_F(BroadcastRadioHalTest, Cancel) {
+ ASSERT_TRUE(openSession());
+
+ for (int i = 0; i < 10; i++) {
+ auto scanResult = mSession->scan(true /* up */, true /* skip subchannel */);
+ ASSERT_EQ(Result::OK, scanResult);
+
+ auto cancelResult = mSession->cancel();
+ ASSERT_TRUE(cancelResult.isOk());
+ }
+}
+
+/**
+ * Test IBroadcastRadio::get|setParameters() methods called with no parameters.
+ *
+ * Verifies that:
+ * - callback is called for empty parameters set.
+ */
+TEST_F(BroadcastRadioHalTest, NoParameters) {
+ ASSERT_TRUE(openSession());
+
+ hidl_vec<VendorKeyValue> halResults = {};
+ bool wasCalled = false;
+ auto cb = [&](hidl_vec<VendorKeyValue> results) {
+ wasCalled = true;
+ halResults = results;
+ };
+
+ auto hidlResult = mSession->setParameters({}, cb);
+ ASSERT_TRUE(hidlResult.isOk());
+ ASSERT_TRUE(wasCalled);
+ ASSERT_EQ(0u, halResults.size());
+
+ wasCalled = false;
+ hidlResult = mSession->getParameters({}, cb);
+ ASSERT_TRUE(hidlResult.isOk());
+ ASSERT_TRUE(wasCalled);
+ ASSERT_EQ(0u, halResults.size());
+}
+
+/**
+ * Test IBroadcastRadio::get|setParameters() methods called with unknown parameters.
+ *
+ * Verifies that:
+ * - unknown parameters are ignored;
+ * - callback is called also for empty results set.
+ */
+TEST_F(BroadcastRadioHalTest, UnknownParameters) {
+ ASSERT_TRUE(openSession());
+
+ hidl_vec<VendorKeyValue> halResults = {};
+ bool wasCalled = false;
+ auto cb = [&](hidl_vec<VendorKeyValue> results) {
+ wasCalled = true;
+ halResults = results;
+ };
+
+ auto hidlResult = mSession->setParameters({{"com.google.unknown", "dummy"}}, cb);
+ ASSERT_TRUE(hidlResult.isOk());
+ ASSERT_TRUE(wasCalled);
+ ASSERT_EQ(0u, halResults.size());
+
+ wasCalled = false;
+ hidlResult = mSession->getParameters({{"com.google.unknown*", "dummy"}}, cb);
+ ASSERT_TRUE(hidlResult.isOk());
+ ASSERT_TRUE(wasCalled);
+ ASSERT_EQ(0u, halResults.size());
+}
+
+/**
+ * Test session closing.
+ *
+ * Verifies that:
+ * - the method does not crash after being invoked multiple times.
+ */
+TEST_F(BroadcastRadioHalTest, Close) {
+ ASSERT_TRUE(openSession());
+
+ for (int i = 0; i < 10; i++) {
+ auto cancelResult = mSession->close();
+ ASSERT_TRUE(cancelResult.isOk());
+ }
+}
+
+/**
+ * Test geting image of invalid ID.
+ *
+ * Verifies that:
+ * - getImage call handles argument 0 gracefully.
+ */
+TEST_F(BroadcastRadioHalTest, GetNoImage) {
+ size_t len = 0;
+ auto result = mModule->getImage(0, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
+
+ ASSERT_TRUE(result.isOk());
+ ASSERT_EQ(0u, len);
+}
+
+} // namespace vts
+} // namespace V2_0
+} // namespace broadcastradio
+} // namespace hardware
+} // namespace android
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ ALOGI("Test result = %d", status);
+ return status;
+}
diff --git a/broadcastradio/common/utils/OWNERS b/broadcastradio/common/OWNERS
similarity index 100%
rename from broadcastradio/common/utils/OWNERS
rename to broadcastradio/common/OWNERS
diff --git a/broadcastradio/common/tests/Android.bp b/broadcastradio/common/tests/Android.bp
index 4456602..bbad527 100644
--- a/broadcastradio/common/tests/Android.bp
+++ b/broadcastradio/common/tests/Android.bp
@@ -26,4 +26,25 @@
"WorkerThread_test.cpp",
],
static_libs: ["android.hardware.broadcastradio@common-utils-lib"],
-}
\ No newline at end of file
+}
+
+cc_test {
+ name: "android.hardware.broadcastradio@common-utils-xx-tests",
+ vendor: true,
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+ srcs: [
+ "CommonXX_test.cpp",
+ ],
+ static_libs: [
+ "android.hardware.broadcastradio@common-utils-1x-lib",
+ "android.hardware.broadcastradio@common-utils-2x-lib",
+ ],
+ shared_libs: [
+ "android.hardware.broadcastradio@1.2",
+ "android.hardware.broadcastradio@2.0",
+ ],
+}
diff --git a/broadcastradio/common/tests/CommonXX_test.cpp b/broadcastradio/common/tests/CommonXX_test.cpp
new file mode 100644
index 0000000..d19204e
--- /dev/null
+++ b/broadcastradio/common/tests/CommonXX_test.cpp
@@ -0,0 +1,18 @@
+/*
+ * 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 <broadcastradio-utils-1x/Utils.h>
+#include <broadcastradio-utils-2x/Utils.h>
diff --git a/broadcastradio/common/utils/Android.bp b/broadcastradio/common/utils/Android.bp
index d29d05c..33ba7da 100644
--- a/broadcastradio/common/utils/Android.bp
+++ b/broadcastradio/common/utils/Android.bp
@@ -24,11 +24,12 @@
"-Werror",
],
srcs: [
- "Utils.cpp",
"WorkerThread.cpp",
],
export_include_dirs: ["include"],
shared_libs: [
- "android.hardware.broadcastradio@1.2",
+ "libbase",
+ "liblog",
+ "libutils",
],
}
diff --git a/broadcastradio/common/utils1x/Android.bp b/broadcastradio/common/utils1x/Android.bp
new file mode 100644
index 0000000..127c15a
--- /dev/null
+++ b/broadcastradio/common/utils1x/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_library_static {
+ name: "android.hardware.broadcastradio@common-utils-1x-lib",
+ vendor_available: true,
+ relative_install_path: "hw",
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+ srcs: [
+ "Utils.cpp",
+ ],
+ export_include_dirs: ["include"],
+ shared_libs: [
+ "android.hardware.broadcastradio@1.2",
+ ],
+}
diff --git a/broadcastradio/common/utils/Utils.cpp b/broadcastradio/common/utils1x/Utils.cpp
similarity index 97%
rename from broadcastradio/common/utils/Utils.cpp
rename to broadcastradio/common/utils1x/Utils.cpp
index 22a6970..7a59d6a 100644
--- a/broadcastradio/common/utils/Utils.cpp
+++ b/broadcastradio/common/utils1x/Utils.cpp
@@ -16,7 +16,7 @@
#define LOG_TAG "BroadcastRadioDefault.utils"
//#define LOG_NDEBUG 0
-#include <broadcastradio-utils/Utils.h>
+#include <broadcastradio-utils-1x/Utils.h>
#include <log/log.h>
@@ -59,9 +59,7 @@
/* We should check all Ids of a given type (ie. other AF),
* but it doesn't matter for default implementation.
*/
- auto aId = getId(a, type);
- auto bId = getId(b, type);
- return aId == bId;
+ return getId(a, type) == getId(b, type);
}
bool tunesTo(const ProgramSelector& a, const ProgramSelector& b) {
@@ -242,14 +240,16 @@
namespace V1_0 {
bool operator==(const BandConfig& l, const BandConfig& r) {
+ using namespace utils;
+
if (l.type != r.type) return false;
if (l.antennaConnected != r.antennaConnected) return false;
if (l.lowerLimit != r.lowerLimit) return false;
if (l.upperLimit != r.upperLimit) return false;
if (l.spacings != r.spacings) return false;
- if (utils::isAm(l.type)) {
+ if (isAm(l.type)) {
return l.ext.am == r.ext.am;
- } else if (utils::isFm(l.type)) {
+ } else if (isFm(l.type)) {
return l.ext.fm == r.ext.fm;
} else {
ALOGW("Unsupported band config type: %s", toString(l.type).c_str());
diff --git a/broadcastradio/common/utils/include/broadcastradio-utils/Utils.h b/broadcastradio/common/utils1x/include/broadcastradio-utils-1x/Utils.h
similarity index 88%
rename from broadcastradio/common/utils/include/broadcastradio-utils/Utils.h
rename to broadcastradio/common/utils1x/include/broadcastradio-utils-1x/Utils.h
index 9cdc629..5884b5a 100644
--- a/broadcastradio/common/utils/include/broadcastradio-utils/Utils.h
+++ b/broadcastradio/common/utils1x/include/broadcastradio-utils-1x/Utils.h
@@ -13,8 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_BROADCASTRADIO_COMMON_UTILS_H
-#define ANDROID_HARDWARE_BROADCASTRADIO_COMMON_UTILS_H
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_COMMON_UTILS_1X_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_COMMON_UTILS_1X_H
#include <android/hardware/broadcastradio/1.2/types.h>
#include <chrono>
@@ -68,8 +68,8 @@
V1_1::ProgramSelector make_selector(V1_0::Band band, uint32_t channel, uint32_t subChannel = 0);
-bool getLegacyChannel(const V1_1::ProgramSelector& sel,
- uint32_t* channelOut, uint32_t* subChannelOut);
+bool getLegacyChannel(const V1_1::ProgramSelector& sel, uint32_t* channelOut,
+ uint32_t* subChannelOut);
bool isDigital(const V1_1::ProgramSelector& sel);
@@ -85,4 +85,4 @@
} // namespace hardware
} // namespace android
-#endif // ANDROID_HARDWARE_BROADCASTRADIO_COMMON_UTILS_H
+#endif // ANDROID_HARDWARE_BROADCASTRADIO_COMMON_UTILS_1X_H
diff --git a/broadcastradio/common/utils2x/Android.bp b/broadcastradio/common/utils2x/Android.bp
new file mode 100644
index 0000000..c6b94af
--- /dev/null
+++ b/broadcastradio/common/utils2x/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_library_static {
+ name: "android.hardware.broadcastradio@common-utils-2x-lib",
+ vendor_available: true,
+ relative_install_path: "hw",
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+ srcs: [
+ "Utils.cpp",
+ ],
+ export_include_dirs: ["include"],
+ shared_libs: [
+ "android.hardware.broadcastradio@2.0",
+ ],
+}
diff --git a/broadcastradio/common/utils2x/Utils.cpp b/broadcastradio/common/utils2x/Utils.cpp
new file mode 100644
index 0000000..d157108
--- /dev/null
+++ b/broadcastradio/common/utils2x/Utils.cpp
@@ -0,0 +1,249 @@
+/*
+ * 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 "BcRadioDef.utils"
+//#define LOG_NDEBUG 0
+
+#include <broadcastradio-utils-2x/Utils.h>
+
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace utils {
+
+using V2_0::IdentifierType;
+using V2_0::Metadata;
+using V2_0::MetadataKey;
+using V2_0::ProgramIdentifier;
+using V2_0::ProgramSelector;
+
+using std::string;
+using std::vector;
+
+IdentifierType getType(const ProgramIdentifier& id) {
+ return static_cast<IdentifierType>(id.type);
+}
+
+static bool bothHaveId(const ProgramSelector& a, const ProgramSelector& b,
+ const IdentifierType type) {
+ return hasId(a, type) && hasId(b, type);
+}
+
+static bool haveEqualIds(const ProgramSelector& a, const ProgramSelector& b,
+ const IdentifierType type) {
+ if (!bothHaveId(a, b, type)) return false;
+ /* We should check all Ids of a given type (ie. other AF),
+ * but it doesn't matter for default implementation.
+ */
+ return getId(a, type) == getId(b, type);
+}
+
+static int getHdSubchannel(const ProgramSelector& sel) {
+ auto hdsidext = getId(sel, IdentifierType::HD_STATION_ID_EXT, 0);
+ hdsidext >>= 32; // Station ID number
+ return hdsidext & 0xF; // HD Radio subchannel
+}
+
+bool tunesTo(const ProgramSelector& a, const ProgramSelector& b) {
+ auto type = getType(b.primaryId);
+
+ switch (type) {
+ case IdentifierType::HD_STATION_ID_EXT:
+ case IdentifierType::RDS_PI:
+ case IdentifierType::AMFM_FREQUENCY:
+ if (haveEqualIds(a, b, IdentifierType::HD_STATION_ID_EXT)) return true;
+ if (haveEqualIds(a, b, IdentifierType::RDS_PI)) return true;
+ return getHdSubchannel(b) == 0 && haveEqualIds(a, b, IdentifierType::AMFM_FREQUENCY);
+ case IdentifierType::DAB_SID_EXT:
+ return haveEqualIds(a, b, IdentifierType::DAB_SID_EXT);
+ case IdentifierType::DRMO_SERVICE_ID:
+ return haveEqualIds(a, b, IdentifierType::DRMO_SERVICE_ID);
+ case IdentifierType::SXM_SERVICE_ID:
+ return haveEqualIds(a, b, IdentifierType::SXM_SERVICE_ID);
+ default: // includes all vendor types
+ ALOGW("Unsupported program type: %s", toString(type).c_str());
+ return false;
+ }
+}
+
+static bool maybeGetId(const ProgramSelector& sel, const IdentifierType type, uint64_t* val) {
+ auto itype = static_cast<uint32_t>(type);
+
+ if (sel.primaryId.type == itype) {
+ if (val) *val = sel.primaryId.value;
+ return true;
+ }
+
+ // not optimal, but we don't care in default impl
+ for (auto&& id : sel.secondaryIds) {
+ if (id.type == itype) {
+ if (val) *val = id.value;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool hasId(const ProgramSelector& sel, const IdentifierType type) {
+ return maybeGetId(sel, type, nullptr);
+}
+
+uint64_t getId(const ProgramSelector& sel, const IdentifierType type) {
+ uint64_t val;
+
+ if (maybeGetId(sel, type, &val)) {
+ return val;
+ }
+
+ ALOGW("Identifier %s not found", toString(type).c_str());
+ return 0;
+}
+
+uint64_t getId(const ProgramSelector& sel, const IdentifierType type, uint64_t defval) {
+ if (!hasId(sel, type)) return defval;
+ return getId(sel, type);
+}
+
+vector<uint64_t> getAllIds(const ProgramSelector& sel, const IdentifierType type) {
+ vector<uint64_t> ret;
+ auto itype = static_cast<uint32_t>(type);
+
+ if (sel.primaryId.type == itype) ret.push_back(sel.primaryId.value);
+
+ for (auto&& id : sel.secondaryIds) {
+ if (id.type == itype) ret.push_back(id.value);
+ }
+
+ return ret;
+}
+
+bool isSupported(const V2_0::Properties& prop, const V2_0::ProgramSelector& sel) {
+ // Not optimal, but it doesn't matter for default impl nor VTS tests.
+ for (auto&& idTypeI : prop.supportedIdentifierTypes) {
+ auto idType = static_cast<IdentifierType>(idTypeI);
+ if (hasId(sel, idType)) return true;
+ }
+ return false;
+}
+
+static bool isValid(const ProgramIdentifier& id) {
+ auto val = id.value;
+ bool valid = true;
+
+ auto expect = [&valid](bool condition, std::string message) {
+ if (!condition) {
+ valid = false;
+ ALOGE("Identifier not valid, expected %s", message.c_str());
+ }
+ };
+
+ switch (static_cast<IdentifierType>(id.type)) {
+ case IdentifierType::AMFM_FREQUENCY:
+ case IdentifierType::DAB_FREQUENCY:
+ case IdentifierType::DRMO_FREQUENCY:
+ expect(val > 100u, "f > 100kHz");
+ expect(val < 10000000u, "f < 10GHz");
+ break;
+ case IdentifierType::RDS_PI:
+ expect(val != 0u, "RDS PI != 0");
+ expect(val <= 0xFFFFu, "16bit id");
+ break;
+ case IdentifierType::HD_STATION_ID_EXT: {
+ auto stationId = val & 0xFFFFFFFF; // 32bit
+ val >>= 32;
+ auto subchannel = val & 0xF; // 4bit
+ val >>= 4;
+ auto freq = val & 0x3FFFF; // 18bit
+ expect(stationId != 0u, "HD station id != 0");
+ expect(subchannel < 8u, "HD subch < 8");
+ expect(freq > 100u, "f > 100kHz");
+ expect(freq < 10000000u, "f < 10GHz");
+ break;
+ }
+ case IdentifierType::DAB_SID_EXT: {
+ auto sid = val & 0xFFFF; // 16bit
+ val >>= 16;
+ auto ecc = val & 0xFF; // 8bit
+ expect(sid != 0u, "DAB SId != 0");
+ expect(ecc >= 0xA0u && ecc <= 0xF6u, "Invalid ECC, see ETSI TS 101 756 V2.1.1");
+ break;
+ }
+ case IdentifierType::DAB_ENSEMBLE:
+ expect(val != 0u, "DAB ensemble != 0");
+ expect(val <= 0xFFFFu, "16bit id");
+ break;
+ case IdentifierType::DAB_SCID:
+ expect(val > 0xFu, "12bit SCId (not 4bit SCIdS)");
+ expect(val <= 0xFFFu, "12bit id");
+ break;
+ case IdentifierType::DRMO_SERVICE_ID:
+ expect(val != 0u, "DRM SId != 0");
+ expect(val <= 0xFFFFFFu, "24bit id");
+ break;
+ case IdentifierType::SXM_SERVICE_ID:
+ expect(val != 0u, "SXM SId != 0");
+ expect(val <= 0xFFFFFFFFu, "32bit id");
+ break;
+ case IdentifierType::SXM_CHANNEL:
+ expect(val < 1000u, "SXM channel < 1000");
+ break;
+ case IdentifierType::VENDOR_START:
+ case IdentifierType::VENDOR_END:
+ // skip
+ break;
+ }
+
+ return valid;
+}
+
+bool isValid(const V2_0::ProgramSelector& sel) {
+ if (!isValid(sel.primaryId)) return false;
+ for (auto&& id : sel.secondaryIds) {
+ if (!isValid(id)) return false;
+ }
+ return true;
+}
+
+ProgramIdentifier make_identifier(IdentifierType type, uint64_t value) {
+ return {static_cast<uint32_t>(type), value};
+}
+
+ProgramSelector make_selector_amfm(uint32_t frequency) {
+ ProgramSelector sel = {};
+ sel.primaryId = make_identifier(IdentifierType::AMFM_FREQUENCY, frequency);
+ return sel;
+}
+
+Metadata make_metadata(MetadataKey key, int64_t value) {
+ Metadata meta = {};
+ meta.key = static_cast<uint32_t>(key);
+ meta.intValue = value;
+ return meta;
+}
+
+Metadata make_metadata(MetadataKey key, string value) {
+ Metadata meta = {};
+ meta.key = static_cast<uint32_t>(key);
+ meta.stringValue = value;
+ return meta;
+}
+
+} // namespace utils
+} // namespace broadcastradio
+} // namespace hardware
+} // namespace android
diff --git a/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h b/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h
new file mode 100644
index 0000000..dd01852
--- /dev/null
+++ b/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_COMMON_UTILS_2X_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_COMMON_UTILS_2X_H
+
+#include <android/hardware/broadcastradio/2.0/types.h>
+#include <chrono>
+#include <queue>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace utils {
+
+V2_0::IdentifierType getType(const V2_0::ProgramIdentifier& id);
+
+/**
+ * Checks, if {@code pointer} tunes to {@channel}.
+ *
+ * For example, having a channel {AMFM_FREQUENCY = 103.3}:
+ * - selector {AMFM_FREQUENCY = 103.3, HD_SUBCHANNEL = 0} can tune to this channel;
+ * - selector {AMFM_FREQUENCY = 103.3, HD_SUBCHANNEL = 1} can't.
+ *
+ * @param pointer selector we're trying to match against channel.
+ * @param channel existing channel.
+ */
+bool tunesTo(const V2_0::ProgramSelector& pointer, const V2_0::ProgramSelector& channel);
+
+bool hasId(const V2_0::ProgramSelector& sel, const V2_0::IdentifierType type);
+
+/**
+ * Returns ID (either primary or secondary) for a given program selector.
+ *
+ * If the selector does not contain given type, returns 0 and emits a warning.
+ */
+uint64_t getId(const V2_0::ProgramSelector& sel, const V2_0::IdentifierType type);
+
+/**
+ * Returns ID (either primary or secondary) for a given program selector.
+ *
+ * If the selector does not contain given type, returns default value.
+ */
+uint64_t getId(const V2_0::ProgramSelector& sel, const V2_0::IdentifierType type, uint64_t defval);
+
+/**
+ * Returns all IDs of a given type.
+ */
+std::vector<uint64_t> getAllIds(const V2_0::ProgramSelector& sel, const V2_0::IdentifierType type);
+
+/**
+ * Checks, if a given selector is supported by the radio module.
+ *
+ * @param prop Module description.
+ * @param sel The selector to check.
+ * @return True, if the selector is supported, false otherwise.
+ */
+bool isSupported(const V2_0::Properties& prop, const V2_0::ProgramSelector& sel);
+
+bool isValid(const V2_0::ProgramSelector& sel);
+
+V2_0::ProgramIdentifier make_identifier(V2_0::IdentifierType type, uint64_t value);
+V2_0::ProgramSelector make_selector_amfm(uint32_t frequency);
+V2_0::Metadata make_metadata(V2_0::MetadataKey key, int64_t value);
+V2_0::Metadata make_metadata(V2_0::MetadataKey key, std::string value);
+
+} // namespace utils
+} // namespace broadcastradio
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_BROADCASTRADIO_COMMON_UTILS_2X_H
diff --git a/broadcastradio/common/vts/utils/OWNERS b/broadcastradio/common/vts/utils/OWNERS
deleted file mode 100644
index 12adf57..0000000
--- a/broadcastradio/common/vts/utils/OWNERS
+++ /dev/null
@@ -1,7 +0,0 @@
-# Automotive team
-egranata@google.com
-twasilczyk@google.com
-
-# VTS team
-yuexima@google.com
-yim@google.com
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
new file mode 100644
index 0000000..0b6f5eb
--- /dev/null
+++ b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/pointer-utils.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_VTS_POINTER_UTILS
+#define ANDROID_HARDWARE_BROADCASTRADIO_VTS_POINTER_UTILS
+
+#include <chrono>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace vts {
+
+/**
+ * Clears strong pointer and waits until the object gets destroyed.
+ *
+ * @param ptr The pointer to get cleared.
+ * @param timeout Time to wait for other references.
+ */
+template <typename T>
+static void clearAndWait(sp<T>& ptr, std::chrono::milliseconds timeout) {
+ using std::chrono::steady_clock;
+
+ constexpr auto step = 10ms;
+
+ wp<T> wptr = ptr;
+ ptr.clear();
+
+ auto limit = steady_clock::now() + timeout;
+ while (wptr.promote() != nullptr) {
+ if (steady_clock::now() + step > limit) {
+ FAIL() << "Pointer was not released within timeout";
+ break;
+ }
+ std::this_thread::sleep_for(step);
+ }
+}
+
+} // namespace vts
+} // namespace broadcastradio
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_BROADCASTRADIO_VTS_POINTER_UTILS
diff --git a/wifi/1.2/default/wifi_legacy_hal.cpp b/wifi/1.2/default/wifi_legacy_hal.cpp
index 8289c67..24b80d5 100644
--- a/wifi/1.2/default/wifi_legacy_hal.cpp
+++ b/wifi/1.2/default/wifi_legacy_hal.cpp
@@ -309,6 +309,15 @@
on_nan_event_range_report_user_callback(*event);
}
}
+
+std::function<void(const NanDataPathScheduleUpdateInd&)>
+ on_nan_event_schedule_update_user_callback;
+void onAsyncNanEventScheduleUpdate(NanDataPathScheduleUpdateInd* event) {
+ const auto lock = hidl_sync_util::acquireGlobalLock();
+ if (on_nan_event_schedule_update_user_callback && event) {
+ on_nan_event_schedule_update_user_callback(*event);
+ }
+}
// End of the free-standing "C" style callbacks.
WifiLegacyHal::WifiLegacyHal()
@@ -1061,6 +1070,8 @@
user_callbacks.on_event_range_request;
on_nan_event_range_report_user_callback =
user_callbacks.on_event_range_report;
+ on_nan_event_schedule_update_user_callback =
+ user_callbacks.on_event_schedule_update;
return global_func_table_.wifi_nan_register_handler(
getIfaceHandle(iface_name),
@@ -1072,7 +1083,7 @@
onAysncNanEventBeaconSdfPayload, onAysncNanEventDataPathRequest,
onAysncNanEventDataPathConfirm, onAysncNanEventDataPathEnd,
onAysncNanEventTransmitFollowUp, onAysncNanEventRangeRequest,
- onAysncNanEventRangeReport});
+ onAysncNanEventRangeReport, onAsyncNanEventScheduleUpdate});
}
wifi_error WifiLegacyHal::nanEnableRequest(const std::string& iface_name,
@@ -1330,6 +1341,7 @@
on_nan_event_transmit_follow_up_user_callback = nullptr;
on_nan_event_range_request_user_callback = nullptr;
on_nan_event_range_report_user_callback = nullptr;
+ on_nan_event_schedule_update_user_callback = nullptr;
}
} // namespace legacy_hal
diff --git a/wifi/1.2/default/wifi_legacy_hal.h b/wifi/1.2/default/wifi_legacy_hal.h
index 193928b..05f700e 100644
--- a/wifi/1.2/default/wifi_legacy_hal.h
+++ b/wifi/1.2/default/wifi_legacy_hal.h
@@ -100,6 +100,7 @@
on_event_transmit_follow_up;
std::function<void(const NanRangeRequestInd&)> on_event_range_request;
std::function<void(const NanRangeReportInd&)> on_event_range_report;
+ std::function<void(const NanDataPathScheduleUpdateInd&)> on_event_schedule_update;
};
// Full scan results contain IE info and are hence passed by reference, to
diff --git a/wifi/1.2/default/wifi_nan_iface.cpp b/wifi/1.2/default/wifi_nan_iface.cpp
index 1d786e3..e7bbfaa 100644
--- a/wifi/1.2/default/wifi_nan_iface.cpp
+++ b/wifi/1.2/default/wifi_nan_iface.cpp
@@ -467,6 +467,11 @@
LOG(ERROR) << "on_event_range_report - should not be called";
};
+ callback_handlers.on_event_schedule_update =
+ [weak_ptr_this](const legacy_hal::NanDataPathScheduleUpdateInd& /* msg */) {
+ LOG(ERROR) << "on_event_schedule_update - should not be called";
+ };
+
legacy_hal::wifi_error legacy_status =
legacy_hal_.lock()->nanRegisterCallbackHandlers(ifname_,
callback_handlers);