blob: e0795522a70e0f7218be3d7590335d458b849ce5 [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{
54 const hw_module_t *mod;
55 int rc;
56 struct radio_hw_device *dev;
57
58 ALOGI("%s", __FUNCTION__);
59
60 rc = hw_get_module_by_class(RADIO_HARDWARE_MODULE_ID, RADIO_HARDWARE_MODULE_ID_FM, &mod);
61 if (rc != 0) {
62 ALOGE("couldn't load radio module %s.%s (%s)",
63 RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc));
64 return;
65 }
66 rc = radio_hw_device_open(mod, &dev);
67 if (rc != 0) {
68 ALOGE("couldn't open radio hw device in %s.%s (%s)",
69 RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc));
70 return;
71 }
72 if (dev->common.version != RADIO_DEVICE_API_VERSION_CURRENT) {
73 ALOGE("wrong radio hw device version %04x", dev->common.version);
74 return;
75 }
76
77 struct radio_hal_properties halProperties;
78 rc = dev->get_properties(dev, &halProperties);
79 if (rc != 0) {
80 ALOGE("could not read implementation properties");
81 return;
82 }
83
84 radio_properties_t properties;
85 properties.handle =
86 (radio_handle_t)android_atomic_inc(&mNextUniqueId);
87
88 ALOGI("loaded default module %s, handle %d", properties.product, properties.handle);
89
90 convertProperties(&properties, &halProperties);
Eric Laurent53810822015-03-12 09:12:01 -070091 sp<Module> module = new Module(dev, properties);
Eric Laurent4e090692015-03-05 15:12:40 -080092 mModules.add(properties.handle, module);
93}
94
95RadioService::~RadioService()
96{
97 for (size_t i = 0; i < mModules.size(); i++) {
98 radio_hw_device_close(mModules.valueAt(i)->hwDevice());
99 }
100}
101
102status_t RadioService::listModules(struct radio_properties *properties,
103 uint32_t *numModules)
104{
105 ALOGV("listModules");
106
107 AutoMutex lock(mServiceLock);
108 if (numModules == NULL || (*numModules != 0 && properties == NULL)) {
109 return BAD_VALUE;
110 }
111 size_t maxModules = *numModules;
112 *numModules = mModules.size();
113 for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
114 properties[i] = mModules.valueAt(i)->properties();
115 }
116 return NO_ERROR;
117}
118
119status_t RadioService::attach(radio_handle_t handle,
120 const sp<IRadioClient>& client,
121 const struct radio_band_config *config,
122 bool withAudio,
123 sp<IRadio>& radio)
124{
125 ALOGV("%s %d config %p withAudio %d", __FUNCTION__, handle, config, withAudio);
126
127 AutoMutex lock(mServiceLock);
128 radio.clear();
129 if (client == 0) {
130 return BAD_VALUE;
131 }
132 ssize_t index = mModules.indexOfKey(handle);
133 if (index < 0) {
134 return BAD_VALUE;
135 }
136 sp<Module> module = mModules.valueAt(index);
137
138 if (config == NULL) {
139 config = module->getDefaultConfig();
140 if (config == NULL) {
141 return INVALID_OPERATION;
142 }
143 }
144 ALOGV("%s region %d type %d", __FUNCTION__, config->region, config->band.type);
145
146 radio = module->addClient(client, config, withAudio);
147
148 if (radio == 0) {
Eric Laurentf2f79cf2015-04-23 17:10:50 -0700149 return NO_INIT;
Eric Laurent4e090692015-03-05 15:12:40 -0800150 }
151 return NO_ERROR;
152}
153
154
155static const int kDumpLockRetries = 50;
156static const int kDumpLockSleep = 60000;
157
158static bool tryLock(Mutex& mutex)
159{
160 bool locked = false;
161 for (int i = 0; i < kDumpLockRetries; ++i) {
162 if (mutex.tryLock() == NO_ERROR) {
163 locked = true;
164 break;
165 }
166 usleep(kDumpLockSleep);
167 }
168 return locked;
169}
170
171status_t RadioService::dump(int fd, const Vector<String16>& args __unused) {
172 String8 result;
173 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
174 result.appendFormat("Permission Denial: can't dump RadioService");
175 write(fd, result.string(), result.size());
176 } else {
177 bool locked = tryLock(mServiceLock);
178 // failed to lock - RadioService is probably deadlocked
179 if (!locked) {
180 result.append("RadioService may be deadlocked\n");
181 write(fd, result.string(), result.size());
182 }
183
184 if (locked) mServiceLock.unlock();
185 }
186 return NO_ERROR;
187}
188
189status_t RadioService::onTransact(
190 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
191 return BnRadioService::onTransact(code, data, reply, flags);
192}
193
194
195// static
196void RadioService::callback(radio_hal_event_t *halEvent, void *cookie)
197{
198 CallbackThread *callbackThread = (CallbackThread *)cookie;
199 if (callbackThread == NULL) {
200 return;
201 }
202 callbackThread->sendEvent(halEvent);
203}
204
205/* static */
206void RadioService::convertProperties(radio_properties_t *properties,
207 const radio_hal_properties_t *halProperties)
208{
209 memset(properties, 0, sizeof(struct radio_properties));
210 properties->class_id = halProperties->class_id;
211 strlcpy(properties->implementor, halProperties->implementor,
212 RADIO_STRING_LEN_MAX);
213 strlcpy(properties->product, halProperties->product,
214 RADIO_STRING_LEN_MAX);
215 strlcpy(properties->version, halProperties->version,
216 RADIO_STRING_LEN_MAX);
217 strlcpy(properties->serial, halProperties->serial,
218 RADIO_STRING_LEN_MAX);
219 properties->num_tuners = halProperties->num_tuners;
220 properties->num_audio_sources = halProperties->num_audio_sources;
221 properties->supports_capture = halProperties->supports_capture;
222
223 for (size_t i = 0; i < ARRAY_SIZE(sKnownRegionConfigs); i++) {
224 const radio_hal_band_config_t *band = &sKnownRegionConfigs[i].band;
225 size_t j;
226 for (j = 0; j < halProperties->num_bands; j++) {
227 const radio_hal_band_config_t *halBand = &halProperties->bands[j];
228 size_t k;
229 if (band->type != halBand->type) continue;
230 if (band->lower_limit < halBand->lower_limit) continue;
231 if (band->upper_limit > halBand->upper_limit) continue;
232 for (k = 0; k < halBand->num_spacings; k++) {
233 if (band->spacings[0] == halBand->spacings[k]) break;
234 }
235 if (k == halBand->num_spacings) continue;
236 if (band->type == RADIO_BAND_AM) break;
237 if ((band->fm.deemphasis & halBand->fm.deemphasis) == 0) continue;
238 if (halBand->fm.rds == 0) break;
239 if ((band->fm.rds & halBand->fm.rds) != 0) break;
240 }
241 if (j == halProperties->num_bands) continue;
242
243 ALOGI("convertProperties() Adding band type %d region %d",
244 sKnownRegionConfigs[i].band.type , sKnownRegionConfigs[i].region);
245
246 memcpy(&properties->bands[properties->num_bands++],
247 &sKnownRegionConfigs[i],
248 sizeof(radio_band_config_t));
249 }
250}
251
252#undef LOG_TAG
253#define LOG_TAG "RadioService::CallbackThread"
254
255RadioService::CallbackThread::CallbackThread(const wp<ModuleClient>& moduleClient)
256 : mModuleClient(moduleClient), mMemoryDealer(new MemoryDealer(1024 * 1024, "RadioService"))
257{
258}
259
260RadioService::CallbackThread::~CallbackThread()
261{
262 mEventQueue.clear();
263}
264
265void RadioService::CallbackThread::onFirstRef()
266{
267 run("RadioService cbk", ANDROID_PRIORITY_URGENT_AUDIO);
268}
269
270bool RadioService::CallbackThread::threadLoop()
271{
272 while (!exitPending()) {
273 sp<IMemory> eventMemory;
274 sp<ModuleClient> moduleClient;
275 {
276 Mutex::Autolock _l(mCallbackLock);
277 while (mEventQueue.isEmpty() && !exitPending()) {
278 ALOGV("CallbackThread::threadLoop() sleep");
279 mCallbackCond.wait(mCallbackLock);
280 ALOGV("CallbackThread::threadLoop() wake up");
281 }
282 if (exitPending()) {
283 break;
284 }
285 eventMemory = mEventQueue[0];
286 mEventQueue.removeAt(0);
287 moduleClient = mModuleClient.promote();
288 }
289 if (moduleClient != 0) {
290 moduleClient->onCallbackEvent(eventMemory);
291 eventMemory.clear();
292 }
293 }
294 return false;
295}
296
297void RadioService::CallbackThread::exit()
298{
299 Mutex::Autolock _l(mCallbackLock);
300 requestExit();
301 mCallbackCond.broadcast();
302}
303
304sp<IMemory> RadioService::CallbackThread::prepareEvent(radio_hal_event_t *halEvent)
305{
306 sp<IMemory> eventMemory;
307
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700308 // The event layout in shared memory is:
309 // sizeof(struct radio_event) bytes : the event itself
310 // 4 bytes : metadata size or 0
311 // N bytes : metadata if present
312 uint32_t metadataOffset = sizeof(struct radio_event) + sizeof(uint32_t);
313 uint32_t metadataSize = 0;
314
Eric Laurent4e090692015-03-05 15:12:40 -0800315 switch (halEvent->type) {
316 case RADIO_EVENT_TUNED:
317 case RADIO_EVENT_AF_SWITCH:
318 if (radio_metadata_check(halEvent->info.metadata) == 0) {
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700319 metadataSize = (uint32_t)radio_metadata_get_size(halEvent->info.metadata);
Eric Laurent4e090692015-03-05 15:12:40 -0800320 }
321 break;
322 case RADIO_EVENT_METADATA:
323 if (radio_metadata_check(halEvent->metadata) != 0) {
324 return eventMemory;
325 }
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700326 metadataSize = (uint32_t)radio_metadata_get_size(halEvent->metadata);
Eric Laurent4e090692015-03-05 15:12:40 -0800327 break;
328 default:
329 break;
330 }
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700331
332 eventMemory = mMemoryDealer->allocate(metadataOffset + metadataSize);
Eric Laurent4e090692015-03-05 15:12:40 -0800333 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
334 eventMemory.clear();
335 return eventMemory;
336 }
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700337
Eric Laurent4e090692015-03-05 15:12:40 -0800338 struct radio_event *event = (struct radio_event *)eventMemory->pointer();
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700339
340 *(uint32_t *)((uint8_t *)event + metadataOffset - sizeof(uint32_t)) = metadataSize;
341
Eric Laurent4e090692015-03-05 15:12:40 -0800342 event->type = halEvent->type;
343 event->status = halEvent->status;
344
345 switch (event->type) {
346 case RADIO_EVENT_CONFIG:
347 event->config.band = halEvent->config;
348 break;
349 case RADIO_EVENT_TUNED:
350 case RADIO_EVENT_AF_SWITCH:
351 event->info = halEvent->info;
352 if (metadataSize != 0) {
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700353 memcpy((uint8_t *)event + metadataOffset, halEvent->info.metadata, metadataSize);
Eric Laurent4e090692015-03-05 15:12:40 -0800354 }
355 break;
356 case RADIO_EVENT_TA:
Sanket Agarwalf639ba12015-10-12 13:05:53 -0700357 case RADIO_EVENT_EA:
Eric Laurent4e090692015-03-05 15:12:40 -0800358 case RADIO_EVENT_ANTENNA:
359 case RADIO_EVENT_CONTROL:
360 event->on = halEvent->on;
361 break;
362 case RADIO_EVENT_METADATA:
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700363 if (metadataSize != 0) {
364 memcpy((uint8_t *)event + metadataOffset, halEvent->metadata, metadataSize);
365 }
Eric Laurent4e090692015-03-05 15:12:40 -0800366 break;
367 case RADIO_EVENT_HW_FAILURE:
368 default:
369 break;
370 }
371
372 return eventMemory;
373}
374
375void RadioService::CallbackThread::sendEvent(radio_hal_event_t *event)
376 {
377 sp<IMemory> eventMemory = prepareEvent(event);
378 if (eventMemory == 0) {
379 return;
380 }
381
382 AutoMutex lock(mCallbackLock);
383 mEventQueue.add(eventMemory);
384 mCallbackCond.signal();
385 ALOGV("%s DONE", __FUNCTION__);
386}
387
388
389#undef LOG_TAG
390#define LOG_TAG "RadioService::Module"
391
Eric Laurent53810822015-03-12 09:12:01 -0700392RadioService::Module::Module(radio_hw_device* hwDevice, radio_properties properties)
393 : mHwDevice(hwDevice), mProperties(properties), mMute(true)
Eric Laurent4e090692015-03-05 15:12:40 -0800394{
395}
396
397RadioService::Module::~Module() {
398 mModuleClients.clear();
399}
400
401status_t RadioService::Module::dump(int fd __unused, const Vector<String16>& args __unused) {
402 String8 result;
403 return NO_ERROR;
404}
405
406sp<RadioService::ModuleClient> RadioService::Module::addClient(const sp<IRadioClient>& client,
407 const struct radio_band_config *config,
408 bool audio)
409{
410 ALOGV("addClient() %p config %p product %s", this, config, mProperties.product);
411 AutoMutex lock(mLock);
412 sp<ModuleClient> moduleClient;
413 int ret;
414
415 for (size_t i = 0; i < mModuleClients.size(); i++) {
416 if (mModuleClients[i]->client() == client) {
417 // client already connected: reject
418 return moduleClient;
419 }
420 }
421 moduleClient = new ModuleClient(this, client, config, audio);
422
423 struct radio_hal_band_config halConfig;
424 halConfig = config->band;
425
Eric Laurent53810822015-03-12 09:12:01 -0700426 // Tuner preemption logic:
427 // There is a limited amount of tuners and a limited amount of radio audio sources per module.
428 // The minimum is one tuner and one audio source.
429 // The numbers of tuners and sources are indicated in the module properties.
430 // NOTE: current framework implementation only supports one radio audio source.
431 // It is possible to open more than one tuner at a time but only one tuner can be connected
432 // to the radio audio source (AUDIO_DEVICE_IN_FM_TUNER).
433 // The base rule is that a newly connected tuner always wins, i.e. always gets a tuner
434 // and can use the audio source if requested.
435 // If another client is preempted, it is notified by a callback with RADIO_EVENT_CONTROL
436 // indicating loss of control.
437 // - If the newly connected client requests the audio source (audio == true):
438 // - if an audio source is available
439 // no problem
440 // - if not:
441 // the oldest client in the list using audio is preempted.
442 // - If the newly connected client does not request the audio source (audio == false):
443 // - if a tuner is available
444 // no problem
445 // - if not:
446 // The oldest client not using audio is preempted first and if none is found the
447 // the oldest client using audio is preempted.
448 // Each time a tuner using the audio source is opened or closed, the audio policy manager is
449 // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
450
Eric Laurent4e090692015-03-05 15:12:40 -0800451 sp<ModuleClient> oldestTuner;
452 sp<ModuleClient> oldestAudio;
453 size_t allocatedTuners = 0;
454 size_t allocatedAudio = 0;
455 for (size_t i = 0; i < mModuleClients.size(); i++) {
456 if (mModuleClients[i]->getTuner() != NULL) {
457 if (mModuleClients[i]->audio()) {
458 if (oldestAudio == 0) {
459 oldestAudio = mModuleClients[i];
460 }
461 allocatedAudio++;
462 } else {
463 if (oldestTuner == 0) {
464 oldestTuner = mModuleClients[i];
465 }
466 allocatedTuners++;
467 }
468 }
469 }
470
471 const struct radio_tuner *halTuner;
Eric Laurent53810822015-03-12 09:12:01 -0700472 sp<ModuleClient> preemtedClient;
Eric Laurent4e090692015-03-05 15:12:40 -0800473 if (audio) {
474 if (allocatedAudio >= mProperties.num_audio_sources) {
475 ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
Eric Laurent53810822015-03-12 09:12:01 -0700476 preemtedClient = oldestAudio;
Eric Laurent4e090692015-03-05 15:12:40 -0800477 }
478 } else {
479 if (allocatedAudio + allocatedTuners >= mProperties.num_tuners) {
480 if (allocatedTuners != 0) {
481 ALOG_ASSERT(oldestTuner != 0, "addClient() allocatedTuners/oldestTuner mismatch");
Eric Laurent53810822015-03-12 09:12:01 -0700482 preemtedClient = oldestTuner;
Eric Laurent4e090692015-03-05 15:12:40 -0800483 } else {
484 ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
Eric Laurent53810822015-03-12 09:12:01 -0700485 preemtedClient = oldestAudio;
Eric Laurent4e090692015-03-05 15:12:40 -0800486 }
487 }
488 }
Eric Laurent53810822015-03-12 09:12:01 -0700489 if (preemtedClient != 0) {
490 halTuner = preemtedClient->getTuner();
491 preemtedClient->setTuner(NULL);
492 mHwDevice->close_tuner(mHwDevice, halTuner);
493 if (preemtedClient->audio()) {
494 notifyDeviceConnection(false, "");
495 }
496 }
Eric Laurent4e090692015-03-05 15:12:40 -0800497
498 ret = mHwDevice->open_tuner(mHwDevice, &halConfig, audio,
499 RadioService::callback, moduleClient->callbackThread().get(),
500 &halTuner);
501 if (ret == 0) {
502 ALOGV("addClient() setTuner %p", halTuner);
503 moduleClient->setTuner(halTuner);
504 mModuleClients.add(moduleClient);
Eric Laurent53810822015-03-12 09:12:01 -0700505 if (audio) {
506 notifyDeviceConnection(true, "");
507 }
Eric Laurentf2f79cf2015-04-23 17:10:50 -0700508 ALOGV("addClient() DONE moduleClient %p", moduleClient.get());
Eric Laurent4e090692015-03-05 15:12:40 -0800509 } else {
Eric Laurentf2f79cf2015-04-23 17:10:50 -0700510 ALOGW("%s open_tuner failed with error %d", __FUNCTION__, ret);
Eric Laurent4e090692015-03-05 15:12:40 -0800511 moduleClient.clear();
512 }
513
Eric Laurent4e090692015-03-05 15:12:40 -0800514 return moduleClient;
515}
516
517void RadioService::Module::removeClient(const sp<ModuleClient>& moduleClient) {
518 ALOGV("removeClient()");
519 AutoMutex lock(mLock);
520 int ret;
521 ssize_t index = -1;
522
523 for (size_t i = 0; i < mModuleClients.size(); i++) {
524 if (mModuleClients[i] == moduleClient) {
525 index = i;
526 break;
527 }
528 }
529 if (index == -1) {
530 return;
531 }
532
533 mModuleClients.removeAt(index);
534 const struct radio_tuner *halTuner = moduleClient->getTuner();
535 if (halTuner == NULL) {
536 return;
537 }
538
539 mHwDevice->close_tuner(mHwDevice, halTuner);
Eric Laurent53810822015-03-12 09:12:01 -0700540 if (moduleClient->audio()) {
541 notifyDeviceConnection(false, "");
542 }
Eric Laurent4e090692015-03-05 15:12:40 -0800543
Eric Laurent4e090692015-03-05 15:12:40 -0800544 mMute = true;
545
546 if (mModuleClients.isEmpty()) {
547 return;
548 }
549
Eric Laurent53810822015-03-12 09:12:01 -0700550 // Tuner reallocation logic:
551 // When a client is removed and was controlling a tuner, this tuner will be allocated to a
552 // previously preempted client. This client will be notified by a callback with
553 // RADIO_EVENT_CONTROL indicating gain of control.
554 // - If a preempted client is waiting for an audio source and one becomes available:
555 // Allocate the tuner to the most recently added client waiting for an audio source
556 // - If not:
557 // Allocate the tuner to the most recently added client.
558 // Each time a tuner using the audio source is opened or closed, the audio policy manager is
559 // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
560
Eric Laurent4e090692015-03-05 15:12:40 -0800561 sp<ModuleClient> youngestClient;
562 sp<ModuleClient> youngestClientAudio;
563 size_t allocatedTuners = 0;
564 size_t allocatedAudio = 0;
Eric Laurent53810822015-03-12 09:12:01 -0700565 for (ssize_t i = mModuleClients.size() - 1; i >= 0; i--) {
Eric Laurent4e090692015-03-05 15:12:40 -0800566 if (mModuleClients[i]->getTuner() == NULL) {
567 if (mModuleClients[i]->audio()) {
568 if (youngestClientAudio == 0) {
569 youngestClientAudio = mModuleClients[i];
570 }
571 } else {
572 if (youngestClient == 0) {
573 youngestClient = mModuleClients[i];
574 }
575 }
576 } else {
577 if (mModuleClients[i]->audio()) {
578 allocatedAudio++;
579 } else {
580 allocatedTuners++;
581 }
582 }
583 }
584
585 ALOG_ASSERT(allocatedTuners + allocatedAudio < mProperties.num_tuners,
586 "removeClient() removed client but no tuner available");
587
588 ALOG_ASSERT(!moduleClient->audio() || allocatedAudio < mProperties.num_audio_sources,
589 "removeClient() removed audio client but no tuner with audio available");
590
591 if (allocatedAudio < mProperties.num_audio_sources && youngestClientAudio != 0) {
592 youngestClient = youngestClientAudio;
593 }
594
595 ALOG_ASSERT(youngestClient != 0, "removeClient() removed client no candidate found for tuner");
596
597 struct radio_hal_band_config halConfig = youngestClient->halConfig();
598 ret = mHwDevice->open_tuner(mHwDevice, &halConfig, youngestClient->audio(),
599 RadioService::callback, moduleClient->callbackThread().get(),
600 &halTuner);
601
Eric Laurent4e090692015-03-05 15:12:40 -0800602 if (ret == 0) {
603 youngestClient->setTuner(halTuner);
Eric Laurent53810822015-03-12 09:12:01 -0700604 if (youngestClient->audio()) {
605 notifyDeviceConnection(true, "");
606 }
Eric Laurent4e090692015-03-05 15:12:40 -0800607 }
608}
609
610status_t RadioService::Module::setMute(bool mute)
611{
612 Mutex::Autolock _l(mLock);
613 if (mute != mMute) {
614 mMute = mute;
615 //TODO notifify audio policy manager of media activity on radio audio device
616 }
617 return NO_ERROR;
618}
619
620status_t RadioService::Module::getMute(bool *mute)
621{
622 Mutex::Autolock _l(mLock);
623 *mute = mMute;
624 return NO_ERROR;
625}
626
627
628const struct radio_band_config *RadioService::Module::getDefaultConfig() const
629{
630 if (mProperties.num_bands == 0) {
631 return NULL;
632 }
633 return &mProperties.bands[0];
634}
635
Eric Laurent53810822015-03-12 09:12:01 -0700636void RadioService::Module::notifyDeviceConnection(bool connected,
637 const char *address) {
638 int64_t token = IPCThreadState::self()->clearCallingIdentity();
639 AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_FM_TUNER,
640 connected ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE :
641 AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
642 address, kRadioTunerAudioDeviceName);
643 IPCThreadState::self()->restoreCallingIdentity(token);
644}
645
Eric Laurent4e090692015-03-05 15:12:40 -0800646#undef LOG_TAG
647#define LOG_TAG "RadioService::ModuleClient"
648
649RadioService::ModuleClient::ModuleClient(const sp<Module>& module,
650 const sp<IRadioClient>& client,
651 const struct radio_band_config *config,
652 bool audio)
653 : mModule(module), mClient(client), mConfig(*config), mAudio(audio), mTuner(NULL)
654{
655}
656
657void RadioService::ModuleClient::onFirstRef()
658{
659 mCallbackThread = new CallbackThread(this);
660 IInterface::asBinder(mClient)->linkToDeath(this);
661}
662
663RadioService::ModuleClient::~ModuleClient() {
664 if (mClient != 0) {
665 IInterface::asBinder(mClient)->unlinkToDeath(this);
666 mClient.clear();
667 }
668 if (mCallbackThread != 0) {
669 mCallbackThread->exit();
670 }
671}
672
673status_t RadioService::ModuleClient::dump(int fd __unused,
674 const Vector<String16>& args __unused) {
675 String8 result;
676 return NO_ERROR;
677}
678
679void RadioService::ModuleClient::detach() {
680 ALOGV("%s", __FUNCTION__);
681 sp<ModuleClient> strongMe = this;
682 {
683 AutoMutex lock(mLock);
684 if (mClient != 0) {
685 IInterface::asBinder(mClient)->unlinkToDeath(this);
686 mClient.clear();
687 }
688 }
689 sp<Module> module = mModule.promote();
690 if (module == 0) {
691 return;
692 }
693 module->removeClient(this);
694}
695
696radio_hal_band_config_t RadioService::ModuleClient::halConfig() const
697{
698 AutoMutex lock(mLock);
699 ALOGV("%s locked", __FUNCTION__);
700 return mConfig.band;
701}
702
703const struct radio_tuner *RadioService::ModuleClient::getTuner() const
704{
705 AutoMutex lock(mLock);
706 ALOGV("%s locked", __FUNCTION__);
707 return mTuner;
708}
709
710void RadioService::ModuleClient::setTuner(const struct radio_tuner *tuner)
711{
712 ALOGV("%s %p", __FUNCTION__, this);
713
714 AutoMutex lock(mLock);
715 mTuner = tuner;
716 ALOGV("%s locked", __FUNCTION__);
717
718 radio_hal_event_t event;
719 event.type = RADIO_EVENT_CONTROL;
720 event.status = 0;
721 event.on = mTuner != NULL;
722 mCallbackThread->sendEvent(&event);
723 ALOGV("%s DONE", __FUNCTION__);
724
725}
726
727status_t RadioService::ModuleClient::setConfiguration(const struct radio_band_config *config)
728{
729 AutoMutex lock(mLock);
730 status_t status = NO_ERROR;
731 ALOGV("%s locked", __FUNCTION__);
732
733 if (mTuner != NULL) {
734 struct radio_hal_band_config halConfig;
735 halConfig = config->band;
736 status = (status_t)mTuner->set_configuration(mTuner, &halConfig);
737 if (status == NO_ERROR) {
738 mConfig = *config;
739 }
740 } else {
741 mConfig = *config;
Aurimas Liutikas13958742016-02-18 10:02:35 -0800742 status = INVALID_OPERATION;
Eric Laurent4e090692015-03-05 15:12:40 -0800743 }
744
745 return status;
746}
747
748status_t RadioService::ModuleClient::getConfiguration(struct radio_band_config *config)
749{
750 AutoMutex lock(mLock);
751 status_t status = NO_ERROR;
752 ALOGV("%s locked", __FUNCTION__);
753
754 if (mTuner != NULL) {
755 struct radio_hal_band_config halConfig;
756 status = (status_t)mTuner->get_configuration(mTuner, &halConfig);
757 if (status == NO_ERROR) {
758 mConfig.band = halConfig;
759 }
760 }
761 *config = mConfig;
762
763 return status;
764}
765
766status_t RadioService::ModuleClient::setMute(bool mute)
767{
768 sp<Module> module;
769 {
770 Mutex::Autolock _l(mLock);
771 ALOGV("%s locked", __FUNCTION__);
772 if (mTuner == NULL || !mAudio) {
773 return INVALID_OPERATION;
774 }
775 module = mModule.promote();
776 if (module == 0) {
777 return NO_INIT;
778 }
779 }
780 module->setMute(mute);
781 return NO_ERROR;
782}
783
784status_t RadioService::ModuleClient::getMute(bool *mute)
785{
786 sp<Module> module;
787 {
788 Mutex::Autolock _l(mLock);
789 ALOGV("%s locked", __FUNCTION__);
790 module = mModule.promote();
791 if (module == 0) {
792 return NO_INIT;
793 }
794 }
795 return module->getMute(mute);
796}
797
798status_t RadioService::ModuleClient::scan(radio_direction_t direction, bool skipSubChannel)
799{
800 AutoMutex lock(mLock);
801 ALOGV("%s locked", __FUNCTION__);
802 status_t status;
803 if (mTuner != NULL) {
804 status = (status_t)mTuner->scan(mTuner, direction, skipSubChannel);
805 } else {
806 status = INVALID_OPERATION;
807 }
808 return status;
809}
810
811status_t RadioService::ModuleClient::step(radio_direction_t direction, bool skipSubChannel)
812{
813 AutoMutex lock(mLock);
814 ALOGV("%s locked", __FUNCTION__);
815 status_t status;
816 if (mTuner != NULL) {
817 status = (status_t)mTuner->step(mTuner, direction, skipSubChannel);
818 } else {
819 status = INVALID_OPERATION;
820 }
821 return status;
822}
823
824status_t RadioService::ModuleClient::tune(unsigned int channel, unsigned int subChannel)
825{
826 AutoMutex lock(mLock);
827 ALOGV("%s locked", __FUNCTION__);
828 status_t status;
829 if (mTuner != NULL) {
830 status = (status_t)mTuner->tune(mTuner, channel, subChannel);
831 } else {
832 status = INVALID_OPERATION;
833 }
834 return status;
835}
836
837status_t RadioService::ModuleClient::cancel()
838{
839 AutoMutex lock(mLock);
840 ALOGV("%s locked", __FUNCTION__);
841 status_t status;
842 if (mTuner != NULL) {
843 status = (status_t)mTuner->cancel(mTuner);
844 } else {
845 status = INVALID_OPERATION;
846 }
847 return status;
848}
849
850status_t RadioService::ModuleClient::getProgramInformation(struct radio_program_info *info)
851{
852 AutoMutex lock(mLock);
853 ALOGV("%s locked", __FUNCTION__);
854 status_t status;
855 if (mTuner != NULL) {
856 status = (status_t)mTuner->get_program_information(mTuner, info);
857 } else {
858 status = INVALID_OPERATION;
859 }
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700860
Eric Laurent4e090692015-03-05 15:12:40 -0800861 return status;
862}
863
864status_t RadioService::ModuleClient::hasControl(bool *hasControl)
865{
866 Mutex::Autolock lock(mLock);
867 ALOGV("%s locked", __FUNCTION__);
868 *hasControl = mTuner != NULL;
869 return NO_ERROR;
870}
871
872void RadioService::ModuleClient::onCallbackEvent(const sp<IMemory>& eventMemory)
873{
874 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
875 return;
876 }
877
878 sp<IRadioClient> client;
879 {
880 AutoMutex lock(mLock);
881 ALOGV("%s locked", __FUNCTION__);
882 radio_event_t *event = (radio_event_t *)eventMemory->pointer();
883 switch (event->type) {
884 case RADIO_EVENT_CONFIG:
885 mConfig.band = event->config.band;
886 event->config.region = mConfig.region;
887 break;
888 default:
889 break;
890 }
891
892 client = mClient;
893 }
894 if (client != 0) {
895 client->onEvent(eventMemory);
896 }
897}
898
899
900void RadioService::ModuleClient::binderDied(
901 const wp<IBinder> &who __unused) {
902 ALOGW("client binder died for client %p", this);
903 detach();
904}
905
906}; // namespace android