• 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 "IRadio"
19 //#define LOG_NDEBUG 0
20 #include <utils/Log.h>
21 #include <utils/Errors.h>
22 #include <binder/IMemory.h>
23 #include <radio/IRadio.h>
24 #include <radio/IRadioService.h>
25 #include <radio/IRadioClient.h>
26 #include <system/radio.h>
27 #include <system/RadioMetadataWrapper.h>
28 
29 namespace android {
30 
31 enum {
32     DETACH = IBinder::FIRST_CALL_TRANSACTION,
33     SET_CONFIGURATION,
34     GET_CONFIGURATION,
35     SET_MUTE,
36     GET_MUTE,
37     SCAN,
38     STEP,
39     TUNE,
40     CANCEL,
41     GET_PROGRAM_INFORMATION,
42     HAS_CONTROL
43 };
44 
45 class BpRadio: public BpInterface<IRadio>
46 {
47 public:
BpRadio(const sp<IBinder> & impl)48     explicit BpRadio(const sp<IBinder>& impl)
49         : BpInterface<IRadio>(impl)
50     {
51     }
52 
detach()53     void detach()
54     {
55         ALOGV("detach");
56         Parcel data, reply;
57         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
58         remote()->transact(DETACH, data, &reply);
59     }
60 
setConfiguration(const struct radio_band_config * config)61     virtual status_t setConfiguration(const struct radio_band_config *config)
62     {
63         Parcel data, reply;
64         if (config == NULL) {
65             return BAD_VALUE;
66         }
67         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
68         data.write(config, sizeof(struct radio_band_config));
69         status_t status = remote()->transact(SET_CONFIGURATION, data, &reply);
70         if (status == NO_ERROR) {
71             status = (status_t)reply.readInt32();
72         }
73         return status;
74     }
75 
getConfiguration(struct radio_band_config * config)76     virtual status_t getConfiguration(struct radio_band_config *config)
77     {
78         Parcel data, reply;
79         if (config == NULL) {
80             return BAD_VALUE;
81         }
82         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
83         status_t status = remote()->transact(GET_CONFIGURATION, data, &reply);
84         if (status == NO_ERROR) {
85             status = (status_t)reply.readInt32();
86             if (status == NO_ERROR) {
87                 reply.read(config, sizeof(struct radio_band_config));
88             }
89         }
90         return status;
91     }
92 
setMute(bool mute)93     virtual status_t setMute(bool mute)
94     {
95         Parcel data, reply;
96         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
97         data.writeInt32(mute ? 1 : 0);
98         status_t status = remote()->transact(SET_MUTE, data, &reply);
99         if (status == NO_ERROR) {
100             status = (status_t)reply.readInt32();
101         }
102         return status;
103     }
104 
getMute(bool * mute)105     virtual status_t getMute(bool *mute)
106     {
107         Parcel data, reply;
108         if (mute == NULL) {
109             return BAD_VALUE;
110         }
111         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
112         status_t status = remote()->transact(GET_MUTE, data, &reply);
113         if (status == NO_ERROR) {
114             status = (status_t)reply.readInt32();
115             if (status == NO_ERROR) {
116                 int32_t muteread = reply.readInt32();
117                 *mute = muteread != 0;
118             }
119         }
120         return status;
121     }
122 
scan(radio_direction_t direction,bool skipSubChannel)123     virtual status_t scan(radio_direction_t direction, bool skipSubChannel)
124     {
125         Parcel data, reply;
126         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
127         data.writeInt32(direction);
128         data.writeInt32(skipSubChannel ? 1 : 0);
129         status_t status = remote()->transact(SCAN, data, &reply);
130         if (status == NO_ERROR) {
131             status = (status_t)reply.readInt32();
132         }
133         return status;
134     }
135 
step(radio_direction_t direction,bool skipSubChannel)136     virtual status_t step(radio_direction_t direction, bool skipSubChannel)
137     {
138         Parcel data, reply;
139         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
140         data.writeInt32(direction);
141         data.writeInt32(skipSubChannel ? 1 : 0);
142         status_t status = remote()->transact(STEP, data, &reply);
143         if (status == NO_ERROR) {
144             status = (status_t)reply.readInt32();
145         }
146         return status;
147     }
148 
tune(uint32_t channel,uint32_t subChannel)149     virtual status_t tune(uint32_t channel, uint32_t subChannel)
150     {
151         Parcel data, reply;
152         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
153         data.writeUint32(channel);
154         data.writeUint32(subChannel);
155         status_t status = remote()->transact(TUNE, data, &reply);
156         if (status == NO_ERROR) {
157             status = (status_t)reply.readInt32();
158         }
159         return status;
160     }
161 
cancel()162     virtual status_t cancel()
163     {
164         Parcel data, reply;
165         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
166         status_t status = remote()->transact(CANCEL, data, &reply);
167         if (status == NO_ERROR) {
168             status = (status_t)reply.readInt32();
169         }
170         return status;
171     }
172 
getProgramInformation(struct radio_program_info * info)173     virtual status_t getProgramInformation(struct radio_program_info *info)
174     {
175         Parcel data, reply;
176         if (info == nullptr || info->metadata == nullptr) {
177             return BAD_VALUE;
178         }
179         radio_metadata_t *metadata = info->metadata;
180         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
181         status_t status = remote()->transact(GET_PROGRAM_INFORMATION, data, &reply);
182         if (status == NO_ERROR) {
183             status = (status_t)reply.readInt32();
184             if (status == NO_ERROR) {
185                 reply.read(info, sizeof(struct radio_program_info));
186                 // restore local metadata pointer
187                 info->metadata = metadata;
188 
189                 uint32_t metadataSize = reply.readUint32();
190                 if (metadataSize != 0) {
191                     radio_metadata_t *newMetadata = (radio_metadata_t *)malloc(metadataSize);
192                     if (newMetadata == NULL) {
193                         return NO_MEMORY;
194                     }
195                     reply.read(newMetadata, metadataSize);
196                     status = radio_metadata_add_metadata(&info->metadata, newMetadata);
197                     free(newMetadata);
198                 }
199             }
200         }
201         return status;
202     }
203 
hasControl(bool * hasControl)204     virtual status_t hasControl(bool *hasControl)
205     {
206         Parcel data, reply;
207         if (hasControl == NULL) {
208             return BAD_VALUE;
209         }
210         data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
211         status_t status = remote()->transact(HAS_CONTROL, data, &reply);
212         if (status == NO_ERROR) {
213             status = (status_t)reply.readInt32();
214             if (status == NO_ERROR) {
215                 *hasControl = reply.readInt32() != 0;
216             }
217         }
218         return status;
219     }
220 };
221 
222 IMPLEMENT_META_INTERFACE(Radio, "android.hardware.IRadio");
223 
224 // ----------------------------------------------------------------------
225 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)226 status_t BnRadio::onTransact(
227     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
228 {
229     switch(code) {
230         case DETACH: {
231             ALOGV("DETACH");
232             CHECK_INTERFACE(IRadio, data, reply);
233             detach();
234             return NO_ERROR;
235         } break;
236         case SET_CONFIGURATION: {
237             CHECK_INTERFACE(IRadio, data, reply);
238             struct radio_band_config config;
239             data.read(&config, sizeof(struct radio_band_config));
240             status_t status = setConfiguration(&config);
241             reply->writeInt32(status);
242             return NO_ERROR;
243         }
244         case GET_CONFIGURATION: {
245             CHECK_INTERFACE(IRadio, data, reply);
246             struct radio_band_config config;
247             status_t status = getConfiguration(&config);
248             reply->writeInt32(status);
249             if (status == NO_ERROR) {
250                 reply->write(&config, sizeof(struct radio_band_config));
251             }
252             return NO_ERROR;
253         }
254         case SET_MUTE: {
255             CHECK_INTERFACE(IRadio, data, reply);
256             bool mute = data.readInt32() != 0;
257             status_t status = setMute(mute);
258             reply->writeInt32(status);
259             return NO_ERROR;
260         }
261         case GET_MUTE: {
262             CHECK_INTERFACE(IRadio, data, reply);
263             bool mute;
264             status_t status = getMute(&mute);
265             reply->writeInt32(status);
266             if (status == NO_ERROR) {
267                 reply->writeInt32(mute ? 1 : 0);
268             }
269             return NO_ERROR;
270         }
271         case SCAN: {
272             CHECK_INTERFACE(IRadio, data, reply);
273             radio_direction_t direction = (radio_direction_t)data.readInt32();
274             bool skipSubChannel = data.readInt32() == 1;
275             status_t status = scan(direction, skipSubChannel);
276             reply->writeInt32(status);
277             return NO_ERROR;
278         }
279         case STEP: {
280             CHECK_INTERFACE(IRadio, data, reply);
281             radio_direction_t direction = (radio_direction_t)data.readInt32();
282             bool skipSubChannel = data.readInt32() == 1;
283             status_t status = step(direction, skipSubChannel);
284             reply->writeInt32(status);
285             return NO_ERROR;
286         }
287         case TUNE: {
288             CHECK_INTERFACE(IRadio, data, reply);
289             uint32_t channel = data.readUint32();
290             uint32_t subChannel = data.readUint32();
291             status_t status = tune(channel, subChannel);
292             reply->writeInt32(status);
293             return NO_ERROR;
294         }
295         case CANCEL: {
296             CHECK_INTERFACE(IRadio, data, reply);
297             status_t status = cancel();
298             reply->writeInt32(status);
299             return NO_ERROR;
300         }
301         case GET_PROGRAM_INFORMATION: {
302             CHECK_INTERFACE(IRadio, data, reply);
303             struct radio_program_info info;
304             RadioMetadataWrapper metadataWrapper(&info.metadata);
305 
306             status_t status = getProgramInformation(&info);
307             reply->writeInt32(status);
308             if (status == NO_ERROR) {
309                 reply->write(&info, sizeof(struct radio_program_info));
310                 if (radio_metadata_get_count(info.metadata) > 0) {
311                     size_t size = radio_metadata_get_size(info.metadata);
312                     reply->writeUint32((uint32_t)size);
313                     reply->write(info.metadata, size);
314                 } else {
315                     reply->writeUint32(0);
316                 }
317             }
318             return NO_ERROR;
319         }
320         case HAS_CONTROL: {
321             CHECK_INTERFACE(IRadio, data, reply);
322             bool control;
323             status_t status = hasControl(&control);
324             reply->writeInt32(status);
325             if (status == NO_ERROR) {
326                 reply->writeInt32(control ? 1 : 0);
327             }
328             return NO_ERROR;
329         }
330         default:
331             return BBinder::onTransact(code, data, reply, flags);
332     }
333 }
334 
335 // ----------------------------------------------------------------------------
336 
337 }; // namespace android
338