1d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent/*
2d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent**
3d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent** Copyright 2015, The Android Open Source Project
4d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent**
5d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent** Licensed under the Apache License, Version 2.0 (the "License");
6d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent** you may not use this file except in compliance with the License.
7d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent** You may obtain a copy of the License at
8d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent**
9d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent**     http://www.apache.org/licenses/LICENSE-2.0
10d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent**
11d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent** Unless required by applicable law or agreed to in writing, software
12d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent** distributed under the License is distributed on an "AS IS" BASIS,
13d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent** See the License for the specific language governing permissions and
15d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent** limitations under the License.
16d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent*/
17d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent
18d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent#define LOG_TAG "BpRadioService"
19d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent//
20d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent#define LOG_NDEBUG 0
21d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent
22d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent#include <utils/Log.h>
23d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent#include <utils/Errors.h>
24d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent
25d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent#include <stdint.h>
26d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent#include <sys/types.h>
27d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent#include <binder/IMemory.h>
28d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent#include <binder/Parcel.h>
29d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent#include <binder/IPCThreadState.h>
30d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent#include <binder/IServiceManager.h>
31d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent
32d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent#include <radio/IRadioService.h>
33d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent#include <radio/IRadio.h>
34d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent#include <radio/IRadioClient.h>
35d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent
36d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurentnamespace android {
37d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent
38d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurentenum {
39d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent    LIST_MODULES = IBinder::FIRST_CALL_TRANSACTION,
40d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent    ATTACH,
41d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent};
42d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent
43d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent#define MAX_ITEMS_PER_LIST 1024
44d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent
45d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurentclass BpRadioService: public BpInterface<IRadioService>
46d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent{
47d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurentpublic:
48d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent    BpRadioService(const sp<IBinder>& impl)
49d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        : BpInterface<IRadioService>(impl)
50d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent    {
51d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent    }
52d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent
53d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent    virtual status_t listModules(struct radio_properties *properties,
54d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                                 uint32_t *numModules)
55d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent    {
56d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        if (numModules == NULL || (*numModules != 0 && properties == NULL)) {
57d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            return BAD_VALUE;
58d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        }
59d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        Parcel data, reply;
60d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        data.writeInterfaceToken(IRadioService::getInterfaceDescriptor());
61d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        unsigned int numModulesReq = (properties == NULL) ? 0 : *numModules;
62d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        data.writeInt32(numModulesReq);
63d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        status_t status = remote()->transact(LIST_MODULES, data, &reply);
64d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        if (status == NO_ERROR) {
65d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            status = (status_t)reply.readInt32();
66d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            *numModules = (unsigned int)reply.readInt32();
67d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        }
68d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        ALOGV("listModules() status %d got *numModules %d", status, *numModules);
69d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        if (status == NO_ERROR) {
70d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            if (numModulesReq > *numModules) {
71d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                numModulesReq = *numModules;
72d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            }
73d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            if (numModulesReq > 0) {
74d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                reply.read(properties, numModulesReq * sizeof(struct radio_properties));
75d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            }
76d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        }
77d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        return status;
78d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent    }
79d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent
80d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent    virtual status_t attach(radio_handle_t handle,
81d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                            const sp<IRadioClient>& client,
82d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                            const struct radio_band_config *config,
83d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                            bool withAudio,
84d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                            sp<IRadio>& radio)
85d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent    {
86d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        Parcel data, reply;
87d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        data.writeInterfaceToken(IRadioService::getInterfaceDescriptor());
88d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        data.writeInt32(handle);
89d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        data.writeStrongBinder(IInterface::asBinder(client));
90d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        ALOGV("attach() config %p withAudio %d region %d type %d", config, withAudio, config->region, config->band.type);
91d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        if (config == NULL) {
92d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            data.writeInt32(0);
93d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        } else {
94d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            data.writeInt32(1);
95d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            data.write(config, sizeof(struct radio_band_config));
96d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        }
97d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        data.writeInt32(withAudio ? 1 : 0);
98d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        status_t status = remote()->transact(ATTACH, data, &reply);
99d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        if (status != NO_ERROR) {
100d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            return status;
101d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        }
102d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        status = reply.readInt32();
103d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        if (reply.readInt32() != 0) {
104d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            radio = interface_cast<IRadio>(reply.readStrongBinder());
105d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        }
106d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        return status;
107d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent    }
108d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent};
109d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent
110d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric LaurentIMPLEMENT_META_INTERFACE(RadioService, "android.hardware.IRadioService");
111d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent
112d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent// ----------------------------------------------------------------------
113d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent
114d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurentstatus_t BnRadioService::onTransact(
115d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
116d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent{
117d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent    switch(code) {
118d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        case LIST_MODULES: {
119d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            CHECK_INTERFACE(IRadioService, data, reply);
120d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            unsigned int numModulesReq = data.readInt32();
121d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            if (numModulesReq > MAX_ITEMS_PER_LIST) {
122d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                numModulesReq = MAX_ITEMS_PER_LIST;
123d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            }
124d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            unsigned int numModules = numModulesReq;
125d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            struct radio_properties *properties =
126d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                    (struct radio_properties *)calloc(numModulesReq,
127d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                                                      sizeof(struct radio_properties));
128d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            if (properties == NULL) {
129d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                reply->writeInt32(NO_MEMORY);
130d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                reply->writeInt32(0);
131d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                return NO_ERROR;
132d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            }
133d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent
134d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            status_t status = listModules(properties, &numModules);
135d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            reply->writeInt32(status);
136d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            reply->writeInt32(numModules);
137d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            ALOGV("LIST_MODULES status %d got numModules %d", status, numModules);
138d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent
139d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            if (status == NO_ERROR) {
140d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                if (numModulesReq > numModules) {
141d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                    numModulesReq = numModules;
142d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                }
143d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                reply->write(properties,
144d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                             numModulesReq * sizeof(struct radio_properties));
145d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            }
146d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            free(properties);
147d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            return NO_ERROR;
148d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        } break;
149d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent
150d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        case ATTACH: {
151d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            CHECK_INTERFACE(IRadioService, data, reply);
152d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            radio_handle_t handle = data.readInt32();
153d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            sp<IRadioClient> client =
154d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                    interface_cast<IRadioClient>(data.readStrongBinder());
155d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            struct radio_band_config config;
156d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            struct radio_band_config *configPtr = NULL;
157d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            if (data.readInt32() != 0) {
158d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                data.read(&config, sizeof(struct radio_band_config));
159d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                configPtr = &config;
160d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            }
161d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            bool withAudio = data.readInt32() != 0;
162d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            ALOGV("ATTACH configPtr %p withAudio %d", configPtr, withAudio);
163d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            sp<IRadio> radio;
164d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            status_t status = attach(handle, client, configPtr, withAudio, radio);
165d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            reply->writeInt32(status);
166d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            if (radio != 0) {
167d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                reply->writeInt32(1);
168d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                reply->writeStrongBinder(IInterface::asBinder(radio));
169d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            } else {
170d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent                reply->writeInt32(0);
171d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            }
172d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            return NO_ERROR;
173d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        } break;
174d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent        default:
175d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent            return BBinder::onTransact(code, data, reply, flags);
176d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent    }
177d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent}
178d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent
179d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent// ----------------------------------------------------------------------------
180d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent
181d73697b9b61be2fa227b93b5c4c8e30badd32e71Eric Laurent}; // namespace android
182