Implement broadcast radio HAL 2.0 default implementation.

Also, split internal common utils library to 1.x and 2.x.

Test: VTS
Bug: 69958777
Change-Id: I21244c74270a07cc350e8a2b974dafcdae02a0e8
This commit is contained in:
Tomasz Wasilczyk
2017-12-04 09:53:32 -08:00
parent 5bbf35ffef
commit 06100b39db
33 changed files with 1299 additions and 43 deletions

View File

@@ -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",
],

View File

@@ -17,13 +17,13 @@
#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 <cutils/native_handle.h>

View File

@@ -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: [

View File

@@ -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 {

View File

@@ -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 @@ 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;
}

View File

@@ -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 {

View File

@@ -18,7 +18,7 @@
#include "VirtualRadio.h"
#include <broadcastradio-utils/Utils.h>
#include <broadcastradio-utils-1x/Utils.h>
#include <log/log.h>
namespace android {

View File

@@ -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",
],

View File

@@ -23,7 +23,6 @@
#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 <cutils/native_handle.h>

View File

@@ -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",
],
}

View File

@@ -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

View File

@@ -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

View File

@@ -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 %lu", stepTo);
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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,4 @@
service broadcastradio-hal2 /vendor/bin/hw/android.hardware.broadcastradio@2.0-service
class hal
user audioserver
group audio

View File

@@ -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

View File

@@ -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
}

View File

@@ -1,7 +1,3 @@
# Automotive team
egranata@google.com
twasilczyk@google.com
# VTS team
yuexima@google.com
yim@google.com

View File

@@ -26,4 +26,25 @@ cc_test {
"WorkerThread_test.cpp",
],
static_libs: ["android.hardware.broadcastradio@common-utils-lib"],
}
}
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",
],
}

View File

@@ -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>

View File

@@ -24,11 +24,7 @@ cc_library_static {
"-Werror",
],
srcs: [
"Utils.cpp",
"WorkerThread.cpp",
],
export_include_dirs: ["include"],
shared_libs: [
"android.hardware.broadcastradio@1.2",
],
}

View File

@@ -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",
],
}

View File

@@ -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 @@ 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());

View File

@@ -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 @@ 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

View File

@@ -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",
],
}

View File

@@ -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 <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;
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);
}
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

View File

@@ -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 <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);
/**
* 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

View File

@@ -1,7 +0,0 @@
# Automotive team
egranata@google.com
twasilczyk@google.com
# VTS team
yuexima@google.com
yim@google.com