diff --git a/broadcastradio/1.1/vts/functional/Android.bp b/broadcastradio/1.1/vts/functional/Android.bp index c016c168d2..27ae4e9d39 100644 --- a/broadcastradio/1.1/vts/functional/Android.bp +++ b/broadcastradio/1.1/vts/functional/Android.bp @@ -22,7 +22,7 @@ cc_test { "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 bb490c941d..9efb9428bf 100644 --- a/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp +++ b/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp @@ -17,13 +17,13 @@ #define LOG_TAG "broadcastradio.vts" #include +#include #include #include #include #include #include -#include -#include +#include #include #include #include diff --git a/broadcastradio/1.2/default/Android.bp b/broadcastradio/1.2/default/Android.bp index e42cb1e7f7..bd4be774f8 100644 --- a/broadcastradio/1.2/default/Android.bp +++ b/broadcastradio/1.2/default/Android.bp @@ -33,6 +33,7 @@ cc_binary { "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 6209dc1953..f589332b5d 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 +#include #include namespace android { diff --git a/broadcastradio/1.2/default/VirtualProgram.cpp b/broadcastradio/1.2/default/VirtualProgram.cpp index 3284bd1273..3594f64403 100644 --- a/broadcastradio/1.2/default/VirtualProgram.cpp +++ b/broadcastradio/1.2/default/VirtualProgram.cpp @@ -15,7 +15,7 @@ */ #include "VirtualProgram.h" -#include +#include #include "resources.h" @@ -83,13 +83,6 @@ bool operator<(const VirtualProgram& lhs, const VirtualProgram& rhs) { 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 5342c848a3..c0b20f0a72 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 -#include +#include namespace android { namespace hardware { diff --git a/broadcastradio/1.2/default/VirtualRadio.cpp b/broadcastradio/1.2/default/VirtualRadio.cpp index 867726d2fc..8988080061 100644 --- a/broadcastradio/1.2/default/VirtualRadio.cpp +++ b/broadcastradio/1.2/default/VirtualRadio.cpp @@ -18,7 +18,7 @@ #include "VirtualRadio.h" -#include +#include #include namespace android { diff --git a/broadcastradio/1.2/vts/functional/Android.bp b/broadcastradio/1.2/vts/functional/Android.bp index 12da14e4be..fd1c25430f 100644 --- a/broadcastradio/1.2/vts/functional/Android.bp +++ b/broadcastradio/1.2/vts/functional/Android.bp @@ -22,7 +22,6 @@ cc_test { "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 f3552a8be3..0204191c65 100644 --- a/broadcastradio/1.2/vts/functional/VtsHalBroadcastradioV1_2TargetTest.cpp +++ b/broadcastradio/1.2/vts/functional/VtsHalBroadcastradioV1_2TargetTest.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/broadcastradio/2.0/default/Android.bp b/broadcastradio/2.0/default/Android.bp new file mode 100644 index 0000000000..6d4effb9f6 --- /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 0000000000..5ab517d17f --- /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 + +#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({ + static_cast(IdentifierType::AMFM_FREQUENCY), + static_cast(IdentifierType::RDS_PI), + static_cast(IdentifierType::HD_STATION_ID_EXT), + }); + prop.vendorInfo = hidl_vec({ + {"com.google.dummy", "dummy"}, + }); + + return prop; +} + +BroadcastRadio::BroadcastRadio(const VirtualRadio& virtualRadio) + : mVirtualRadio(virtualRadio), mProperties(initProperties(virtualRadio)) {} + +Return BroadcastRadio::getProperties(getProperties_cb _hidl_cb) { + ALOGV("%s", __func__); + _hidl_cb(mProperties); + return {}; +} + +Return BroadcastRadio::openSession(const sp& callback, + openSession_cb _hidl_cb) { + ALOGV("%s", __func__); + lock_guard lk(mMut); + + auto oldSession = mSession.promote(); + if (oldSession != nullptr) { + ALOGI("Closing previously opened tuner"); + oldSession->close(); + mSession = nullptr; + } + + sp newSession = new TunerSession(*this, callback); + mSession = newSession; + + _hidl_cb(Result::OK, newSession); + return {}; +} + +Return BroadcastRadio::getImage(uint32_t id, getImage_cb _hidl_cb) { + ALOGV("%s(%x)", __func__, id); + + if (id == resources::demoPngId) { + _hidl_cb(std::vector(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 0000000000..fcf06155e8 --- /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 +#include + +namespace android { +namespace hardware { +namespace broadcastradio { +namespace V2_0 { +namespace implementation { + +struct BroadcastRadio : public IBroadcastRadio { + BroadcastRadio(const VirtualRadio& virtualRadio); + + // V2_0::IBroadcastRadio methods + Return getProperties(getProperties_cb _hidl_cb) override; + Return openSession(const sp& callback, openSession_cb _hidl_cb) override; + Return getImage(uint32_t id, getImage_cb _hidl_cb); + + std::reference_wrapper mVirtualRadio; + Properties mProperties; + + private: + std::mutex mMut; + wp 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% rename from broadcastradio/common/utils/OWNERS rename 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 0000000000..7e02e53e0e --- /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 +#include + +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& 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 TunerSession::tune(const ProgramSelector& sel) { + ALOGV("%s(%s)", __func__, toString(sel).c_str()); + lock_guard 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 lk(mMut); + tuneInternalLocked(sel); + }; + mThread.schedule(task, delay::tune); + + return Result::OK; +} + +Return TunerSession::scan(bool directionUp, bool /* skipSubChannel */) { + ALOGV("%s", __func__); + lock_guard 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 lk(mMut); + tuneInternalLocked(tuneTo); + }; + mThread.schedule(task, delay::scan); + + return Result::OK; +} + +Return TunerSession::step(bool directionUp) { + ALOGV("%s", __func__); + lock_guard 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 %lu", stepTo); + + lock_guard lk(mMut); + + tuneInternalLocked(utils::make_selector_amfm(stepTo)); + }; + mThread.schedule(task, delay::step); + + return Result::OK; +} + +Return TunerSession::cancel() { + ALOGV("%s", __func__); + lock_guard lk(mMut); + if (mIsClosed) return {}; + + mThread.cancelAll(); + return {}; +} + +Return TunerSession::setParameters(const hidl_vec& /* parameters */, + setParameters_cb _hidl_cb) { + ALOGV("%s", __func__); + + _hidl_cb({}); + return {}; +} + +Return TunerSession::getParameters(const hidl_vec& /* keys */, + getParameters_cb _hidl_cb) { + ALOGV("%s", __func__); + + _hidl_cb({}); + return {}; +} + +Return TunerSession::close() { + ALOGV("%s", __func__); + lock_guard 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 0000000000..08a7588b5a --- /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 +#include +#include + +namespace android { +namespace hardware { +namespace broadcastradio { +namespace V2_0 { +namespace implementation { + +struct BroadcastRadio; + +struct TunerSession : public ITunerSession { + TunerSession(BroadcastRadio& module, const sp& callback); + + // V2_0::ITunerSession methods + virtual Return tune(const ProgramSelector& program) override; + virtual Return scan(bool directionUp, bool skipSubChannel) override; + virtual Return step(bool directionUp) override; + virtual Return cancel() override; + virtual Return setParameters(const hidl_vec& parameters, + setParameters_cb _hidl_cb) override; + virtual Return getParameters(const hidl_vec& keys, + getParameters_cb _hidl_cb) override; + virtual Return close() override; + + private: + std::mutex mMut; + WorkerThread mThread; + bool mIsClosed = false; + + const sp mCallback; + + std::reference_wrapper 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 0000000000..1acd4d30c3 --- /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 + +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({ + 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({ + {"com.google.dummy", "dummy"}, + {"com.google.dummy.VirtualProgram", std::to_string(reinterpret_cast(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 0000000000..e1c4f75985 --- /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 + +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 0000000000..f601d41637 --- /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 +#include + +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& initialList) + : mName(name), mPrograms(initialList) {} + +std::string VirtualRadio::getName() const { + return mName; +} + +vector VirtualRadio::getProgramList() const { + lock_guard lk(mMut); + return mPrograms; +} + +bool VirtualRadio::getProgram(const ProgramSelector& selector, VirtualProgram& programOut) const { + lock_guard 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 0000000000..9c07816b4b --- /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 +#include + +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& initialList); + + std::string getName() const; + std::vector getProgramList() const; + bool getProgram(const ProgramSelector& selector, VirtualProgram& program) const; + + private: + mutable std::mutex mMut; + std::string mName; + std::vector 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 0000000000..7d68b6cebb --- /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 0000000000..97360dd95c --- /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 0000000000..7e677a1323 --- /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 +#include + +#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/common/OWNERS similarity index 56% rename from broadcastradio/common/tests/OWNERS rename to broadcastradio/common/OWNERS index 12adf5762b..136b607b94 100644 --- a/broadcastradio/common/tests/OWNERS +++ b/broadcastradio/common/OWNERS @@ -1,7 +1,3 @@ # Automotive team egranata@google.com twasilczyk@google.com - -# VTS team -yuexima@google.com -yim@google.com diff --git a/broadcastradio/common/tests/Android.bp b/broadcastradio/common/tests/Android.bp index 44566028de..bbad527c6d 100644 --- a/broadcastradio/common/tests/Android.bp +++ b/broadcastradio/common/tests/Android.bp @@ -26,4 +26,25 @@ cc_test { "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 0000000000..d19204ebe3 --- /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 +#include diff --git a/broadcastradio/common/utils/Android.bp b/broadcastradio/common/utils/Android.bp index d29d05c8ff..99793a1ef3 100644 --- a/broadcastradio/common/utils/Android.bp +++ b/broadcastradio/common/utils/Android.bp @@ -24,11 +24,7 @@ cc_library_static { "-Werror", ], srcs: [ - "Utils.cpp", "WorkerThread.cpp", ], export_include_dirs: ["include"], - shared_libs: [ - "android.hardware.broadcastradio@1.2", - ], } diff --git a/broadcastradio/common/utils1x/Android.bp b/broadcastradio/common/utils1x/Android.bp new file mode 100644 index 0000000000..127c15a154 --- /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 22a697066a..7a59d6a13a 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 +#include #include @@ -59,9 +59,7 @@ static bool haveEqualIds(const ProgramSelector& a, const ProgramSelector& b, /* 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 @@ bool isDigital(const ProgramSelector& sel) { 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 89% rename from broadcastradio/common/utils/include/broadcastradio-utils/Utils.h rename to broadcastradio/common/utils1x/include/broadcastradio-utils-1x/Utils.h index 9cdc629d76..5884b5ad6f 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 #include @@ -68,8 +68,8 @@ uint64_t getId(const V1_1::ProgramSelector& sel, const V1_2::IdentifierType type 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 @@ bool operator==(const BandConfig& l, const BandConfig& r); } // 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 0000000000..c6b94afb0f --- /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 0000000000..3c9fba774a --- /dev/null +++ b/broadcastradio/common/utils2x/Utils.cpp @@ -0,0 +1,235 @@ +/* + * 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 + +#include + +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; + +IdentifierType getType(const ProgramIdentifier& id) { + return static_cast(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(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); +} + +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(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(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(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(key); + meta.intValue = value; + return meta; +} + +Metadata make_metadata(MetadataKey key, string value) { + Metadata meta = {}; + meta.key = static_cast(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 0000000000..e9ac8642dc --- /dev/null +++ b/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h @@ -0,0 +1,80 @@ +/* + * 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 +#include +#include +#include + +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); + +/** + * 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 12adf5762b..0000000000 --- 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