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