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 "Tuner"
18//#define LOG_NDEBUG 0
19
20#include <log/log.h>
21
22#include "BroadcastRadio.h"
23#include "Tuner.h"
24#include "Utils.h"
25#include <system/RadioMetadataWrapper.h>
26
27namespace android {
28namespace hardware {
29namespace broadcastradio {
30namespace V1_0 {
31namespace implementation {
32
33void Tuner::onCallback(radio_hal_event_t *halEvent)
34{
35    BandConfig config;
36    ProgramInfo info;
37    hidl_vec<MetaData> metadata;
38
39    if (mCallback != 0) {
40        switch(halEvent->type) {
41        case RADIO_EVENT_CONFIG:
42            Utils::convertBandConfigFromHal(&config, &halEvent->config);
43            mCallback->configChange(Utils::convertHalResult(halEvent->status), config);
44            break;
45        case RADIO_EVENT_ANTENNA:
46            mCallback->antennaStateChange(halEvent->on);
47            break;
48        case RADIO_EVENT_TUNED:
49            Utils::convertProgramInfoFromHal(&info, &halEvent->info);
50            mCallback->tuneComplete(Utils::convertHalResult(halEvent->status), info);
51            break;
52        case RADIO_EVENT_METADATA: {
53            uint32_t channel;
54            uint32_t sub_channel;
55            if (radio_metadata_get_channel(halEvent->metadata, &channel, &sub_channel) == 0) {
56                Utils::convertMetaDataFromHal(metadata, halEvent->metadata);
57                mCallback->newMetadata(channel, sub_channel, metadata);
58            }
59            } break;
60        case RADIO_EVENT_TA:
61            mCallback->trafficAnnouncement(halEvent->on);
62            break;
63        case RADIO_EVENT_AF_SWITCH:
64            Utils::convertProgramInfoFromHal(&info, &halEvent->info);
65            mCallback->afSwitch(info);
66            break;
67        case RADIO_EVENT_EA:
68            mCallback->emergencyAnnouncement(halEvent->on);
69            break;
70        case RADIO_EVENT_HW_FAILURE:
71        default:
72            mCallback->hardwareFailure();
73            break;
74        }
75    }
76}
77
78//static
79void Tuner::callback(radio_hal_event_t *halEvent, void *cookie)
80{
81    wp<Tuner> weak(reinterpret_cast<Tuner*>(cookie));
82    sp<Tuner> tuner = weak.promote();
83    if (tuner == 0) return;
84    tuner->onCallback(halEvent);
85}
86
87Tuner::Tuner(const sp<ITunerCallback>& callback, const wp<BroadcastRadio>& parentDevice)
88    : mHalTuner(NULL), mCallback(callback), mParentDevice(parentDevice)
89{
90    ALOGV("%s", __FUNCTION__);
91}
92
93
94Tuner::~Tuner()
95{
96    ALOGV("%s", __FUNCTION__);
97    const sp<BroadcastRadio> parentDevice = mParentDevice.promote();
98    if (parentDevice != 0) {
99        parentDevice->closeHalTuner(mHalTuner);
100    }
101}
102
103// Methods from ::android::hardware::broadcastradio::V1_0::ITuner follow.
104Return<Result> Tuner::setConfiguration(const BandConfig& config)  {
105    ALOGV("%s", __FUNCTION__);
106    if (mHalTuner == NULL) {
107        return Utils::convertHalResult(-ENODEV);
108    }
109    radio_hal_band_config_t halConfig;
110    Utils::convertBandConfigToHal(&halConfig, &config);
111    int rc = mHalTuner->set_configuration(mHalTuner, &halConfig);
112    return Utils::convertHalResult(rc);
113}
114
115Return<void> Tuner::getConfiguration(getConfiguration_cb _hidl_cb)  {
116    int rc;
117    radio_hal_band_config_t halConfig;
118    BandConfig config;
119
120    ALOGV("%s", __FUNCTION__);
121    if (mHalTuner == NULL) {
122        rc = -ENODEV;
123        goto exit;
124    }
125    rc = mHalTuner->get_configuration(mHalTuner, &halConfig);
126    if (rc == 0) {
127        Utils::convertBandConfigFromHal(&config, &halConfig);
128    }
129
130exit:
131    _hidl_cb(Utils::convertHalResult(rc), config);
132    return Void();
133}
134
135Return<Result> Tuner::scan(Direction direction, bool skipSubChannel)  {
136    if (mHalTuner == NULL) {
137        return Utils::convertHalResult(-ENODEV);
138    }
139    int rc = mHalTuner->scan(mHalTuner, static_cast<radio_direction_t>(direction), skipSubChannel);
140    return Utils::convertHalResult(rc);
141}
142
143Return<Result> Tuner::step(Direction direction, bool skipSubChannel)  {
144    if (mHalTuner == NULL) {
145        return Utils::convertHalResult(-ENODEV);
146    }
147    int rc = mHalTuner->step(mHalTuner, static_cast<radio_direction_t>(direction), skipSubChannel);
148    return Utils::convertHalResult(rc);
149}
150
151Return<Result> Tuner::tune(uint32_t channel, uint32_t subChannel)  {
152    if (mHalTuner == NULL) {
153        return Utils::convertHalResult(-ENODEV);
154    }
155    int rc = mHalTuner->tune(mHalTuner, channel, subChannel);
156    return Utils::convertHalResult(rc);
157}
158
159Return<Result> Tuner::cancel()  {
160    if (mHalTuner == NULL) {
161        return Utils::convertHalResult(-ENODEV);
162    }
163    int rc = mHalTuner->cancel(mHalTuner);
164    return Utils::convertHalResult(rc);
165}
166
167Return<void> Tuner::getProgramInformation(getProgramInformation_cb _hidl_cb)  {
168    int rc;
169    radio_program_info_t halInfo;
170    RadioMetadataWrapper metadataWrapper(&halInfo.metadata);
171    ProgramInfo info;
172
173    ALOGV("%s", __FUNCTION__);
174    if (mHalTuner == NULL) {
175        rc = -ENODEV;
176        goto exit;
177    }
178
179    rc = mHalTuner->get_program_information(mHalTuner, &halInfo);
180    if (rc == 0) {
181        Utils::convertProgramInfoFromHal(&info, &halInfo);
182    }
183
184exit:
185    _hidl_cb(Utils::convertHalResult(rc), info);
186    return Void();
187}
188
189} // namespace implementation
190}  // namespace V1_0
191}  // namespace broadcastradio
192}  // namespace hardware
193}  // namespace android
194