Home | History | Annotate | Download | only in radio
      1 /*
      2 **
      3 ** Copyright 2015, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #define LOG_TAG "IRadio"
     19 #include <utils/Log.h>
     20 #include <utils/Errors.h>
     21 #include <binder/IMemory.h>
     22 #include <radio/IRadio.h>
     23 #include <radio/IRadioService.h>
     24 #include <radio/IRadioClient.h>
     25 #include <system/radio.h>
     26 #include <system/radio_metadata.h>
     27 
     28 namespace android {
     29 
     30 enum {
     31     DETACH = IBinder::FIRST_CALL_TRANSACTION,
     32     SET_CONFIGURATION,
     33     GET_CONFIGURATION,
     34     SET_MUTE,
     35     GET_MUTE,
     36     SCAN,
     37     STEP,
     38     TUNE,
     39     CANCEL,
     40     GET_PROGRAM_INFORMATION,
     41     HAS_CONTROL
     42 };
     43 
     44 class BpRadio: public BpInterface<IRadio>
     45 {
     46 public:
     47     BpRadio(const sp<IBinder>& impl)
     48         : BpInterface<IRadio>(impl)
     49     {
     50     }
     51 
     52     void detach()
     53     {
     54         ALOGV("detach");
     55         Parcel data, reply;
     56         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
     57         remote()->transact(DETACH, data, &reply);
     58     }
     59 
     60     virtual status_t setConfiguration(const struct radio_band_config *config)
     61     {
     62         Parcel data, reply;
     63         if (config == NULL) {
     64             return BAD_VALUE;
     65         }
     66         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
     67         data.write(config, sizeof(struct radio_band_config));
     68         status_t status = remote()->transact(SET_CONFIGURATION, data, &reply);
     69         if (status == NO_ERROR) {
     70             status = (status_t)reply.readInt32();
     71         }
     72         return status;
     73     }
     74 
     75     virtual status_t getConfiguration(struct radio_band_config *config)
     76     {
     77         Parcel data, reply;
     78         if (config == NULL) {
     79             return BAD_VALUE;
     80         }
     81         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
     82         status_t status = remote()->transact(GET_CONFIGURATION, data, &reply);
     83         if (status == NO_ERROR) {
     84             status = (status_t)reply.readInt32();
     85             if (status == NO_ERROR) {
     86                 reply.read(config, sizeof(struct radio_band_config));
     87             }
     88         }
     89         return status;
     90     }
     91 
     92     virtual status_t setMute(bool mute)
     93     {
     94         Parcel data, reply;
     95         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
     96         data.writeInt32(mute ? 1 : 0);
     97         status_t status = remote()->transact(SET_MUTE, data, &reply);
     98         if (status == NO_ERROR) {
     99             status = (status_t)reply.readInt32();
    100         }
    101         return status;
    102     }
    103 
    104     virtual status_t getMute(bool *mute)
    105     {
    106         Parcel data, reply;
    107         if (mute == NULL) {
    108             return BAD_VALUE;
    109         }
    110         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
    111         status_t status = remote()->transact(GET_MUTE, data, &reply);
    112         if (status == NO_ERROR) {
    113             status = (status_t)reply.readInt32();
    114             if (status == NO_ERROR) {
    115                 int muteread = reply.readInt32();
    116                 *mute = muteread != 0;
    117             }
    118         }
    119         return status;
    120     }
    121 
    122     virtual status_t scan(radio_direction_t direction, bool skipSubChannel)
    123     {
    124         Parcel data, reply;
    125         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
    126         data.writeInt32(direction);
    127         data.writeInt32(skipSubChannel ? 1 : 0);
    128         status_t status = remote()->transact(SCAN, data, &reply);
    129         if (status == NO_ERROR) {
    130             status = (status_t)reply.readInt32();
    131         }
    132         return status;
    133     }
    134 
    135     virtual status_t step(radio_direction_t direction, bool skipSubChannel)
    136     {
    137         Parcel data, reply;
    138         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
    139         data.writeInt32(direction);
    140         data.writeInt32(skipSubChannel ? 1 : 0);
    141         status_t status = remote()->transact(STEP, data, &reply);
    142         if (status == NO_ERROR) {
    143             status = (status_t)reply.readInt32();
    144         }
    145         return status;
    146     }
    147 
    148     virtual status_t tune(unsigned int channel, unsigned int subChannel)
    149     {
    150         Parcel data, reply;
    151         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
    152         data.writeInt32(channel);
    153         data.writeInt32(subChannel);
    154         status_t status = remote()->transact(TUNE, data, &reply);
    155         if (status == NO_ERROR) {
    156             status = (status_t)reply.readInt32();
    157         }
    158         return status;
    159     }
    160 
    161     virtual status_t cancel()
    162     {
    163         Parcel data, reply;
    164         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
    165         status_t status = remote()->transact(CANCEL, data, &reply);
    166         if (status == NO_ERROR) {
    167             status = (status_t)reply.readInt32();
    168         }
    169         return status;
    170     }
    171 
    172     virtual status_t getProgramInformation(struct radio_program_info *info)
    173     {
    174         Parcel data, reply;
    175         if (info == NULL) {
    176             return BAD_VALUE;
    177         }
    178         radio_metadata_t *metadata = info->metadata;
    179         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
    180         status_t status = remote()->transact(GET_PROGRAM_INFORMATION, data, &reply);
    181         if (status == NO_ERROR) {
    182             status = (status_t)reply.readInt32();
    183             if (status == NO_ERROR) {
    184                 reply.read(info, sizeof(struct radio_program_info));
    185                 info->metadata = metadata;
    186                 if (metadata == NULL) {
    187                     return status;
    188                 }
    189                 size_t size = (size_t)reply.readInt32();
    190                 if (size == 0) {
    191                     return status;
    192                 }
    193                 metadata =
    194                     (radio_metadata_t *)calloc(size / sizeof(unsigned int), sizeof(unsigned int));
    195                 if (metadata == NULL) {
    196                     return NO_MEMORY;
    197                 }
    198                 reply.read(metadata, size);
    199                 status = radio_metadata_add_metadata(&info->metadata, metadata);
    200                 free(metadata);
    201             }
    202         }
    203         return status;
    204     }
    205 
    206     virtual status_t hasControl(bool *hasControl)
    207     {
    208         Parcel data, reply;
    209         if (hasControl == NULL) {
    210             return BAD_VALUE;
    211         }
    212         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
    213         status_t status = remote()->transact(HAS_CONTROL, data, &reply);
    214         if (status == NO_ERROR) {
    215             status = (status_t)reply.readInt32();
    216             if (status == NO_ERROR) {
    217                 *hasControl = reply.readInt32() != 0;
    218             }
    219         }
    220         return status;
    221     }
    222 };
    223 
    224 IMPLEMENT_META_INTERFACE(Radio, "android.hardware.IRadio");
    225 
    226 // ----------------------------------------------------------------------
    227 
    228 status_t BnRadio::onTransact(
    229     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    230 {
    231     switch(code) {
    232         case DETACH: {
    233             ALOGV("DETACH");
    234             CHECK_INTERFACE(IRadio, data, reply);
    235             detach();
    236             return NO_ERROR;
    237         } break;
    238         case SET_CONFIGURATION: {
    239             CHECK_INTERFACE(IRadio, data, reply);
    240             struct radio_band_config config;
    241             data.read(&config, sizeof(struct radio_band_config));
    242             status_t status = setConfiguration(&config);
    243             reply->writeInt32(status);
    244             return NO_ERROR;
    245         }
    246         case GET_CONFIGURATION: {
    247             CHECK_INTERFACE(IRadio, data, reply);
    248             struct radio_band_config config;
    249             status_t status = getConfiguration(&config);
    250             reply->writeInt32(status);
    251             if (status == NO_ERROR) {
    252                 reply->write(&config, sizeof(struct radio_band_config));
    253             }
    254             return NO_ERROR;
    255         }
    256         case SET_MUTE: {
    257             CHECK_INTERFACE(IRadio, data, reply);
    258             bool mute = data.readInt32() != 0;
    259             status_t status = setMute(mute);
    260             reply->writeInt32(status);
    261             return NO_ERROR;
    262         }
    263         case GET_MUTE: {
    264             CHECK_INTERFACE(IRadio, data, reply);
    265             bool mute;
    266             status_t status = getMute(&mute);
    267             reply->writeInt32(status);
    268             if (status == NO_ERROR) {
    269                 reply->writeInt32(mute ? 1 : 0);
    270             }
    271             return NO_ERROR;
    272         }
    273         case SCAN: {
    274             CHECK_INTERFACE(IRadio, data, reply);
    275             radio_direction_t direction = (radio_direction_t)data.readInt32();
    276             bool skipSubChannel = data.readInt32() == 1;
    277             status_t status = scan(direction, skipSubChannel);
    278             reply->writeInt32(status);
    279             return NO_ERROR;
    280         }
    281         case STEP: {
    282             CHECK_INTERFACE(IRadio, data, reply);
    283             radio_direction_t direction = (radio_direction_t)data.readInt32();
    284             bool skipSubChannel = data.readInt32() == 1;
    285             status_t status = step(direction, skipSubChannel);
    286             reply->writeInt32(status);
    287             return NO_ERROR;
    288         }
    289         case TUNE: {
    290             CHECK_INTERFACE(IRadio, data, reply);
    291             unsigned int channel = (unsigned int)data.readInt32();
    292             unsigned int subChannel = (unsigned int)data.readInt32();
    293             status_t status = tune(channel, subChannel);
    294             reply->writeInt32(status);
    295             return NO_ERROR;
    296         }
    297         case CANCEL: {
    298             CHECK_INTERFACE(IRadio, data, reply);
    299             status_t status = cancel();
    300             reply->writeInt32(status);
    301             return NO_ERROR;
    302         }
    303         case GET_PROGRAM_INFORMATION: {
    304             CHECK_INTERFACE(IRadio, data, reply);
    305             struct radio_program_info info;
    306 
    307             status_t status = radio_metadata_allocate(&info.metadata, 0, 0);
    308             if (status != NO_ERROR) {
    309                 return status;
    310             }
    311             status = getProgramInformation(&info);
    312             reply->writeInt32(status);
    313             if (status == NO_ERROR) {
    314                 reply->write(&info, sizeof(struct radio_program_info));
    315                 int count = radio_metadata_get_count(info.metadata);
    316                 if (count > 0) {
    317                     size_t size = radio_metadata_get_size(info.metadata);
    318                     reply->writeInt32(size);
    319                     reply->write(info.metadata, size);
    320                 } else {
    321                     reply->writeInt32(0);
    322                 }
    323             }
    324             radio_metadata_deallocate(info.metadata);
    325             return NO_ERROR;
    326         }
    327         case HAS_CONTROL: {
    328             CHECK_INTERFACE(IRadio, data, reply);
    329             bool control;
    330             status_t status = hasControl(&control);
    331             reply->writeInt32(status);
    332             if (status == NO_ERROR) {
    333                 reply->writeInt32(control ? 1 : 0);
    334             }
    335             return NO_ERROR;
    336         }
    337         default:
    338             return BBinder::onTransact(code, data, reply, flags);
    339     }
    340 }
    341 
    342 // ----------------------------------------------------------------------------
    343 
    344 }; // namespace android
    345