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 "BpRadioService"
     19 //
     20 #define LOG_NDEBUG 0
     21 
     22 #include <utils/Log.h>
     23 #include <utils/Errors.h>
     24 
     25 #include <stdint.h>
     26 #include <sys/types.h>
     27 #include <binder/IMemory.h>
     28 #include <binder/Parcel.h>
     29 #include <binder/IPCThreadState.h>
     30 #include <binder/IServiceManager.h>
     31 
     32 #include <radio/IRadioService.h>
     33 #include <radio/IRadio.h>
     34 #include <radio/IRadioClient.h>
     35 
     36 namespace android {
     37 
     38 enum {
     39     LIST_MODULES = IBinder::FIRST_CALL_TRANSACTION,
     40     ATTACH,
     41 };
     42 
     43 #define MAX_ITEMS_PER_LIST 1024
     44 
     45 class BpRadioService: public BpInterface<IRadioService>
     46 {
     47 public:
     48     BpRadioService(const sp<IBinder>& impl)
     49         : BpInterface<IRadioService>(impl)
     50     {
     51     }
     52 
     53     virtual status_t listModules(struct radio_properties *properties,
     54                                  uint32_t *numModules)
     55     {
     56         if (numModules == NULL || (*numModules != 0 && properties == NULL)) {
     57             return BAD_VALUE;
     58         }
     59         Parcel data, reply;
     60         data.writeInterfaceToken(IRadioService::getInterfaceDescriptor());
     61         unsigned int numModulesReq = (properties == NULL) ? 0 : *numModules;
     62         data.writeInt32(numModulesReq);
     63         status_t status = remote()->transact(LIST_MODULES, data, &reply);
     64         if (status == NO_ERROR) {
     65             status = (status_t)reply.readInt32();
     66             *numModules = (unsigned int)reply.readInt32();
     67         }
     68         ALOGV("listModules() status %d got *numModules %d", status, *numModules);
     69         if (status == NO_ERROR) {
     70             if (numModulesReq > *numModules) {
     71                 numModulesReq = *numModules;
     72             }
     73             if (numModulesReq > 0) {
     74                 reply.read(properties, numModulesReq * sizeof(struct radio_properties));
     75             }
     76         }
     77         return status;
     78     }
     79 
     80     virtual status_t attach(radio_handle_t handle,
     81                             const sp<IRadioClient>& client,
     82                             const struct radio_band_config *config,
     83                             bool withAudio,
     84                             sp<IRadio>& radio)
     85     {
     86         Parcel data, reply;
     87         data.writeInterfaceToken(IRadioService::getInterfaceDescriptor());
     88         data.writeInt32(handle);
     89         data.writeStrongBinder(IInterface::asBinder(client));
     90         ALOGV("attach() config %p withAudio %d region %d type %d",
     91               config == NULL ? 0 : config, withAudio, config->region, config->band.type);
     92         if (config == NULL) {
     93             data.writeInt32(0);
     94         } else {
     95             data.writeInt32(1);
     96             data.write(config, sizeof(struct radio_band_config));
     97         }
     98         data.writeInt32(withAudio ? 1 : 0);
     99         status_t status = remote()->transact(ATTACH, data, &reply);
    100         if (status != NO_ERROR) {
    101             return status;
    102         }
    103         status = reply.readInt32();
    104         if (reply.readInt32() != 0) {
    105             radio = interface_cast<IRadio>(reply.readStrongBinder());
    106         }
    107         return status;
    108     }
    109 };
    110 
    111 IMPLEMENT_META_INTERFACE(RadioService, "android.hardware.IRadioService");
    112 
    113 // ----------------------------------------------------------------------
    114 
    115 status_t BnRadioService::onTransact(
    116     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    117 {
    118     switch(code) {
    119         case LIST_MODULES: {
    120             CHECK_INTERFACE(IRadioService, data, reply);
    121             unsigned int numModulesReq = data.readInt32();
    122             if (numModulesReq > MAX_ITEMS_PER_LIST) {
    123                 numModulesReq = MAX_ITEMS_PER_LIST;
    124             }
    125             unsigned int numModules = numModulesReq;
    126             struct radio_properties *properties =
    127                     (struct radio_properties *)calloc(numModulesReq,
    128                                                       sizeof(struct radio_properties));
    129             if (properties == NULL) {
    130                 reply->writeInt32(NO_MEMORY);
    131                 reply->writeInt32(0);
    132                 return NO_ERROR;
    133             }
    134 
    135             status_t status = listModules(properties, &numModules);
    136             reply->writeInt32(status);
    137             reply->writeInt32(numModules);
    138             ALOGV("LIST_MODULES status %d got numModules %d", status, numModules);
    139 
    140             if (status == NO_ERROR) {
    141                 if (numModulesReq > numModules) {
    142                     numModulesReq = numModules;
    143                 }
    144                 reply->write(properties,
    145                              numModulesReq * sizeof(struct radio_properties));
    146             }
    147             free(properties);
    148             return NO_ERROR;
    149         } break;
    150 
    151         case ATTACH: {
    152             CHECK_INTERFACE(IRadioService, data, reply);
    153             radio_handle_t handle = data.readInt32();
    154             sp<IRadioClient> client =
    155                     interface_cast<IRadioClient>(data.readStrongBinder());
    156             struct radio_band_config config;
    157             struct radio_band_config *configPtr = NULL;
    158             if (data.readInt32() != 0) {
    159                 data.read(&config, sizeof(struct radio_band_config));
    160                 configPtr = &config;
    161             }
    162             bool withAudio = data.readInt32() != 0;
    163             ALOGV("ATTACH configPtr %p withAudio %d", configPtr, withAudio);
    164             sp<IRadio> radio;
    165             status_t status = attach(handle, client, configPtr, withAudio, radio);
    166             reply->writeInt32(status);
    167             if (radio != 0) {
    168                 reply->writeInt32(1);
    169                 reply->writeStrongBinder(IInterface::asBinder(radio));
    170             } else {
    171                 reply->writeInt32(0);
    172             }
    173             return NO_ERROR;
    174         } break;
    175         default:
    176             return BBinder::onTransact(code, data, reply, flags);
    177     }
    178 }
    179 
    180 // ----------------------------------------------------------------------------
    181 
    182 }; // namespace android
    183