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", config, withAudio, config->region, config->band.type);
91 if (config == NULL) {
92 data.writeInt32(0);
93 } else {
94 data.writeInt32(1);
95 data.write(config, sizeof(struct radio_band_config));
96 }
97 data.writeInt32(withAudio ? 1 : 0);
98 status_t status = remote()->transact(ATTACH, data, &reply);
99 if (status != NO_ERROR) {
100 return status;
101 }
102 status = reply.readInt32();
103 if (reply.readInt32() != 0) {
104 radio = interface_cast<IRadio>(reply.readStrongBinder());
105 }
106 return status;
107 }
108 };
109
110 IMPLEMENT_META_INTERFACE(RadioService, "android.hardware.IRadioService");
111
112 // ----------------------------------------------------------------------
113
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)114 status_t BnRadioService::onTransact(
115 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
116 {
117 switch(code) {
118 case LIST_MODULES: {
119 CHECK_INTERFACE(IRadioService, data, reply);
120 unsigned int numModulesReq = data.readInt32();
121 if (numModulesReq > MAX_ITEMS_PER_LIST) {
122 numModulesReq = MAX_ITEMS_PER_LIST;
123 }
124 unsigned int numModules = numModulesReq;
125 struct radio_properties *properties =
126 (struct radio_properties *)calloc(numModulesReq,
127 sizeof(struct radio_properties));
128 if (properties == NULL) {
129 reply->writeInt32(NO_MEMORY);
130 reply->writeInt32(0);
131 return NO_ERROR;
132 }
133
134 status_t status = listModules(properties, &numModules);
135 reply->writeInt32(status);
136 reply->writeInt32(numModules);
137 ALOGV("LIST_MODULES status %d got numModules %d", status, numModules);
138
139 if (status == NO_ERROR) {
140 if (numModulesReq > numModules) {
141 numModulesReq = numModules;
142 }
143 reply->write(properties,
144 numModulesReq * sizeof(struct radio_properties));
145 }
146 free(properties);
147 return NO_ERROR;
148 } break;
149
150 case ATTACH: {
151 CHECK_INTERFACE(IRadioService, data, reply);
152 radio_handle_t handle = data.readInt32();
153 sp<IRadioClient> client =
154 interface_cast<IRadioClient>(data.readStrongBinder());
155 struct radio_band_config config;
156 struct radio_band_config *configPtr = NULL;
157 if (data.readInt32() != 0) {
158 data.read(&config, sizeof(struct radio_band_config));
159 configPtr = &config;
160 }
161 bool withAudio = data.readInt32() != 0;
162 ALOGV("ATTACH configPtr %p withAudio %d", configPtr, withAudio);
163 sp<IRadio> radio;
164 status_t status = attach(handle, client, configPtr, withAudio, radio);
165 reply->writeInt32(status);
166 if (radio != 0) {
167 reply->writeInt32(1);
168 reply->writeStrongBinder(IInterface::asBinder(radio));
169 } else {
170 reply->writeInt32(0);
171 }
172 return NO_ERROR;
173 } break;
174 default:
175 return BBinder::onTransact(code, data, reply, flags);
176 }
177 }
178
179 // ----------------------------------------------------------------------------
180
181 }; // namespace android
182