From 6a9f856e24936d9696407ab2857afc1c47151874 Mon Sep 17 00:00:00 2001 From: Tomasz Wasilczyk Date: Wed, 27 Dec 2017 09:46:43 -0800 Subject: [PATCH] Implement broadcast radio announcements. Bug: 68045105 Test: VTS Change-Id: I14d394862ec34d63218c938779e217c28710e230 --- broadcastradio/2.0/Android.bp | 4 ++ broadcastradio/2.0/IAnnouncementObserver.hal | 30 +++++++++++ broadcastradio/2.0/IBroadcastRadio.hal | 28 +++++++++- broadcastradio/2.0/ICloseHandle.hal | 32 ++++++++++++ broadcastradio/2.0/ITunerSession.hal | 2 +- broadcastradio/2.0/default/BroadcastRadio.cpp | 9 ++++ broadcastradio/2.0/default/BroadcastRadio.h | 3 ++ broadcastradio/2.0/types.hal | 52 +++++++++++++++++++ .../VtsHalBroadcastradioV2_0TargetTest.cpp | 38 ++++++++++++++ 9 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 broadcastradio/2.0/IAnnouncementObserver.hal create mode 100644 broadcastradio/2.0/ICloseHandle.hal diff --git a/broadcastradio/2.0/Android.bp b/broadcastradio/2.0/Android.bp index f4894ad70a..74090059a1 100644 --- a/broadcastradio/2.0/Android.bp +++ b/broadcastradio/2.0/Android.bp @@ -8,7 +8,9 @@ hidl_interface { }, srcs: [ "types.hal", + "IAnnouncementObserver.hal", "IBroadcastRadio.hal", + "ICloseHandle.hal", "ITunerCallback.hal", "ITunerSession.hal", ], @@ -18,6 +20,8 @@ hidl_interface { types: [ "AmFmBandRange", "AmFmRegionConfig", + "Announcement", + "AnnouncementType", "ConfigFlag", "Constants", "DabTableEntry", diff --git a/broadcastradio/2.0/IAnnouncementObserver.hal b/broadcastradio/2.0/IAnnouncementObserver.hal new file mode 100644 index 0000000000..c91e29a708 --- /dev/null +++ b/broadcastradio/2.0/IAnnouncementObserver.hal @@ -0,0 +1,30 @@ +/* Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.broadcastradio@2.0; + +/** + * Callback interface for announcement observer. + * + * For typical configuration, the observer is a broadcast radio service. + */ +interface IAnnouncementObserver { + /** + * Called whenever announcement list has changed. + * + * @param announcements The complete list of currently active announcements. + */ + oneway onListUpdated(vec announcements); +}; diff --git a/broadcastradio/2.0/IBroadcastRadio.hal b/broadcastradio/2.0/IBroadcastRadio.hal index 3b19e6123f..7578f4453b 100644 --- a/broadcastradio/2.0/IBroadcastRadio.hal +++ b/broadcastradio/2.0/IBroadcastRadio.hal @@ -15,6 +15,8 @@ package android.hardware.broadcastradio@2.0; +import IAnnouncementObserver; +import ICloseHandle; import ITunerCallback; import ITunerSession; @@ -66,7 +68,7 @@ interface IBroadcastRadio { * @return session The session interface. */ openSession(ITunerCallback callback) - generates (Result result, ITunerSession session); + generates (Result result, ITunerSession session); /** * Fetch image from radio module cache. @@ -100,4 +102,28 @@ interface IBroadcastRadio { * or a zero-length vector if identifier doesn't exist. */ getImage(uint32_t id) generates (vec image); + + /** + * Registers announcement observer. + * + * If there is at least one observer registered, HAL implementation must + * notify about announcements even if no sessions are active. + * + * If the observer dies, the HAL implementation must unregister observer + * automatically. + * + * @param enabled The list of announcement types to watch for. + * @param cb The callback interface. + * @return result OK in case of success. + * NOT_SUPPORTED if the tuner doesn't support announcements. + * @return closeHandle A handle to unregister observer, + * nullptr if result was not OK. + */ + registerAnnouncementObserver( + vec enabled, + IAnnouncementObserver cb + ) generates ( + Result result, + ICloseHandle closeHandle + ); }; diff --git a/broadcastradio/2.0/ICloseHandle.hal b/broadcastradio/2.0/ICloseHandle.hal new file mode 100644 index 0000000000..34cea146d3 --- /dev/null +++ b/broadcastradio/2.0/ICloseHandle.hal @@ -0,0 +1,32 @@ +/* Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.broadcastradio@2.0; + +/** + * Represents a generic close handle to remove a callback that doesn't need + * active interface. + */ +interface ICloseHandle { + /** + * Closes the handle. + * + * The call must not fail and must only be issued once. + * + * After the close call is executed, no other calls to this interface + * are allowed. + */ + close(); +}; diff --git a/broadcastradio/2.0/ITunerSession.hal b/broadcastradio/2.0/ITunerSession.hal index a3f93fd946..a58fa62ef9 100644 --- a/broadcastradio/2.0/ITunerSession.hal +++ b/broadcastradio/2.0/ITunerSession.hal @@ -154,7 +154,7 @@ interface ITunerSession { * @return results Operation completion status for parameters being set. */ setParameters(vec parameters) - generates (vec results); + generates (vec results); /** * Generic method for retrieving vendor-specific parameter values. diff --git a/broadcastradio/2.0/default/BroadcastRadio.cpp b/broadcastradio/2.0/default/BroadcastRadio.cpp index 5dde8a7bea..d16aaff7ff 100644 --- a/broadcastradio/2.0/default/BroadcastRadio.cpp +++ b/broadcastradio/2.0/default/BroadcastRadio.cpp @@ -141,6 +141,15 @@ Return BroadcastRadio::getImage(uint32_t id, getImage_cb _hidl_cb) { return {}; } +Return BroadcastRadio::registerAnnouncementObserver( + const hidl_vec& enabled, const sp& /* cb */, + registerAnnouncementObserver_cb _hidl_cb) { + ALOGV("%s(%s)", __func__, toString(enabled).c_str()); + + _hidl_cb(Result::NOT_SUPPORTED, nullptr); + return {}; +} + } // namespace implementation } // namespace V2_0 } // namespace broadcastradio diff --git a/broadcastradio/2.0/default/BroadcastRadio.h b/broadcastradio/2.0/default/BroadcastRadio.h index 733cadf8a4..7904946e22 100644 --- a/broadcastradio/2.0/default/BroadcastRadio.h +++ b/broadcastradio/2.0/default/BroadcastRadio.h @@ -36,6 +36,9 @@ struct BroadcastRadio : public IBroadcastRadio { Return getDabRegionConfig(getDabRegionConfig_cb _hidl_cb); Return openSession(const sp& callback, openSession_cb _hidl_cb) override; Return getImage(uint32_t id, getImage_cb _hidl_cb); + Return registerAnnouncementObserver(const hidl_vec& enabled, + const sp& cb, + registerAnnouncementObserver_cb _hidl_cb); std::reference_wrapper mVirtualRadio; Properties mProperties; diff --git a/broadcastradio/2.0/types.hal b/broadcastradio/2.0/types.hal index 38a5709a29..d77e8c12f6 100644 --- a/broadcastradio/2.0/types.hal +++ b/broadcastradio/2.0/types.hal @@ -777,3 +777,55 @@ struct ProgramFilter { */ bool excludeModifications; }; + +/** + * Type of an announcement. + * + * It maps to different announcement types per each radio technology. + */ +enum AnnouncementType : uint8_t { + /** DAB alarm, RDS emergency program type (PTY 31). */ + EMERGENCY = 1, + + /** DAB warning. */ + WARNING, + + /** DAB road traffic, RDS TA, HD Radio transportation. */ + TRAFFIC, + + /** Weather. */ + WEATHER, + + /** News. */ + NEWS, + + /** DAB event, special event. */ + EVENT, + + /** DAB sport report, RDS sports. */ + SPORT, + + /** All others. */ + MISC, +}; + +/** + * A pointer to a station broadcasting active announcement. + */ +struct Announcement { + /** + * Program selector to tune to the announcement. + */ + ProgramSelector selector; + + /** Announcement type. */ + AnnouncementType type; + + /** + * Vendor-specific information. + * + * It may be used for extra features, not supported by the platform, + * for example: com.me.hdradio.urgency=100; com.me.hdradio.certainity=50. + */ + vec vendorInfo; +}; diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp index 87ac93415e..aa75442f0e 100644 --- a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp +++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp @@ -89,6 +89,10 @@ class TunerCallbackMock : public ITunerCallback { utils::ProgramInfoSet mProgramList; }; +struct AnnouncementObserverMock : public IAnnouncementObserver { + MOCK_METHOD1(onListUpdated, Return(const hidl_vec&)); +}; + class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase { protected: virtual void SetUp() override; @@ -660,6 +664,40 @@ TEST_F(BroadcastRadioHalTest, GetProgramList) { EXPECT_TRUE(stopResult.isOk()); } +/** + * Test announcement observer registration. + * + * Verifies that: + * - registerAnnouncementObserver either succeeds or returns NOT_SUPPORTED; + * - if it succeeds, it returns a valid close handle (which is a nullptr otherwise); + * - closing handle does not crash. + */ +TEST_F(BroadcastRadioHalTest, AnnouncementObserverRegistration) { + sp observer = new AnnouncementObserverMock(); + + Result halResult = Result::UNKNOWN_ERROR; + sp closeHandle = nullptr; + auto cb = [&](Result result, const sp& closeHandle_) { + halResult = result; + closeHandle = closeHandle_; + }; + + auto hidlResult = + mModule->registerAnnouncementObserver({AnnouncementType::EMERGENCY}, observer, cb); + ASSERT_TRUE(hidlResult.isOk()); + + if (halResult == Result::NOT_SUPPORTED) { + ASSERT_EQ(nullptr, closeHandle.get()); + printSkipped("Announcements not supported"); + return; + } + + ASSERT_EQ(Result::OK, halResult); + ASSERT_NE(nullptr, closeHandle.get()); + + closeHandle->close(); +} + // TODO(b/70939328): test ProgramInfo's currentlyTunedId and // currentlyTunedChannel once the program list is implemented.