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 #define LOG_TAG "BcRadioDef.module"
17 #define LOG_NDEBUG 0
18
19 #include "BroadcastRadio.h"
20
21 #include <log/log.h>
22
23 #include "resources.h"
24
25 namespace android {
26 namespace hardware {
27 namespace broadcastradio {
28 namespace V2_0 {
29 namespace implementation {
30
31 using std::lock_guard;
32 using std::map;
33 using std::mutex;
34 using std::vector;
35
36 static const AmFmRegionConfig gDefaultAmFmConfig = { //
37 {
38 {87500, 108000, 100, 100}, // FM
39 {153, 282, 3, 9}, // AM LW
40 {531, 1620, 9, 9}, // AM MW
41 {1600, 30000, 1, 5}, // AM SW
42 },
43 static_cast<uint32_t>(Deemphasis::D50),
44 static_cast<uint32_t>(Rds::RDS)};
45
initProperties(const VirtualRadio & virtualRadio)46 static Properties initProperties(const VirtualRadio& virtualRadio) {
47 Properties prop = {};
48
49 prop.maker = "Google";
50 prop.product = virtualRadio.getName();
51 prop.supportedIdentifierTypes = hidl_vec<uint32_t>({
52 static_cast<uint32_t>(IdentifierType::AMFM_FREQUENCY),
53 static_cast<uint32_t>(IdentifierType::RDS_PI),
54 static_cast<uint32_t>(IdentifierType::HD_STATION_ID_EXT),
55 });
56 prop.vendorInfo = hidl_vec<VendorKeyValue>({
57 {"com.google.dummy", "dummy"},
58 });
59
60 return prop;
61 }
62
BroadcastRadio(const VirtualRadio & virtualRadio)63 BroadcastRadio::BroadcastRadio(const VirtualRadio& virtualRadio)
64 : mVirtualRadio(virtualRadio),
65 mProperties(initProperties(virtualRadio)),
66 mAmFmConfig(gDefaultAmFmConfig) {}
67
getProperties(getProperties_cb _hidl_cb)68 Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb) {
69 ALOGV("%s", __func__);
70 _hidl_cb(mProperties);
71 return {};
72 }
73
getAmFmConfig() const74 AmFmRegionConfig BroadcastRadio::getAmFmConfig() const {
75 lock_guard<mutex> lk(mMut);
76 return mAmFmConfig;
77 }
78
getAmFmRegionConfig(bool full,getAmFmRegionConfig_cb _hidl_cb)79 Return<void> BroadcastRadio::getAmFmRegionConfig(bool full, getAmFmRegionConfig_cb _hidl_cb) {
80 ALOGV("%s(%d)", __func__, full);
81
82 if (full) {
83 AmFmRegionConfig config = {};
84 config.ranges = hidl_vec<AmFmBandRange>({
85 {65000, 108000, 10, 0}, // FM
86 {150, 30000, 1, 0}, // AM
87 });
88 config.fmDeemphasis = Deemphasis::D50 | Deemphasis::D75;
89 config.fmRds = Rds::RDS | Rds::RBDS;
90 _hidl_cb(Result::OK, config);
91 return {};
92 } else {
93 _hidl_cb(Result::OK, getAmFmConfig());
94 return {};
95 }
96 }
97
getDabRegionConfig(getDabRegionConfig_cb _hidl_cb)98 Return<void> BroadcastRadio::getDabRegionConfig(getDabRegionConfig_cb _hidl_cb) {
99 ALOGV("%s", __func__);
100
101 hidl_vec<DabTableEntry> config = {
102 {"5A", 174928}, {"7D", 194064}, {"8A", 195936}, {"8B", 197648}, {"9A", 202928},
103 {"9B", 204640}, {"9C", 206352}, {"10B", 211648}, {"10C", 213360}, {"10D", 215072},
104 {"11A", 216928}, {"11B", 218640}, {"11C", 220352}, {"11D", 222064}, {"12A", 223936},
105 {"12B", 225648}, {"12C", 227360}, {"12D", 229072},
106 };
107
108 _hidl_cb(Result::OK, config);
109 return {};
110 }
111
openSession(const sp<ITunerCallback> & callback,openSession_cb _hidl_cb)112 Return<void> BroadcastRadio::openSession(const sp<ITunerCallback>& callback,
113 openSession_cb _hidl_cb) {
114 ALOGV("%s", __func__);
115
116 /* For the needs of default implementation it's fine to instantiate new session object
117 * out of the lock scope. If your implementation needs it, use reentrant lock.
118 */
119 sp<TunerSession> newSession = new TunerSession(*this, callback);
120
121 lock_guard<mutex> lk(mMut);
122
123 auto oldSession = mSession.promote();
124 if (oldSession != nullptr) {
125 ALOGI("Closing previously opened tuner");
126 oldSession->close();
127 mSession = nullptr;
128 }
129
130 mSession = newSession;
131
132 _hidl_cb(Result::OK, newSession);
133 return {};
134 }
135
getImage(uint32_t id,getImage_cb _hidl_cb)136 Return<void> BroadcastRadio::getImage(uint32_t id, getImage_cb _hidl_cb) {
137 ALOGV("%s(%x)", __func__, id);
138
139 if (id == resources::demoPngId) {
140 _hidl_cb(std::vector<uint8_t>(resources::demoPng, std::end(resources::demoPng)));
141 return {};
142 }
143
144 ALOGI("Image %x doesn't exists", id);
145 _hidl_cb({});
146 return {};
147 }
148
registerAnnouncementListener(const hidl_vec<AnnouncementType> & enabled,const sp<IAnnouncementListener> &,registerAnnouncementListener_cb _hidl_cb)149 Return<void> BroadcastRadio::registerAnnouncementListener(
150 const hidl_vec<AnnouncementType>& enabled, const sp<IAnnouncementListener>& /* listener */,
151 registerAnnouncementListener_cb _hidl_cb) {
152 ALOGV("%s(%s)", __func__, toString(enabled).c_str());
153
154 _hidl_cb(Result::NOT_SUPPORTED, nullptr);
155 return {};
156 }
157
158 } // namespace implementation
159 } // namespace V2_0
160 } // namespace broadcastradio
161 } // namespace hardware
162 } // namespace android
163