1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "BroadcastRadio.h"
17
18 #include "resources.h"
19
20 #include <android-base/logging.h>
21
22 namespace android {
23 namespace hardware {
24 namespace broadcastradio {
25 namespace V2_0 {
26 namespace implementation {
27
28 using std::lock_guard;
29 using std::map;
30 using std::mutex;
31 using std::vector;
32
33 static const AmFmRegionConfig gDefaultAmFmConfig = { //
34 {
35 {87500, 108000, 100, 100}, // FM
36 {153, 282, 3, 9}, // AM LW
37 {531, 1620, 9, 9}, // AM MW
38 {1600, 30000, 1, 5}, // AM SW
39 },
40 static_cast<uint32_t>(Deemphasis::D50),
41 static_cast<uint32_t>(Rds::RDS)};
42
initProperties(const VirtualRadio & virtualRadio)43 static Properties initProperties(const VirtualRadio& virtualRadio) {
44 Properties prop = {};
45
46 prop.maker = "Google";
47 prop.product = virtualRadio.getName();
48 prop.supportedIdentifierTypes = hidl_vec<uint32_t>({
49 static_cast<uint32_t>(IdentifierType::AMFM_FREQUENCY),
50 static_cast<uint32_t>(IdentifierType::RDS_PI),
51 static_cast<uint32_t>(IdentifierType::HD_STATION_ID_EXT),
52 static_cast<uint32_t>(IdentifierType::DAB_SID_EXT),
53 });
54 prop.vendorInfo = hidl_vec<VendorKeyValue>({
55 {"com.google.dummy", "dummy"},
56 });
57
58 return prop;
59 }
60
BroadcastRadio(const VirtualRadio & virtualRadio)61 BroadcastRadio::BroadcastRadio(const VirtualRadio& virtualRadio)
62 : mVirtualRadio(virtualRadio),
63 mProperties(initProperties(virtualRadio)),
64 mAmFmConfig(gDefaultAmFmConfig) {}
65
getProperties(getProperties_cb _hidl_cb)66 Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb) {
67 _hidl_cb(mProperties);
68 return {};
69 }
70
getAmFmConfig() const71 AmFmRegionConfig BroadcastRadio::getAmFmConfig() const {
72 lock_guard<mutex> lk(mMut);
73 return mAmFmConfig;
74 }
75
getAmFmRegionConfig(bool full,getAmFmRegionConfig_cb _hidl_cb)76 Return<void> BroadcastRadio::getAmFmRegionConfig(bool full, getAmFmRegionConfig_cb _hidl_cb) {
77 if (full) {
78 AmFmRegionConfig config = {};
79 config.ranges = hidl_vec<AmFmBandRange>({
80 {65000, 108000, 10, 0}, // FM
81 {150, 30000, 1, 0}, // AM
82 });
83 config.fmDeemphasis = Deemphasis::D50 | Deemphasis::D75;
84 config.fmRds = Rds::RDS | Rds::RBDS;
85 _hidl_cb(Result::OK, config);
86 return {};
87 } else {
88 _hidl_cb(Result::OK, getAmFmConfig());
89 return {};
90 }
91 }
92
getDabRegionConfig(getDabRegionConfig_cb _hidl_cb)93 Return<void> BroadcastRadio::getDabRegionConfig(getDabRegionConfig_cb _hidl_cb) {
94 hidl_vec<DabTableEntry> config = {
95 {"5A", 174928}, {"7D", 194064}, {"8A", 195936}, {"8B", 197648}, {"9A", 202928},
96 {"9B", 204640}, {"9C", 206352}, {"10B", 211648}, {"10C", 213360}, {"10D", 215072},
97 {"11A", 216928}, {"11B", 218640}, {"11C", 220352}, {"11D", 222064}, {"12A", 223936},
98 {"12B", 225648}, {"12C", 227360}, {"12D", 229072},
99 };
100
101 _hidl_cb(Result::OK, config);
102 return {};
103 }
104
openSession(const sp<ITunerCallback> & callback,openSession_cb _hidl_cb)105 Return<void> BroadcastRadio::openSession(const sp<ITunerCallback>& callback,
106 openSession_cb _hidl_cb) {
107 LOG(DEBUG) << "opening new session...";
108
109 /* For the needs of default implementation it's fine to instantiate new session object
110 * out of the lock scope. If your implementation needs it, use reentrant lock.
111 */
112 sp<TunerSession> newSession = new TunerSession(*this, callback);
113
114 lock_guard<mutex> lk(mMut);
115
116 auto oldSession = mSession.promote();
117 if (oldSession != nullptr) {
118 LOG(INFO) << "closing previously opened tuner";
119 oldSession->close();
120 mSession = nullptr;
121 }
122
123 mSession = newSession;
124
125 _hidl_cb(Result::OK, newSession);
126 return {};
127 }
128
getImage(uint32_t id,getImage_cb _hidl_cb)129 Return<void> BroadcastRadio::getImage(uint32_t id, getImage_cb _hidl_cb) {
130 LOG(DEBUG) << "fetching image " << std::hex << id;
131
132 if (id == resources::demoPngId) {
133 _hidl_cb(std::vector<uint8_t>(resources::demoPng, std::end(resources::demoPng)));
134 return {};
135 }
136
137 LOG(INFO) << "image " << std::hex << id << " doesn't exists";
138 _hidl_cb({});
139 return {};
140 }
141
registerAnnouncementListener(const hidl_vec<AnnouncementType> & enabled,const sp<IAnnouncementListener> &,registerAnnouncementListener_cb _hidl_cb)142 Return<void> BroadcastRadio::registerAnnouncementListener(
143 const hidl_vec<AnnouncementType>& enabled, const sp<IAnnouncementListener>& /* listener */,
144 registerAnnouncementListener_cb _hidl_cb) {
145 LOG(DEBUG) << "registering announcement listener for " << toString(enabled);
146
147 _hidl_cb(Result::NOT_SUPPORTED, nullptr);
148 return {};
149 }
150
151 } // namespace implementation
152 } // namespace V2_0
153 } // namespace broadcastradio
154 } // namespace hardware
155 } // namespace android
156