• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
BpRadioService(const sp<IBinder> & impl)48     BpRadioService(const sp<IBinder>& impl)
49         : BpInterface<IRadioService>(impl)
50     {
51     }
52 
listModules(struct radio_properties * properties,uint32_t * numModules)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 
attach(radio_handle_t handle,const sp<IRadioClient> & client,const struct radio_band_config * config,bool withAudio,sp<IRadio> & radio)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 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)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