• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 <media/audiohal/hidl/HalDeathHandler.h>
21 #include <utils/Log.h>
22 #include <utils/misc.h>
23 #include <system/RadioMetadataWrapper.h>
24 #include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
25 
26 #include "RadioHalHidl.h"
27 #include "HidlUtils.h"
28 
29 namespace android {
30 
31 using android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory;
32 using android::hardware::broadcastradio::V1_0::Class;
33 using android::hardware::broadcastradio::V1_0::Direction;
34 using android::hardware::broadcastradio::V1_0::Properties;
35 
36 
37 /* static */
connectModule(radio_class_t classId)38 sp<RadioInterface> RadioInterface::connectModule(radio_class_t classId)
39 {
40     return new RadioHalHidl(classId);
41 }
42 
getProperties(radio_hal_properties_t * properties)43 int RadioHalHidl::getProperties(radio_hal_properties_t *properties)
44 {
45     ALOGV("%s IN", __FUNCTION__);
46     sp<IBroadcastRadio> module = getService();
47     if (module == 0) {
48         return -ENODEV;
49     }
50     Properties halProperties;
51     Result halResult = Result::NOT_INITIALIZED;
52     Return<void> hidlReturn =
53             module->getProperties([&](Result result, const Properties& properties) {
54                     halResult = result;
55                     if (result == Result::OK) {
56                         halProperties = properties;
57                     }
58                 });
59 
60     if (halResult == Result::OK) {
61         HidlUtils::convertPropertiesFromHal(properties, &halProperties);
62     }
63     return HidlUtils::convertHalResult(halResult);
64 }
65 
openTuner(const radio_hal_band_config_t * config,bool audio,sp<TunerCallbackInterface> callback,sp<TunerInterface> & tuner)66 int RadioHalHidl::openTuner(const radio_hal_band_config_t *config,
67                             bool audio,
68                             sp<TunerCallbackInterface> callback,
69                             sp<TunerInterface>& tuner)
70 {
71     sp<IBroadcastRadio> module = getService();
72     if (module == 0) {
73         return -ENODEV;
74     }
75     sp<Tuner> tunerImpl = new Tuner(callback, this);
76 
77     BandConfig halConfig;
78     Result halResult = Result::NOT_INITIALIZED;
79     sp<ITuner> halTuner;
80 
81     HidlUtils::convertBandConfigToHal(&halConfig, config);
82     Return<void> hidlReturn =
83             module->openTuner(halConfig, audio, tunerImpl,
84                               [&](Result result, const sp<ITuner>& tuner) {
85                     halResult = result;
86                     if (result == Result::OK) {
87                         halTuner = tuner;
88                     }
89                 });
90 
91     if (halResult == Result::OK) {
92         tunerImpl->setHalTuner(halTuner);
93         tuner = tunerImpl;
94     }
95 
96     return HidlUtils::convertHalResult(halResult);
97 }
98 
closeTuner(sp<TunerInterface> & tuner)99 int RadioHalHidl::closeTuner(sp<TunerInterface>& tuner)
100 {
101     sp<Tuner> tunerImpl = static_cast<Tuner *>(tuner.get());
102     sp<ITuner> clearTuner;
103     tunerImpl->setHalTuner(clearTuner);
104     return 0;
105 }
106 
RadioHalHidl(radio_class_t classId)107 RadioHalHidl::RadioHalHidl(radio_class_t classId)
108     : mClassId(classId)
109 {
110 }
111 
~RadioHalHidl()112 RadioHalHidl::~RadioHalHidl()
113 {
114 }
115 
getService()116 sp<IBroadcastRadio> RadioHalHidl::getService()
117 {
118     if (mHalModule == 0) {
119         sp<IBroadcastRadioFactory> factory = IBroadcastRadioFactory::getService();
120         if (factory != 0) {
121             factory->connectModule(static_cast<Class>(mClassId),
122                                [&](Result retval, const ::android::sp<IBroadcastRadio>& result) {
123                 if (retval == Result::OK) {
124                     mHalModule = result;
125                 }
126             });
127         }
128     }
129     ALOGV("%s OUT module %p", __FUNCTION__, mHalModule.get());
130     return mHalModule;
131 }
132 
clearService()133 void RadioHalHidl::clearService()
134 {
135     ALOGV("%s IN module %p", __FUNCTION__, mHalModule.get());
136     mHalModule.clear();
137 }
138 
139 
setConfiguration(const radio_hal_band_config_t * config)140 int RadioHalHidl::Tuner::setConfiguration(const radio_hal_band_config_t *config)
141 {
142     ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
143 
144     if (mHalTuner == 0) {
145         return -ENODEV;
146     }
147     BandConfig halConfig;
148     HidlUtils::convertBandConfigToHal(&halConfig, config);
149 
150     Return<Result> hidlResult = mHalTuner->setConfiguration(halConfig);
151     return HidlUtils::convertHalResult(hidlResult);
152 }
153 
getConfiguration(radio_hal_band_config_t * config)154 int RadioHalHidl::Tuner::getConfiguration(radio_hal_band_config_t *config)
155 {
156     ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
157     if (mHalTuner == 0) {
158         return -ENODEV;
159     }
160     BandConfig halConfig;
161     Result halResult;
162     Return<void> hidlReturn =
163             mHalTuner->getConfiguration([&](Result result, const BandConfig& config) {
164                     halResult = result;
165                     if (result == Result::OK) {
166                         halConfig = config;
167                     }
168                 });
169     if (hidlReturn.isOk() && halResult == Result::OK) {
170         HidlUtils::convertBandConfigFromHal(config, &halConfig);
171     }
172     return HidlUtils::convertHalResult(halResult);
173 }
174 
scan(radio_direction_t direction,bool skip_sub_channel)175 int RadioHalHidl::Tuner::scan(radio_direction_t direction, bool skip_sub_channel)
176 {
177     ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
178     if (mHalTuner == 0) {
179         return -ENODEV;
180     }
181     Return<Result> hidlResult =
182             mHalTuner->scan(static_cast<Direction>(direction), skip_sub_channel);
183     return HidlUtils::convertHalResult(hidlResult);
184 }
185 
step(radio_direction_t direction,bool skip_sub_channel)186 int RadioHalHidl::Tuner::step(radio_direction_t direction, bool skip_sub_channel)
187 {
188     ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
189     if (mHalTuner == 0) {
190         return -ENODEV;
191     }
192     Return<Result> hidlResult =
193             mHalTuner->step(static_cast<Direction>(direction), skip_sub_channel);
194     return HidlUtils::convertHalResult(hidlResult);
195 }
196 
tune(unsigned int channel,unsigned int sub_channel)197 int RadioHalHidl::Tuner::tune(unsigned int channel, unsigned int sub_channel)
198 {
199     ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
200     if (mHalTuner == 0) {
201         return -ENODEV;
202     }
203     Return<Result> hidlResult =
204             mHalTuner->tune(channel, sub_channel);
205     return HidlUtils::convertHalResult(hidlResult);
206 }
207 
cancel()208 int RadioHalHidl::Tuner::cancel()
209 {
210     ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
211     if (mHalTuner == 0) {
212         return -ENODEV;
213     }
214     Return<Result> hidlResult = mHalTuner->cancel();
215     return HidlUtils::convertHalResult(hidlResult);
216 }
217 
getProgramInformation(radio_program_info_t * info)218 int RadioHalHidl::Tuner::getProgramInformation(radio_program_info_t *info)
219 {
220     ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
221     if (mHalTuner == 0) {
222         return -ENODEV;
223     }
224     if (info == nullptr || info->metadata == nullptr) {
225         return BAD_VALUE;
226     }
227     ProgramInfo halInfo;
228     Result halResult;
229     Return<void> hidlReturn = mHalTuner->getProgramInformation(
230         [&](Result result, const ProgramInfo& info) {
231             halResult = result;
232             if (result == Result::OK) {
233                 halInfo = info;
234             }
235         });
236     if (hidlReturn.isOk() && halResult == Result::OK) {
237         HidlUtils::convertProgramInfoFromHal(info, &halInfo);
238     }
239     return HidlUtils::convertHalResult(halResult);
240 }
241 
hardwareFailure()242 Return<void> RadioHalHidl::Tuner::hardwareFailure()
243 {
244     ALOGV("%s IN", __FUNCTION__);
245     handleHwFailure();
246     return Return<void>();
247 }
248 
configChange(Result result,const BandConfig & config)249 Return<void> RadioHalHidl::Tuner::configChange(Result result, const BandConfig& config)
250 {
251     ALOGV("%s IN", __FUNCTION__);
252     radio_hal_event_t event;
253     memset(&event, 0, sizeof(radio_hal_event_t));
254     event.type = RADIO_EVENT_CONFIG;
255     event.status = HidlUtils::convertHalResult(result);
256     HidlUtils::convertBandConfigFromHal(&event.config, &config);
257     onCallback(&event);
258     return Return<void>();
259 }
260 
tuneComplete(Result result,const ProgramInfo & info)261 Return<void> RadioHalHidl::Tuner::tuneComplete(Result result, const ProgramInfo& info)
262 {
263     ALOGV("%s IN", __FUNCTION__);
264     radio_hal_event_t event = {};
265     RadioMetadataWrapper metadataWrapper(&event.info.metadata);
266 
267     event.type = RADIO_EVENT_TUNED;
268     event.status = HidlUtils::convertHalResult(result);
269     HidlUtils::convertProgramInfoFromHal(&event.info, &info);
270     onCallback(&event);
271     return Return<void>();
272 }
273 
afSwitch(const ProgramInfo & info)274 Return<void> RadioHalHidl::Tuner::afSwitch(const ProgramInfo& info)
275 {
276     ALOGV("%s IN", __FUNCTION__);
277     radio_hal_event_t event = {};
278     RadioMetadataWrapper metadataWrapper(&event.info.metadata);
279 
280     event.type = RADIO_EVENT_AF_SWITCH;
281     HidlUtils::convertProgramInfoFromHal(&event.info, &info);
282     onCallback(&event);
283     return Return<void>();
284 }
285 
antennaStateChange(bool connected)286 Return<void> RadioHalHidl::Tuner::antennaStateChange(bool connected)
287 {
288     ALOGV("%s IN", __FUNCTION__);
289     radio_hal_event_t event;
290     memset(&event, 0, sizeof(radio_hal_event_t));
291     event.type = RADIO_EVENT_ANTENNA;
292     event.on = connected;
293     onCallback(&event);
294     return Return<void>();
295 }
trafficAnnouncement(bool active)296 Return<void> RadioHalHidl::Tuner::trafficAnnouncement(bool active)
297 {
298     ALOGV("%s IN", __FUNCTION__);
299     radio_hal_event_t event;
300     memset(&event, 0, sizeof(radio_hal_event_t));
301     event.type = RADIO_EVENT_TA;
302     event.on = active;
303     onCallback(&event);
304     return Return<void>();
305 }
emergencyAnnouncement(bool active)306 Return<void> RadioHalHidl::Tuner::emergencyAnnouncement(bool active)
307 {
308     ALOGV("%s IN", __FUNCTION__);
309     radio_hal_event_t event;
310     memset(&event, 0, sizeof(radio_hal_event_t));
311     event.type = RADIO_EVENT_EA;
312     event.on = active;
313     onCallback(&event);
314     return Return<void>();
315 }
newMetadata(uint32_t channel,uint32_t subChannel,const::android::hardware::hidl_vec<MetaData> & metadata)316 Return<void> RadioHalHidl::Tuner::newMetadata(uint32_t channel, uint32_t subChannel,
317                                           const ::android::hardware::hidl_vec<MetaData>& metadata)
318 {
319     ALOGV("%s IN", __FUNCTION__);
320     radio_hal_event_t event = {};
321     RadioMetadataWrapper metadataWrapper(&event.metadata);
322 
323     event.type = RADIO_EVENT_METADATA;
324     HidlUtils::convertMetaDataFromHal(&event.metadata, metadata, channel, subChannel);
325     onCallback(&event);
326     return Return<void>();
327 }
328 
329 
Tuner(sp<TunerCallbackInterface> callback,sp<RadioHalHidl> module)330 RadioHalHidl::Tuner::Tuner(sp<TunerCallbackInterface> callback, sp<RadioHalHidl> module)
331     : TunerInterface(), mHalTuner(NULL), mCallback(callback), mParentModule(module)
332 {
333     // Make sure the handler we are passing in only deals with const members,
334     // as it can be called on an arbitrary thread.
335     const auto& self = this;
336     HalDeathHandler::getInstance()->registerAtExitHandler(
337             this, [&self]() { self->sendHwFailureEvent(); });
338 }
339 
340 
~Tuner()341 RadioHalHidl::Tuner::~Tuner()
342 {
343     HalDeathHandler::getInstance()->unregisterAtExitHandler(this);
344 }
345 
setHalTuner(sp<ITuner> & halTuner)346 void RadioHalHidl::Tuner::setHalTuner(sp<ITuner>& halTuner) {
347     if (mHalTuner != 0) {
348         mHalTuner->unlinkToDeath(HalDeathHandler::getInstance());
349     }
350     mHalTuner = halTuner;
351     if (mHalTuner != 0) {
352         mHalTuner->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
353     }
354 }
355 
handleHwFailure()356 void RadioHalHidl::Tuner::handleHwFailure()
357 {
358     ALOGV("%s IN", __FUNCTION__);
359     sp<RadioHalHidl> parentModule = mParentModule.promote();
360     if (parentModule != 0) {
361         parentModule->clearService();
362     }
363     sendHwFailureEvent();
364     mHalTuner.clear();
365 }
366 
sendHwFailureEvent() const367 void RadioHalHidl::Tuner::sendHwFailureEvent() const
368 {
369     radio_hal_event_t event;
370     memset(&event, 0, sizeof(radio_hal_event_t));
371     event.type = RADIO_EVENT_HW_FAILURE;
372     onCallback(&event);
373 }
374 
onCallback(radio_hal_event_t * halEvent) const375 void RadioHalHidl::Tuner::onCallback(radio_hal_event_t *halEvent) const
376 {
377     if (mCallback != 0) {
378         mCallback->onEvent(halEvent);
379     }
380 }
381 
382 } // namespace android
383