blob: a73ed8f6d81a73c9b1e625c43afa604b615d8041 [file] [log] [blame]
Eric Laurent4e090692015-03-05 15:12:40 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "RadioService"
18//#define LOG_NDEBUG 0
19
20#include <stdio.h>
21#include <string.h>
22#include <sys/types.h>
23#include <pthread.h>
24
Eric Laurent53810822015-03-12 09:12:01 -070025#include <system/audio.h>
26#include <system/audio_policy.h>
Eric Laurent4e090692015-03-05 15:12:40 -080027#include <system/radio.h>
28#include <system/radio_metadata.h>
29#include <cutils/atomic.h>
30#include <cutils/properties.h>
31#include <hardware/hardware.h>
32#include <utils/Errors.h>
33#include <utils/Log.h>
34#include <binder/IServiceManager.h>
35#include <binder/MemoryBase.h>
36#include <binder/MemoryHeapBase.h>
37#include <hardware/radio.h>
Eric Laurent53810822015-03-12 09:12:01 -070038#include <media/AudioSystem.h>
Eric Laurent4e090692015-03-05 15:12:40 -080039#include "RadioService.h"
40#include "RadioRegions.h"
41
42namespace android {
43
Eric Laurent53810822015-03-12 09:12:01 -070044static const char kRadioTunerAudioDeviceName[] = "Radio tuner source";
Eric Laurent4e090692015-03-05 15:12:40 -080045
46RadioService::RadioService()
47 : BnRadioService(), mNextUniqueId(1)
48{
49 ALOGI("%s", __FUNCTION__);
50}
51
52void RadioService::onFirstRef()
53{
Eric Laurent4e090692015-03-05 15:12:40 -080054 ALOGI("%s", __FUNCTION__);
55
Eric Laurent01d267e2016-10-21 08:16:10 -070056 sp<RadioInterface> dev = RadioInterface::connectModule(RADIO_CLASS_AM_FM);
Eric Laurent4e090692015-03-05 15:12:40 -080057
Eric Laurent01d267e2016-10-21 08:16:10 -070058 if (dev == 0) {
59 return;
60 }
Eric Laurent4e090692015-03-05 15:12:40 -080061 struct radio_hal_properties halProperties;
Eric Laurent01d267e2016-10-21 08:16:10 -070062 int rc = dev->getProperties(&halProperties);
Eric Laurent4e090692015-03-05 15:12:40 -080063 if (rc != 0) {
64 ALOGE("could not read implementation properties");
65 return;
66 }
67
68 radio_properties_t properties;
69 properties.handle =
70 (radio_handle_t)android_atomic_inc(&mNextUniqueId);
71
72 ALOGI("loaded default module %s, handle %d", properties.product, properties.handle);
73
74 convertProperties(&properties, &halProperties);
Eric Laurent53810822015-03-12 09:12:01 -070075 sp<Module> module = new Module(dev, properties);
Eric Laurent4e090692015-03-05 15:12:40 -080076 mModules.add(properties.handle, module);
77}
78
79RadioService::~RadioService()
80{
Eric Laurent4e090692015-03-05 15:12:40 -080081}
82
83status_t RadioService::listModules(struct radio_properties *properties,
84 uint32_t *numModules)
85{
86 ALOGV("listModules");
87
88 AutoMutex lock(mServiceLock);
89 if (numModules == NULL || (*numModules != 0 && properties == NULL)) {
90 return BAD_VALUE;
91 }
Eric Laurent01d267e2016-10-21 08:16:10 -070092 uint32_t maxModules = *numModules;
Eric Laurent4e090692015-03-05 15:12:40 -080093 *numModules = mModules.size();
94 for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
95 properties[i] = mModules.valueAt(i)->properties();
96 }
97 return NO_ERROR;
98}
99
100status_t RadioService::attach(radio_handle_t handle,
101 const sp<IRadioClient>& client,
102 const struct radio_band_config *config,
103 bool withAudio,
104 sp<IRadio>& radio)
105{
106 ALOGV("%s %d config %p withAudio %d", __FUNCTION__, handle, config, withAudio);
107
108 AutoMutex lock(mServiceLock);
109 radio.clear();
110 if (client == 0) {
111 return BAD_VALUE;
112 }
113 ssize_t index = mModules.indexOfKey(handle);
114 if (index < 0) {
115 return BAD_VALUE;
116 }
117 sp<Module> module = mModules.valueAt(index);
118
119 if (config == NULL) {
120 config = module->getDefaultConfig();
121 if (config == NULL) {
122 return INVALID_OPERATION;
123 }
124 }
125 ALOGV("%s region %d type %d", __FUNCTION__, config->region, config->band.type);
126
127 radio = module->addClient(client, config, withAudio);
128
129 if (radio == 0) {
Eric Laurentf2f79cf2015-04-23 17:10:50 -0700130 return NO_INIT;
Eric Laurent4e090692015-03-05 15:12:40 -0800131 }
132 return NO_ERROR;
133}
134
135
136static const int kDumpLockRetries = 50;
137static const int kDumpLockSleep = 60000;
138
139static bool tryLock(Mutex& mutex)
140{
141 bool locked = false;
142 for (int i = 0; i < kDumpLockRetries; ++i) {
143 if (mutex.tryLock() == NO_ERROR) {
144 locked = true;
145 break;
146 }
147 usleep(kDumpLockSleep);
148 }
149 return locked;
150}
151
152status_t RadioService::dump(int fd, const Vector<String16>& args __unused) {
153 String8 result;
154 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
155 result.appendFormat("Permission Denial: can't dump RadioService");
156 write(fd, result.string(), result.size());
157 } else {
158 bool locked = tryLock(mServiceLock);
159 // failed to lock - RadioService is probably deadlocked
160 if (!locked) {
161 result.append("RadioService may be deadlocked\n");
162 write(fd, result.string(), result.size());
163 }
164
165 if (locked) mServiceLock.unlock();
166 }
167 return NO_ERROR;
168}
169
170status_t RadioService::onTransact(
171 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
172 return BnRadioService::onTransact(code, data, reply, flags);
173}
174
175
Eric Laurent4e090692015-03-05 15:12:40 -0800176/* static */
177void RadioService::convertProperties(radio_properties_t *properties,
178 const radio_hal_properties_t *halProperties)
179{
180 memset(properties, 0, sizeof(struct radio_properties));
181 properties->class_id = halProperties->class_id;
182 strlcpy(properties->implementor, halProperties->implementor,
183 RADIO_STRING_LEN_MAX);
184 strlcpy(properties->product, halProperties->product,
185 RADIO_STRING_LEN_MAX);
186 strlcpy(properties->version, halProperties->version,
187 RADIO_STRING_LEN_MAX);
188 strlcpy(properties->serial, halProperties->serial,
189 RADIO_STRING_LEN_MAX);
190 properties->num_tuners = halProperties->num_tuners;
191 properties->num_audio_sources = halProperties->num_audio_sources;
192 properties->supports_capture = halProperties->supports_capture;
193
194 for (size_t i = 0; i < ARRAY_SIZE(sKnownRegionConfigs); i++) {
195 const radio_hal_band_config_t *band = &sKnownRegionConfigs[i].band;
196 size_t j;
197 for (j = 0; j < halProperties->num_bands; j++) {
198 const radio_hal_band_config_t *halBand = &halProperties->bands[j];
199 size_t k;
200 if (band->type != halBand->type) continue;
201 if (band->lower_limit < halBand->lower_limit) continue;
202 if (band->upper_limit > halBand->upper_limit) continue;
203 for (k = 0; k < halBand->num_spacings; k++) {
204 if (band->spacings[0] == halBand->spacings[k]) break;
205 }
206 if (k == halBand->num_spacings) continue;
207 if (band->type == RADIO_BAND_AM) break;
208 if ((band->fm.deemphasis & halBand->fm.deemphasis) == 0) continue;
209 if (halBand->fm.rds == 0) break;
210 if ((band->fm.rds & halBand->fm.rds) != 0) break;
211 }
212 if (j == halProperties->num_bands) continue;
213
214 ALOGI("convertProperties() Adding band type %d region %d",
215 sKnownRegionConfigs[i].band.type , sKnownRegionConfigs[i].region);
216
217 memcpy(&properties->bands[properties->num_bands++],
218 &sKnownRegionConfigs[i],
219 sizeof(radio_band_config_t));
220 }
221}
222
223#undef LOG_TAG
224#define LOG_TAG "RadioService::CallbackThread"
225
226RadioService::CallbackThread::CallbackThread(const wp<ModuleClient>& moduleClient)
227 : mModuleClient(moduleClient), mMemoryDealer(new MemoryDealer(1024 * 1024, "RadioService"))
228{
229}
230
231RadioService::CallbackThread::~CallbackThread()
232{
233 mEventQueue.clear();
234}
235
236void RadioService::CallbackThread::onFirstRef()
237{
238 run("RadioService cbk", ANDROID_PRIORITY_URGENT_AUDIO);
239}
240
241bool RadioService::CallbackThread::threadLoop()
242{
243 while (!exitPending()) {
244 sp<IMemory> eventMemory;
245 sp<ModuleClient> moduleClient;
246 {
247 Mutex::Autolock _l(mCallbackLock);
248 while (mEventQueue.isEmpty() && !exitPending()) {
249 ALOGV("CallbackThread::threadLoop() sleep");
250 mCallbackCond.wait(mCallbackLock);
251 ALOGV("CallbackThread::threadLoop() wake up");
252 }
253 if (exitPending()) {
254 break;
255 }
256 eventMemory = mEventQueue[0];
257 mEventQueue.removeAt(0);
258 moduleClient = mModuleClient.promote();
259 }
260 if (moduleClient != 0) {
261 moduleClient->onCallbackEvent(eventMemory);
262 eventMemory.clear();
263 }
264 }
265 return false;
266}
267
268void RadioService::CallbackThread::exit()
269{
270 Mutex::Autolock _l(mCallbackLock);
271 requestExit();
272 mCallbackCond.broadcast();
273}
274
275sp<IMemory> RadioService::CallbackThread::prepareEvent(radio_hal_event_t *halEvent)
276{
277 sp<IMemory> eventMemory;
278
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700279 // The event layout in shared memory is:
280 // sizeof(struct radio_event) bytes : the event itself
281 // 4 bytes : metadata size or 0
282 // N bytes : metadata if present
283 uint32_t metadataOffset = sizeof(struct radio_event) + sizeof(uint32_t);
284 uint32_t metadataSize = 0;
285
Eric Laurent4e090692015-03-05 15:12:40 -0800286 switch (halEvent->type) {
287 case RADIO_EVENT_TUNED:
288 case RADIO_EVENT_AF_SWITCH:
289 if (radio_metadata_check(halEvent->info.metadata) == 0) {
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700290 metadataSize = (uint32_t)radio_metadata_get_size(halEvent->info.metadata);
Eric Laurent4e090692015-03-05 15:12:40 -0800291 }
292 break;
293 case RADIO_EVENT_METADATA:
294 if (radio_metadata_check(halEvent->metadata) != 0) {
295 return eventMemory;
296 }
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700297 metadataSize = (uint32_t)radio_metadata_get_size(halEvent->metadata);
Eric Laurent4e090692015-03-05 15:12:40 -0800298 break;
299 default:
300 break;
301 }
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700302
303 eventMemory = mMemoryDealer->allocate(metadataOffset + metadataSize);
Eric Laurent4e090692015-03-05 15:12:40 -0800304 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
305 eventMemory.clear();
306 return eventMemory;
307 }
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700308
Eric Laurent4e090692015-03-05 15:12:40 -0800309 struct radio_event *event = (struct radio_event *)eventMemory->pointer();
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700310
311 *(uint32_t *)((uint8_t *)event + metadataOffset - sizeof(uint32_t)) = metadataSize;
312
Eric Laurent4e090692015-03-05 15:12:40 -0800313 event->type = halEvent->type;
314 event->status = halEvent->status;
315
316 switch (event->type) {
317 case RADIO_EVENT_CONFIG:
318 event->config.band = halEvent->config;
319 break;
320 case RADIO_EVENT_TUNED:
321 case RADIO_EVENT_AF_SWITCH:
322 event->info = halEvent->info;
323 if (metadataSize != 0) {
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700324 memcpy((uint8_t *)event + metadataOffset, halEvent->info.metadata, metadataSize);
Eric Laurent4e090692015-03-05 15:12:40 -0800325 }
326 break;
327 case RADIO_EVENT_TA:
Sanket Agarwalf639ba12015-10-12 13:05:53 -0700328 case RADIO_EVENT_EA:
Eric Laurent4e090692015-03-05 15:12:40 -0800329 case RADIO_EVENT_ANTENNA:
330 case RADIO_EVENT_CONTROL:
331 event->on = halEvent->on;
332 break;
333 case RADIO_EVENT_METADATA:
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700334 if (metadataSize != 0) {
335 memcpy((uint8_t *)event + metadataOffset, halEvent->metadata, metadataSize);
336 }
Eric Laurent4e090692015-03-05 15:12:40 -0800337 break;
338 case RADIO_EVENT_HW_FAILURE:
339 default:
340 break;
341 }
342
343 return eventMemory;
344}
345
346void RadioService::CallbackThread::sendEvent(radio_hal_event_t *event)
347 {
348 sp<IMemory> eventMemory = prepareEvent(event);
349 if (eventMemory == 0) {
350 return;
351 }
352
353 AutoMutex lock(mCallbackLock);
354 mEventQueue.add(eventMemory);
355 mCallbackCond.signal();
356 ALOGV("%s DONE", __FUNCTION__);
357}
358
359
360#undef LOG_TAG
361#define LOG_TAG "RadioService::Module"
362
Eric Laurent01d267e2016-10-21 08:16:10 -0700363RadioService::Module::Module(sp<RadioInterface> hwDevice, radio_properties properties)
Eric Laurent53810822015-03-12 09:12:01 -0700364 : mHwDevice(hwDevice), mProperties(properties), mMute(true)
Eric Laurent4e090692015-03-05 15:12:40 -0800365{
366}
367
368RadioService::Module::~Module() {
Eric Laurent01d267e2016-10-21 08:16:10 -0700369 mHwDevice.clear();
Eric Laurent4e090692015-03-05 15:12:40 -0800370 mModuleClients.clear();
371}
372
373status_t RadioService::Module::dump(int fd __unused, const Vector<String16>& args __unused) {
374 String8 result;
375 return NO_ERROR;
376}
377
378sp<RadioService::ModuleClient> RadioService::Module::addClient(const sp<IRadioClient>& client,
379 const struct radio_band_config *config,
380 bool audio)
381{
382 ALOGV("addClient() %p config %p product %s", this, config, mProperties.product);
Eric Laurent01d267e2016-10-21 08:16:10 -0700383
Eric Laurent4e090692015-03-05 15:12:40 -0800384 AutoMutex lock(mLock);
385 sp<ModuleClient> moduleClient;
386 int ret;
387
Eric Laurent01d267e2016-10-21 08:16:10 -0700388 if (mHwDevice == 0) {
389 return moduleClient;
390 }
391
Eric Laurent4e090692015-03-05 15:12:40 -0800392 for (size_t i = 0; i < mModuleClients.size(); i++) {
393 if (mModuleClients[i]->client() == client) {
394 // client already connected: reject
395 return moduleClient;
396 }
397 }
398 moduleClient = new ModuleClient(this, client, config, audio);
399
400 struct radio_hal_band_config halConfig;
401 halConfig = config->band;
402
Eric Laurent53810822015-03-12 09:12:01 -0700403 // Tuner preemption logic:
404 // There is a limited amount of tuners and a limited amount of radio audio sources per module.
405 // The minimum is one tuner and one audio source.
406 // The numbers of tuners and sources are indicated in the module properties.
407 // NOTE: current framework implementation only supports one radio audio source.
408 // It is possible to open more than one tuner at a time but only one tuner can be connected
409 // to the radio audio source (AUDIO_DEVICE_IN_FM_TUNER).
410 // The base rule is that a newly connected tuner always wins, i.e. always gets a tuner
411 // and can use the audio source if requested.
412 // If another client is preempted, it is notified by a callback with RADIO_EVENT_CONTROL
413 // indicating loss of control.
414 // - If the newly connected client requests the audio source (audio == true):
415 // - if an audio source is available
416 // no problem
417 // - if not:
418 // the oldest client in the list using audio is preempted.
419 // - If the newly connected client does not request the audio source (audio == false):
420 // - if a tuner is available
421 // no problem
422 // - if not:
423 // The oldest client not using audio is preempted first and if none is found the
424 // the oldest client using audio is preempted.
425 // Each time a tuner using the audio source is opened or closed, the audio policy manager is
426 // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
427
Eric Laurent4e090692015-03-05 15:12:40 -0800428 sp<ModuleClient> oldestTuner;
429 sp<ModuleClient> oldestAudio;
430 size_t allocatedTuners = 0;
431 size_t allocatedAudio = 0;
432 for (size_t i = 0; i < mModuleClients.size(); i++) {
433 if (mModuleClients[i]->getTuner() != NULL) {
434 if (mModuleClients[i]->audio()) {
435 if (oldestAudio == 0) {
436 oldestAudio = mModuleClients[i];
437 }
438 allocatedAudio++;
439 } else {
440 if (oldestTuner == 0) {
441 oldestTuner = mModuleClients[i];
442 }
443 allocatedTuners++;
444 }
445 }
446 }
447
Eric Laurent01d267e2016-10-21 08:16:10 -0700448 sp<TunerInterface> halTuner;
Eric Laurent53810822015-03-12 09:12:01 -0700449 sp<ModuleClient> preemtedClient;
Eric Laurent4e090692015-03-05 15:12:40 -0800450 if (audio) {
451 if (allocatedAudio >= mProperties.num_audio_sources) {
452 ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
Eric Laurent53810822015-03-12 09:12:01 -0700453 preemtedClient = oldestAudio;
Eric Laurent4e090692015-03-05 15:12:40 -0800454 }
455 } else {
456 if (allocatedAudio + allocatedTuners >= mProperties.num_tuners) {
457 if (allocatedTuners != 0) {
458 ALOG_ASSERT(oldestTuner != 0, "addClient() allocatedTuners/oldestTuner mismatch");
Eric Laurent53810822015-03-12 09:12:01 -0700459 preemtedClient = oldestTuner;
Eric Laurent4e090692015-03-05 15:12:40 -0800460 } else {
461 ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
Eric Laurent53810822015-03-12 09:12:01 -0700462 preemtedClient = oldestAudio;
Eric Laurent4e090692015-03-05 15:12:40 -0800463 }
464 }
465 }
Eric Laurent53810822015-03-12 09:12:01 -0700466 if (preemtedClient != 0) {
467 halTuner = preemtedClient->getTuner();
Eric Laurent01d267e2016-10-21 08:16:10 -0700468 sp<TunerInterface> clear;
469 preemtedClient->setTuner(clear);
470 mHwDevice->closeTuner(halTuner);
Eric Laurent53810822015-03-12 09:12:01 -0700471 if (preemtedClient->audio()) {
472 notifyDeviceConnection(false, "");
473 }
474 }
Eric Laurent4e090692015-03-05 15:12:40 -0800475
Eric Laurent01d267e2016-10-21 08:16:10 -0700476 ret = mHwDevice->openTuner(&halConfig, audio,
477 moduleClient,
478 halTuner);
Eric Laurent4e090692015-03-05 15:12:40 -0800479 if (ret == 0) {
Eric Laurent01d267e2016-10-21 08:16:10 -0700480 ALOGV("addClient() setTuner %p", halTuner.get());
Eric Laurent4e090692015-03-05 15:12:40 -0800481 moduleClient->setTuner(halTuner);
482 mModuleClients.add(moduleClient);
Eric Laurent53810822015-03-12 09:12:01 -0700483 if (audio) {
484 notifyDeviceConnection(true, "");
485 }
Eric Laurentf2f79cf2015-04-23 17:10:50 -0700486 ALOGV("addClient() DONE moduleClient %p", moduleClient.get());
Eric Laurent4e090692015-03-05 15:12:40 -0800487 } else {
Eric Laurentf2f79cf2015-04-23 17:10:50 -0700488 ALOGW("%s open_tuner failed with error %d", __FUNCTION__, ret);
Eric Laurent4e090692015-03-05 15:12:40 -0800489 moduleClient.clear();
490 }
491
Eric Laurent4e090692015-03-05 15:12:40 -0800492 return moduleClient;
493}
494
495void RadioService::Module::removeClient(const sp<ModuleClient>& moduleClient) {
496 ALOGV("removeClient()");
497 AutoMutex lock(mLock);
498 int ret;
499 ssize_t index = -1;
500
501 for (size_t i = 0; i < mModuleClients.size(); i++) {
502 if (mModuleClients[i] == moduleClient) {
503 index = i;
504 break;
505 }
506 }
507 if (index == -1) {
508 return;
509 }
510
511 mModuleClients.removeAt(index);
Eric Laurent01d267e2016-10-21 08:16:10 -0700512 sp<TunerInterface> halTuner = moduleClient->getTuner();
Eric Laurent4e090692015-03-05 15:12:40 -0800513 if (halTuner == NULL) {
514 return;
515 }
516
Eric Laurent01d267e2016-10-21 08:16:10 -0700517 if (mHwDevice != 0) {
518 mHwDevice->closeTuner(halTuner);
519 }
520
Eric Laurent53810822015-03-12 09:12:01 -0700521 if (moduleClient->audio()) {
522 notifyDeviceConnection(false, "");
523 }
Eric Laurent4e090692015-03-05 15:12:40 -0800524
Eric Laurent4e090692015-03-05 15:12:40 -0800525 mMute = true;
526
527 if (mModuleClients.isEmpty()) {
528 return;
529 }
530
Eric Laurent01d267e2016-10-21 08:16:10 -0700531 if (mHwDevice == 0) {
532 return;
533 }
534
Eric Laurent53810822015-03-12 09:12:01 -0700535 // Tuner reallocation logic:
536 // When a client is removed and was controlling a tuner, this tuner will be allocated to a
537 // previously preempted client. This client will be notified by a callback with
538 // RADIO_EVENT_CONTROL indicating gain of control.
539 // - If a preempted client is waiting for an audio source and one becomes available:
540 // Allocate the tuner to the most recently added client waiting for an audio source
541 // - If not:
542 // Allocate the tuner to the most recently added client.
543 // Each time a tuner using the audio source is opened or closed, the audio policy manager is
544 // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
545
Eric Laurent4e090692015-03-05 15:12:40 -0800546 sp<ModuleClient> youngestClient;
547 sp<ModuleClient> youngestClientAudio;
548 size_t allocatedTuners = 0;
549 size_t allocatedAudio = 0;
Eric Laurent53810822015-03-12 09:12:01 -0700550 for (ssize_t i = mModuleClients.size() - 1; i >= 0; i--) {
Eric Laurent4e090692015-03-05 15:12:40 -0800551 if (mModuleClients[i]->getTuner() == NULL) {
552 if (mModuleClients[i]->audio()) {
553 if (youngestClientAudio == 0) {
554 youngestClientAudio = mModuleClients[i];
555 }
556 } else {
557 if (youngestClient == 0) {
558 youngestClient = mModuleClients[i];
559 }
560 }
561 } else {
562 if (mModuleClients[i]->audio()) {
563 allocatedAudio++;
564 } else {
565 allocatedTuners++;
566 }
567 }
568 }
569
570 ALOG_ASSERT(allocatedTuners + allocatedAudio < mProperties.num_tuners,
571 "removeClient() removed client but no tuner available");
572
573 ALOG_ASSERT(!moduleClient->audio() || allocatedAudio < mProperties.num_audio_sources,
574 "removeClient() removed audio client but no tuner with audio available");
575
576 if (allocatedAudio < mProperties.num_audio_sources && youngestClientAudio != 0) {
577 youngestClient = youngestClientAudio;
578 }
579
580 ALOG_ASSERT(youngestClient != 0, "removeClient() removed client no candidate found for tuner");
581
582 struct radio_hal_band_config halConfig = youngestClient->halConfig();
Eric Laurent01d267e2016-10-21 08:16:10 -0700583 ret = mHwDevice->openTuner(&halConfig, youngestClient->audio(),
584 moduleClient,
585 halTuner);
Eric Laurent4e090692015-03-05 15:12:40 -0800586
Eric Laurent4e090692015-03-05 15:12:40 -0800587 if (ret == 0) {
588 youngestClient->setTuner(halTuner);
Eric Laurent53810822015-03-12 09:12:01 -0700589 if (youngestClient->audio()) {
590 notifyDeviceConnection(true, "");
591 }
Eric Laurent4e090692015-03-05 15:12:40 -0800592 }
593}
594
595status_t RadioService::Module::setMute(bool mute)
596{
597 Mutex::Autolock _l(mLock);
598 if (mute != mMute) {
599 mMute = mute;
600 //TODO notifify audio policy manager of media activity on radio audio device
601 }
602 return NO_ERROR;
603}
604
605status_t RadioService::Module::getMute(bool *mute)
606{
607 Mutex::Autolock _l(mLock);
608 *mute = mMute;
609 return NO_ERROR;
610}
611
612
613const struct radio_band_config *RadioService::Module::getDefaultConfig() const
614{
615 if (mProperties.num_bands == 0) {
616 return NULL;
617 }
618 return &mProperties.bands[0];
619}
620
Eric Laurent53810822015-03-12 09:12:01 -0700621void RadioService::Module::notifyDeviceConnection(bool connected,
622 const char *address) {
623 int64_t token = IPCThreadState::self()->clearCallingIdentity();
624 AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_FM_TUNER,
625 connected ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE :
626 AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
627 address, kRadioTunerAudioDeviceName);
628 IPCThreadState::self()->restoreCallingIdentity(token);
629}
630
Eric Laurent4e090692015-03-05 15:12:40 -0800631#undef LOG_TAG
632#define LOG_TAG "RadioService::ModuleClient"
633
634RadioService::ModuleClient::ModuleClient(const sp<Module>& module,
635 const sp<IRadioClient>& client,
636 const struct radio_band_config *config,
637 bool audio)
Eric Laurent01d267e2016-10-21 08:16:10 -0700638 : mModule(module), mClient(client), mConfig(*config), mAudio(audio), mTuner(0)
Eric Laurent4e090692015-03-05 15:12:40 -0800639{
640}
641
642void RadioService::ModuleClient::onFirstRef()
643{
644 mCallbackThread = new CallbackThread(this);
645 IInterface::asBinder(mClient)->linkToDeath(this);
646}
647
648RadioService::ModuleClient::~ModuleClient() {
649 if (mClient != 0) {
650 IInterface::asBinder(mClient)->unlinkToDeath(this);
651 mClient.clear();
652 }
653 if (mCallbackThread != 0) {
654 mCallbackThread->exit();
655 }
656}
657
Eric Laurent01d267e2016-10-21 08:16:10 -0700658void RadioService::ModuleClient::onEvent(radio_hal_event_t *halEvent)
659{
660 mCallbackThread->sendEvent(halEvent);
661}
662
Eric Laurent4e090692015-03-05 15:12:40 -0800663status_t RadioService::ModuleClient::dump(int fd __unused,
664 const Vector<String16>& args __unused) {
665 String8 result;
666 return NO_ERROR;
667}
668
669void RadioService::ModuleClient::detach() {
670 ALOGV("%s", __FUNCTION__);
671 sp<ModuleClient> strongMe = this;
672 {
673 AutoMutex lock(mLock);
674 if (mClient != 0) {
675 IInterface::asBinder(mClient)->unlinkToDeath(this);
676 mClient.clear();
677 }
678 }
679 sp<Module> module = mModule.promote();
680 if (module == 0) {
681 return;
682 }
683 module->removeClient(this);
684}
685
686radio_hal_band_config_t RadioService::ModuleClient::halConfig() const
687{
688 AutoMutex lock(mLock);
689 ALOGV("%s locked", __FUNCTION__);
690 return mConfig.band;
691}
692
Eric Laurent01d267e2016-10-21 08:16:10 -0700693sp<TunerInterface>& RadioService::ModuleClient::getTuner()
Eric Laurent4e090692015-03-05 15:12:40 -0800694{
695 AutoMutex lock(mLock);
696 ALOGV("%s locked", __FUNCTION__);
697 return mTuner;
698}
699
Eric Laurent01d267e2016-10-21 08:16:10 -0700700void RadioService::ModuleClient::setTuner(sp<TunerInterface>& tuner)
Eric Laurent4e090692015-03-05 15:12:40 -0800701{
702 ALOGV("%s %p", __FUNCTION__, this);
703
704 AutoMutex lock(mLock);
705 mTuner = tuner;
706 ALOGV("%s locked", __FUNCTION__);
707
708 radio_hal_event_t event;
709 event.type = RADIO_EVENT_CONTROL;
710 event.status = 0;
Eric Laurent01d267e2016-10-21 08:16:10 -0700711 event.on = mTuner != 0;
Eric Laurent4e090692015-03-05 15:12:40 -0800712 mCallbackThread->sendEvent(&event);
713 ALOGV("%s DONE", __FUNCTION__);
714
715}
716
717status_t RadioService::ModuleClient::setConfiguration(const struct radio_band_config *config)
718{
719 AutoMutex lock(mLock);
720 status_t status = NO_ERROR;
721 ALOGV("%s locked", __FUNCTION__);
722
Eric Laurent01d267e2016-10-21 08:16:10 -0700723 if (mTuner != 0) {
Eric Laurent4e090692015-03-05 15:12:40 -0800724 struct radio_hal_band_config halConfig;
725 halConfig = config->band;
Eric Laurent01d267e2016-10-21 08:16:10 -0700726 status = (status_t)mTuner->setConfiguration(&halConfig);
Eric Laurent4e090692015-03-05 15:12:40 -0800727 if (status == NO_ERROR) {
728 mConfig = *config;
729 }
730 } else {
731 mConfig = *config;
Aurimas Liutikas13958742016-02-18 10:02:35 -0800732 status = INVALID_OPERATION;
Eric Laurent4e090692015-03-05 15:12:40 -0800733 }
734
735 return status;
736}
737
738status_t RadioService::ModuleClient::getConfiguration(struct radio_band_config *config)
739{
740 AutoMutex lock(mLock);
741 status_t status = NO_ERROR;
742 ALOGV("%s locked", __FUNCTION__);
743
Eric Laurent01d267e2016-10-21 08:16:10 -0700744 if (mTuner != 0) {
Eric Laurent4e090692015-03-05 15:12:40 -0800745 struct radio_hal_band_config halConfig;
Eric Laurent01d267e2016-10-21 08:16:10 -0700746 status = (status_t)mTuner->getConfiguration(&halConfig);
Eric Laurent4e090692015-03-05 15:12:40 -0800747 if (status == NO_ERROR) {
748 mConfig.band = halConfig;
749 }
750 }
751 *config = mConfig;
752
753 return status;
754}
755
756status_t RadioService::ModuleClient::setMute(bool mute)
757{
758 sp<Module> module;
759 {
760 Mutex::Autolock _l(mLock);
761 ALOGV("%s locked", __FUNCTION__);
Eric Laurent01d267e2016-10-21 08:16:10 -0700762 if (mTuner == 0 || !mAudio) {
Eric Laurent4e090692015-03-05 15:12:40 -0800763 return INVALID_OPERATION;
764 }
765 module = mModule.promote();
766 if (module == 0) {
767 return NO_INIT;
768 }
769 }
770 module->setMute(mute);
771 return NO_ERROR;
772}
773
774status_t RadioService::ModuleClient::getMute(bool *mute)
775{
776 sp<Module> module;
777 {
778 Mutex::Autolock _l(mLock);
779 ALOGV("%s locked", __FUNCTION__);
780 module = mModule.promote();
781 if (module == 0) {
782 return NO_INIT;
783 }
784 }
785 return module->getMute(mute);
786}
787
788status_t RadioService::ModuleClient::scan(radio_direction_t direction, bool skipSubChannel)
789{
790 AutoMutex lock(mLock);
791 ALOGV("%s locked", __FUNCTION__);
792 status_t status;
Eric Laurent01d267e2016-10-21 08:16:10 -0700793 if (mTuner != 0) {
794 status = (status_t)mTuner->scan(direction, skipSubChannel);
Eric Laurent4e090692015-03-05 15:12:40 -0800795 } else {
796 status = INVALID_OPERATION;
797 }
798 return status;
799}
800
801status_t RadioService::ModuleClient::step(radio_direction_t direction, bool skipSubChannel)
802{
803 AutoMutex lock(mLock);
804 ALOGV("%s locked", __FUNCTION__);
805 status_t status;
Eric Laurent01d267e2016-10-21 08:16:10 -0700806 if (mTuner != 0) {
807 status = (status_t)mTuner->step(direction, skipSubChannel);
Eric Laurent4e090692015-03-05 15:12:40 -0800808 } else {
809 status = INVALID_OPERATION;
810 }
811 return status;
812}
813
Eric Laurent01d267e2016-10-21 08:16:10 -0700814status_t RadioService::ModuleClient::tune(uint32_t channel, uint32_t subChannel)
Eric Laurent4e090692015-03-05 15:12:40 -0800815{
816 AutoMutex lock(mLock);
817 ALOGV("%s locked", __FUNCTION__);
818 status_t status;
Eric Laurent01d267e2016-10-21 08:16:10 -0700819 if (mTuner != 0) {
820 status = (status_t)mTuner->tune(channel, subChannel);
Eric Laurent4e090692015-03-05 15:12:40 -0800821 } else {
822 status = INVALID_OPERATION;
823 }
824 return status;
825}
826
827status_t RadioService::ModuleClient::cancel()
828{
829 AutoMutex lock(mLock);
830 ALOGV("%s locked", __FUNCTION__);
831 status_t status;
Eric Laurent01d267e2016-10-21 08:16:10 -0700832 if (mTuner != 0) {
833 status = (status_t)mTuner->cancel();
Eric Laurent4e090692015-03-05 15:12:40 -0800834 } else {
835 status = INVALID_OPERATION;
836 }
837 return status;
838}
839
840status_t RadioService::ModuleClient::getProgramInformation(struct radio_program_info *info)
841{
842 AutoMutex lock(mLock);
843 ALOGV("%s locked", __FUNCTION__);
844 status_t status;
845 if (mTuner != NULL) {
Eric Laurent01d267e2016-10-21 08:16:10 -0700846 status = (status_t)mTuner->getProgramInformation(info);
Eric Laurent4e090692015-03-05 15:12:40 -0800847 } else {
848 status = INVALID_OPERATION;
849 }
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700850
Eric Laurent4e090692015-03-05 15:12:40 -0800851 return status;
852}
853
854status_t RadioService::ModuleClient::hasControl(bool *hasControl)
855{
856 Mutex::Autolock lock(mLock);
857 ALOGV("%s locked", __FUNCTION__);
Eric Laurent01d267e2016-10-21 08:16:10 -0700858 *hasControl = mTuner != 0;
Eric Laurent4e090692015-03-05 15:12:40 -0800859 return NO_ERROR;
860}
861
862void RadioService::ModuleClient::onCallbackEvent(const sp<IMemory>& eventMemory)
863{
864 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
865 return;
866 }
867
868 sp<IRadioClient> client;
869 {
870 AutoMutex lock(mLock);
871 ALOGV("%s locked", __FUNCTION__);
872 radio_event_t *event = (radio_event_t *)eventMemory->pointer();
873 switch (event->type) {
874 case RADIO_EVENT_CONFIG:
875 mConfig.band = event->config.band;
876 event->config.region = mConfig.region;
877 break;
878 default:
879 break;
880 }
881
882 client = mClient;
883 }
884 if (client != 0) {
885 client->onEvent(eventMemory);
886 }
887}
888
889
890void RadioService::ModuleClient::binderDied(
891 const wp<IBinder> &who __unused) {
892 ALOGW("client binder died for client %p", this);
893 detach();
894}
895
896}; // namespace android