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: 48 BpRadioService(const sp<IBinder>& impl) 49 : 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)); 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 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