blob: 34a6db7ce5e021e76f7cb6eb2a3c25d735f14f59 [file] [log] [blame]
Eric Laurent73e17f22016-11-21 10:40:36 -08001/*
2 * Copyright (C) 2016 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
17#define LOG_TAG "RadioHalHidl"
18//#define LOG_NDEBUG 0
19
20#include <utils/Log.h>
21#include <utils/misc.h>
22#include <system/radio_metadata.h>
23#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
24
25#include "RadioHalHidl.h"
26#include "HidlUtils.h"
27
28namespace android {
29
30using android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory;
31using android::hardware::broadcastradio::V1_0::Class;
32using android::hardware::broadcastradio::V1_0::Direction;
33using android::hardware::broadcastradio::V1_0::Properties;
34
35
36/* static */
37sp<RadioInterface> RadioInterface::connectModule(radio_class_t classId)
38{
39 return new RadioHalHidl(classId);
40}
41
42int RadioHalHidl::getProperties(radio_hal_properties_t *properties)
43{
44 ALOGV("%s IN", __FUNCTION__);
45 sp<IBroadcastRadio> module = getService();
46 if (module == 0) {
47 return -ENODEV;
48 }
49 Properties halProperties;
Steven Morelande83be8a2017-01-06 11:06:33 -080050 Result halResult = Result::NOT_INITIALIZED;
Eric Laurent73e17f22016-11-21 10:40:36 -080051 Return<void> hidlReturn =
52 module->getProperties([&](Result result, const Properties& properties) {
53 halResult = result;
54 if (result == Result::OK) {
55 halProperties = properties;
56 }
57 });
58
Eric Laurent73e17f22016-11-21 10:40:36 -080059 if (halResult == Result::OK) {
60 HidlUtils::convertPropertiesFromHal(properties, &halProperties);
61 }
62 return HidlUtils::convertHalResult(halResult);
63}
64
65int RadioHalHidl::openTuner(const radio_hal_band_config_t *config,
66 bool audio,
67 sp<TunerCallbackInterface> callback,
68 sp<TunerInterface>& tuner)
69{
70 sp<IBroadcastRadio> module = getService();
71 if (module == 0) {
72 return -ENODEV;
73 }
74 sp<Tuner> tunerImpl = new Tuner(callback, this);
75
76 BandConfig halConfig;
Steven Morelande83be8a2017-01-06 11:06:33 -080077 Result halResult = Result::NOT_INITIALIZED;
Eric Laurent73e17f22016-11-21 10:40:36 -080078 sp<ITuner> halTuner;
79
80 HidlUtils::convertBandConfigToHal(&halConfig, config);
81 Return<void> hidlReturn =
82 module->openTuner(halConfig, audio, tunerImpl,
83 [&](Result result, const sp<ITuner>& tuner) {
84 halResult = result;
85 if (result == Result::OK) {
86 halTuner = tuner;
87 }
88 });
89
Eric Laurent73e17f22016-11-21 10:40:36 -080090 if (halResult == Result::OK) {
91 tunerImpl->setHalTuner(halTuner);
92 tuner = tunerImpl;
93 }
94
95 return HidlUtils::convertHalResult(halResult);
96}
97
98int RadioHalHidl::closeTuner(sp<TunerInterface>& tuner)
99{
100 sp<Tuner> tunerImpl = static_cast<Tuner *>(tuner.get());
101 sp<ITuner> clearTuner;
102 tunerImpl->setHalTuner(clearTuner);
103 return 0;
104}
105
106RadioHalHidl::RadioHalHidl(radio_class_t classId)
107 : mClassId(classId)
108{
109}
110
111RadioHalHidl::~RadioHalHidl()
112{
113}
114
115sp<IBroadcastRadio> RadioHalHidl::getService()
116{
117 if (mHalModule == 0) {
118 sp<IBroadcastRadioFactory> factory = IBroadcastRadioFactory::getService("broadcastradio");
119 if (factory != 0) {
120 factory->connectModule(static_cast<Class>(mClassId),
121 [&](Result retval, const ::android::sp<IBroadcastRadio>& result) {
122 if (retval == Result::OK) {
123 mHalModule = result;
124 }
125 });
126 }
127 }
128 ALOGV("%s OUT module %p", __FUNCTION__, mHalModule.get());
129 return mHalModule;
130}
131
132void RadioHalHidl::clearService()
133{
134 ALOGV("%s IN module %p", __FUNCTION__, mHalModule.get());
135 mHalModule.clear();
136}
137
138
139int RadioHalHidl::Tuner::setConfiguration(const radio_hal_band_config_t *config)
140{
141 ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
142
143 if (mHalTuner == 0) {
144 return -ENODEV;
145 }
146 BandConfig halConfig;
147 HidlUtils::convertBandConfigToHal(&halConfig, config);
148
149 Return<Result> hidlResult = mHalTuner->setConfiguration(halConfig);
Eric Laurent73e17f22016-11-21 10:40:36 -0800150 return HidlUtils::convertHalResult(hidlResult);
151}
152
153int RadioHalHidl::Tuner::getConfiguration(radio_hal_band_config_t *config)
154{
155 ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
156 if (mHalTuner == 0) {
157 return -ENODEV;
158 }
159 BandConfig halConfig;
160 Result halResult;
161 Return<void> hidlReturn =
162 mHalTuner->getConfiguration([&](Result result, const BandConfig& config) {
163 halResult = result;
164 if (result == Result::OK) {
165 halConfig = config;
166 }
167 });
Steven Morelande83be8a2017-01-06 11:06:33 -0800168 if (hidlReturn.isOk() && halResult == Result::OK) {
Eric Laurent73e17f22016-11-21 10:40:36 -0800169 HidlUtils::convertBandConfigFromHal(config, &halConfig);
170 }
171 return HidlUtils::convertHalResult(halResult);
172}
173
174int RadioHalHidl::Tuner::scan(radio_direction_t direction, bool skip_sub_channel)
175{
176 ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
177 if (mHalTuner == 0) {
178 return -ENODEV;
179 }
180 Return<Result> hidlResult =
181 mHalTuner->scan(static_cast<Direction>(direction), skip_sub_channel);
Eric Laurent73e17f22016-11-21 10:40:36 -0800182 return HidlUtils::convertHalResult(hidlResult);
183}
184
185int RadioHalHidl::Tuner::step(radio_direction_t direction, bool skip_sub_channel)
186{
187 ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
188 if (mHalTuner == 0) {
189 return -ENODEV;
190 }
191 Return<Result> hidlResult =
192 mHalTuner->step(static_cast<Direction>(direction), skip_sub_channel);
Eric Laurent73e17f22016-11-21 10:40:36 -0800193 return HidlUtils::convertHalResult(hidlResult);
194}
195
196int RadioHalHidl::Tuner::tune(unsigned int channel, unsigned int sub_channel)
197{
198 ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
199 if (mHalTuner == 0) {
200 return -ENODEV;
201 }
202 Return<Result> hidlResult =
203 mHalTuner->tune(channel, sub_channel);
Eric Laurent73e17f22016-11-21 10:40:36 -0800204 return HidlUtils::convertHalResult(hidlResult);
205}
206
207int RadioHalHidl::Tuner::cancel()
208{
209 ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
210 if (mHalTuner == 0) {
211 return -ENODEV;
212 }
213 Return<Result> hidlResult = mHalTuner->cancel();
Eric Laurent73e17f22016-11-21 10:40:36 -0800214 return HidlUtils::convertHalResult(hidlResult);
215}
216
217int RadioHalHidl::Tuner::getProgramInformation(radio_program_info_t *info)
218{
219 ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
220 if (mHalTuner == 0) {
221 return -ENODEV;
222 }
Tomasz Wasilczyk049475c2017-01-06 14:17:04 -0800223 if (info == nullptr || info->metadata == nullptr) {
224 return BAD_VALUE;
225 }
Eric Laurent73e17f22016-11-21 10:40:36 -0800226 ProgramInfo halInfo;
227 Result halResult;
Eric Laurent73e17f22016-11-21 10:40:36 -0800228 Return<void> hidlReturn = mHalTuner->getProgramInformation(
Tomasz Wasilczyk049475c2017-01-06 14:17:04 -0800229 [&](Result result, const ProgramInfo& info) {
230 halResult = result;
231 if (result == Result::OK) {
232 halInfo = info;
233 }
234 });
Steven Morelande83be8a2017-01-06 11:06:33 -0800235 if (hidlReturn.isOk() && halResult == Result::OK) {
Tomasz Wasilczyk049475c2017-01-06 14:17:04 -0800236 HidlUtils::convertProgramInfoFromHal(info, &halInfo);
Eric Laurent73e17f22016-11-21 10:40:36 -0800237 }
238 return HidlUtils::convertHalResult(halResult);
239}
240
241Return<void> RadioHalHidl::Tuner::hardwareFailure()
242{
243 ALOGV("%s IN", __FUNCTION__);
244 handleHwFailure();
245 return Return<void>();
246}
247
248Return<void> RadioHalHidl::Tuner::configChange(Result result, const BandConfig& config)
249{
250 ALOGV("%s IN", __FUNCTION__);
251 radio_hal_event_t event;
252 memset(&event, 0, sizeof(radio_hal_event_t));
253 event.type = RADIO_EVENT_CONFIG;
254 event.status = HidlUtils::convertHalResult(result);
255 HidlUtils::convertBandConfigFromHal(&event.config, &config);
256 onCallback(&event);
257 return Return<void>();
258}
259
260Return<void> RadioHalHidl::Tuner::tuneComplete(Result result, const ProgramInfo& info)
261{
262 ALOGV("%s IN", __FUNCTION__);
263 radio_hal_event_t event;
264 memset(&event, 0, sizeof(radio_hal_event_t));
265 event.type = RADIO_EVENT_TUNED;
266 event.status = HidlUtils::convertHalResult(result);
Tomasz Wasilczyk049475c2017-01-06 14:17:04 -0800267 HidlUtils::convertProgramInfoFromHal(&event.info, &info);
Eric Laurent73e17f22016-11-21 10:40:36 -0800268 onCallback(&event);
Tomasz Wasilczyk049475c2017-01-06 14:17:04 -0800269 radio_metadata_deallocate(event.info.metadata);
Eric Laurent73e17f22016-11-21 10:40:36 -0800270 return Return<void>();
271}
272
273Return<void> RadioHalHidl::Tuner::afSwitch(const ProgramInfo& info)
274{
275 ALOGV("%s IN", __FUNCTION__);
276 radio_hal_event_t event;
277 memset(&event, 0, sizeof(radio_hal_event_t));
278 event.type = RADIO_EVENT_AF_SWITCH;
Tomasz Wasilczyk049475c2017-01-06 14:17:04 -0800279 HidlUtils::convertProgramInfoFromHal(&event.info, &info);
Eric Laurent73e17f22016-11-21 10:40:36 -0800280 onCallback(&event);
281 if (event.info.metadata != NULL) {
282 radio_metadata_deallocate(event.info.metadata);
283 }
284 return Return<void>();
285}
286
287Return<void> RadioHalHidl::Tuner::antennaStateChange(bool connected)
288{
289 ALOGV("%s IN", __FUNCTION__);
290 radio_hal_event_t event;
291 memset(&event, 0, sizeof(radio_hal_event_t));
292 event.type = RADIO_EVENT_ANTENNA;
293 event.on = connected;
294 onCallback(&event);
295 return Return<void>();
296}
297Return<void> RadioHalHidl::Tuner::trafficAnnouncement(bool active)
298{
299 ALOGV("%s IN", __FUNCTION__);
300 radio_hal_event_t event;
301 memset(&event, 0, sizeof(radio_hal_event_t));
302 event.type = RADIO_EVENT_TA;
303 event.on = active;
304 onCallback(&event);
305 return Return<void>();
306}
307Return<void> RadioHalHidl::Tuner::emergencyAnnouncement(bool active)
308{
309 ALOGV("%s IN", __FUNCTION__);
310 radio_hal_event_t event;
311 memset(&event, 0, sizeof(radio_hal_event_t));
312 event.type = RADIO_EVENT_EA;
313 event.on = active;
314 onCallback(&event);
315 return Return<void>();
316}
317Return<void> RadioHalHidl::Tuner::newMetadata(uint32_t channel, uint32_t subChannel,
318 const ::android::hardware::hidl_vec<MetaData>& metadata)
319{
320 ALOGV("%s IN", __FUNCTION__);
321 radio_hal_event_t event;
322 memset(&event, 0, sizeof(radio_hal_event_t));
323 event.type = RADIO_EVENT_METADATA;
324 HidlUtils::convertMetaDataFromHal(&event.metadata, metadata, channel, subChannel);
325 onCallback(&event);
326 if (event.metadata != NULL) {
327 radio_metadata_deallocate(event.info.metadata);
328 }
329 return Return<void>();
330}
331
332
333RadioHalHidl::Tuner::Tuner(sp<TunerCallbackInterface> callback, sp<RadioHalHidl> module)
334 : TunerInterface(), mHalTuner(NULL), mCallback(callback), mParentModule(module)
335{
336}
337
338
339RadioHalHidl::Tuner::~Tuner()
340{
341}
342
343void RadioHalHidl::Tuner::handleHwFailure()
344{
345 ALOGV("%s IN", __FUNCTION__);
346 sp<RadioHalHidl> parentModule = mParentModule.promote();
347 if (parentModule != 0) {
348 parentModule->clearService();
349 }
350 radio_hal_event_t event;
351 memset(&event, 0, sizeof(radio_hal_event_t));
352 event.type = RADIO_EVENT_HW_FAILURE;
353 onCallback(&event);
354 mHalTuner.clear();
355}
356
Eric Laurent73e17f22016-11-21 10:40:36 -0800357void RadioHalHidl::Tuner::onCallback(radio_hal_event_t *halEvent)
358{
359 if (mCallback != 0) {
360 mCallback->onEvent(halEvent);
361 }
362}
363
364} // namespace android