blob: be7d21e470432f0e5ecb5279d6954ba2fb563d22 [file] [log] [blame]
Eric Laurentd73697b2015-03-05 15:09:23 -08001/*
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
36namespace android {
37
38enum {
39 LIST_MODULES = IBinder::FIRST_CALL_TRANSACTION,
40 ATTACH,
41};
42
43#define MAX_ITEMS_PER_LIST 1024
44
45class BpRadioService: public BpInterface<IRadioService>
46{
47public:
Chih-Hung Hsieh090ef602016-04-27 10:39:54 -070048 explicit BpRadioService(const sp<IBinder>& impl)
Eric Laurentd73697b2015-03-05 15:09:23 -080049 : 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));
Sanket Agarwalf639ba12015-10-12 13:05:53 -070090 ALOGV("attach() config %p withAudio %d region %d type %d",
Yunlian Jiang007843b2016-10-12 12:05:54 -070091 config == NULL ? 0 : config, withAudio,
92 config == NULL ? 0 : config->region,
93 config == NULL ? 0 : config->band.type);
Eric Laurentd73697b2015-03-05 15:09:23 -080094 if (config == NULL) {
95 data.writeInt32(0);
96 } else {
97 data.writeInt32(1);
98 data.write(config, sizeof(struct radio_band_config));
99 }
100 data.writeInt32(withAudio ? 1 : 0);
101 status_t status = remote()->transact(ATTACH, data, &reply);
102 if (status != NO_ERROR) {
103 return status;
104 }
105 status = reply.readInt32();
106 if (reply.readInt32() != 0) {
107 radio = interface_cast<IRadio>(reply.readStrongBinder());
108 }
109 return status;
110 }
111};
112
113IMPLEMENT_META_INTERFACE(RadioService, "android.hardware.IRadioService");
114
115// ----------------------------------------------------------------------
116
117status_t BnRadioService::onTransact(
118 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
119{
120 switch(code) {
121 case LIST_MODULES: {
122 CHECK_INTERFACE(IRadioService, data, reply);
123 unsigned int numModulesReq = data.readInt32();
124 if (numModulesReq > MAX_ITEMS_PER_LIST) {
125 numModulesReq = MAX_ITEMS_PER_LIST;
126 }
127 unsigned int numModules = numModulesReq;
128 struct radio_properties *properties =
129 (struct radio_properties *)calloc(numModulesReq,
130 sizeof(struct radio_properties));
131 if (properties == NULL) {
132 reply->writeInt32(NO_MEMORY);
133 reply->writeInt32(0);
134 return NO_ERROR;
135 }
136
137 status_t status = listModules(properties, &numModules);
138 reply->writeInt32(status);
139 reply->writeInt32(numModules);
140 ALOGV("LIST_MODULES status %d got numModules %d", status, numModules);
141
142 if (status == NO_ERROR) {
143 if (numModulesReq > numModules) {
144 numModulesReq = numModules;
145 }
146 reply->write(properties,
147 numModulesReq * sizeof(struct radio_properties));
148 }
149 free(properties);
150 return NO_ERROR;
151 } break;
152
153 case ATTACH: {
154 CHECK_INTERFACE(IRadioService, data, reply);
155 radio_handle_t handle = data.readInt32();
156 sp<IRadioClient> client =
157 interface_cast<IRadioClient>(data.readStrongBinder());
158 struct radio_band_config config;
159 struct radio_band_config *configPtr = NULL;
160 if (data.readInt32() != 0) {
161 data.read(&config, sizeof(struct radio_band_config));
162 configPtr = &config;
163 }
164 bool withAudio = data.readInt32() != 0;
165 ALOGV("ATTACH configPtr %p withAudio %d", configPtr, withAudio);
166 sp<IRadio> radio;
167 status_t status = attach(handle, client, configPtr, withAudio, radio);
168 reply->writeInt32(status);
169 if (radio != 0) {
170 reply->writeInt32(1);
171 reply->writeStrongBinder(IInterface::asBinder(radio));
172 } else {
173 reply->writeInt32(0);
174 }
175 return NO_ERROR;
176 } break;
177 default:
178 return BBinder::onTransact(code, data, reply, flags);
179 }
180}
181
182// ----------------------------------------------------------------------------
183
184}; // namespace android