blob: 227955dc1af8885e5c3f4150ad0c34e257f3e756 [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
279 size_t headerSize =
280 (sizeof(struct radio_event) + sizeof(unsigned int) - 1) /sizeof(unsigned int);
281 size_t metadataSize = 0;
282 switch (halEvent->type) {
283 case RADIO_EVENT_TUNED:
284 case RADIO_EVENT_AF_SWITCH:
285 if (radio_metadata_check(halEvent->info.metadata) == 0) {
286 metadataSize = radio_metadata_get_size(halEvent->info.metadata);
287 }
288 break;
289 case RADIO_EVENT_METADATA:
290 if (radio_metadata_check(halEvent->metadata) != 0) {
291 return eventMemory;
292 }
293 metadataSize = radio_metadata_get_size(halEvent->metadata);
294 break;
295 default:
296 break;
297 }
298 size_t size = headerSize + metadataSize;
299 eventMemory = mMemoryDealer->allocate(size);
300 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
301 eventMemory.clear();
302 return eventMemory;
303 }
304 struct radio_event *event = (struct radio_event *)eventMemory->pointer();
305 event->type = halEvent->type;
306 event->status = halEvent->status;
307
308 switch (event->type) {
309 case RADIO_EVENT_CONFIG:
310 event->config.band = halEvent->config;
311 break;
312 case RADIO_EVENT_TUNED:
313 case RADIO_EVENT_AF_SWITCH:
314 event->info = halEvent->info;
315 if (metadataSize != 0) {
316 memcpy((char *)event + headerSize, halEvent->info.metadata, metadataSize);
317 // replace meta data pointer by offset while in shared memory so that receiving side
318 // can restore the pointer in destination process.
319 event->info.metadata = (radio_metadata_t *)headerSize;
320 }
321 break;
322 case RADIO_EVENT_TA:
Sanket Agarwalf639ba12015-10-12 13:05:53 -0700323 case RADIO_EVENT_EA:
Eric Laurent4e090692015-03-05 15:12:40 -0800324 case RADIO_EVENT_ANTENNA:
325 case RADIO_EVENT_CONTROL:
326 event->on = halEvent->on;
327 break;
328 case RADIO_EVENT_METADATA:
329 memcpy((char *)event + headerSize, halEvent->metadata, metadataSize);
330 // replace meta data pointer by offset while in shared memory so that receiving side
331 // can restore the pointer in destination process.
332 event->metadata = (radio_metadata_t *)headerSize;
333 break;
334 case RADIO_EVENT_HW_FAILURE:
335 default:
336 break;
337 }
338
339 return eventMemory;
340}
341
342void RadioService::CallbackThread::sendEvent(radio_hal_event_t *event)
343 {
344 sp<IMemory> eventMemory = prepareEvent(event);
345 if (eventMemory == 0) {
346 return;
347 }
348
349 AutoMutex lock(mCallbackLock);
350 mEventQueue.add(eventMemory);
351 mCallbackCond.signal();
352 ALOGV("%s DONE", __FUNCTION__);
353}
354
355
356#undef LOG_TAG
357#define LOG_TAG "RadioService::Module"
358
Eric Laurent01d267e2016-10-21 08:16:10 -0700359RadioService::Module::Module(sp<RadioInterface> hwDevice, radio_properties properties)
Eric Laurent53810822015-03-12 09:12:01 -0700360 : mHwDevice(hwDevice), mProperties(properties), mMute(true)
Eric Laurent4e090692015-03-05 15:12:40 -0800361{
362}
363
364RadioService::Module::~Module() {
Eric Laurent01d267e2016-10-21 08:16:10 -0700365 mHwDevice.clear();
Eric Laurent4e090692015-03-05 15:12:40 -0800366 mModuleClients.clear();
367}
368
369status_t RadioService::Module::dump(int fd __unused, const Vector<String16>& args __unused) {
370 String8 result;
371 return NO_ERROR;
372}
373
374sp<RadioService::ModuleClient> RadioService::Module::addClient(const sp<IRadioClient>& client,
375 const struct radio_band_config *config,
376 bool audio)
377{
378 ALOGV("addClient() %p config %p product %s", this, config, mProperties.product);
Eric Laurent01d267e2016-10-21 08:16:10 -0700379
Eric Laurent4e090692015-03-05 15:12:40 -0800380 AutoMutex lock(mLock);
381 sp<ModuleClient> moduleClient;
382 int ret;
383
Eric Laurent01d267e2016-10-21 08:16:10 -0700384 if (mHwDevice == 0) {
385 return moduleClient;
386 }
387
Eric Laurent4e090692015-03-05 15:12:40 -0800388 for (size_t i = 0; i < mModuleClients.size(); i++) {
389 if (mModuleClients[i]->client() == client) {
390 // client already connected: reject
391 return moduleClient;
392 }
393 }
394 moduleClient = new ModuleClient(this, client, config, audio);
395
396 struct radio_hal_band_config halConfig;
397 halConfig = config->band;
398
Eric Laurent53810822015-03-12 09:12:01 -0700399 // Tuner preemption logic:
400 // There is a limited amount of tuners and a limited amount of radio audio sources per module.
401 // The minimum is one tuner and one audio source.
402 // The numbers of tuners and sources are indicated in the module properties.
403 // NOTE: current framework implementation only supports one radio audio source.
404 // It is possible to open more than one tuner at a time but only one tuner can be connected
405 // to the radio audio source (AUDIO_DEVICE_IN_FM_TUNER).
406 // The base rule is that a newly connected tuner always wins, i.e. always gets a tuner
407 // and can use the audio source if requested.
408 // If another client is preempted, it is notified by a callback with RADIO_EVENT_CONTROL
409 // indicating loss of control.
410 // - If the newly connected client requests the audio source (audio == true):
411 // - if an audio source is available
412 // no problem
413 // - if not:
414 // the oldest client in the list using audio is preempted.
415 // - If the newly connected client does not request the audio source (audio == false):
416 // - if a tuner is available
417 // no problem
418 // - if not:
419 // The oldest client not using audio is preempted first and if none is found the
420 // the oldest client using audio is preempted.
421 // Each time a tuner using the audio source is opened or closed, the audio policy manager is
422 // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
423
Eric Laurent4e090692015-03-05 15:12:40 -0800424 sp<ModuleClient> oldestTuner;
425 sp<ModuleClient> oldestAudio;
426 size_t allocatedTuners = 0;
427 size_t allocatedAudio = 0;
428 for (size_t i = 0; i < mModuleClients.size(); i++) {
429 if (mModuleClients[i]->getTuner() != NULL) {
430 if (mModuleClients[i]->audio()) {
431 if (oldestAudio == 0) {
432 oldestAudio = mModuleClients[i];
433 }
434 allocatedAudio++;
435 } else {
436 if (oldestTuner == 0) {
437 oldestTuner = mModuleClients[i];
438 }
439 allocatedTuners++;
440 }
441 }
442 }
443
Eric Laurent01d267e2016-10-21 08:16:10 -0700444 sp<TunerInterface> halTuner;
Eric Laurent53810822015-03-12 09:12:01 -0700445 sp<ModuleClient> preemtedClient;
Eric Laurent4e090692015-03-05 15:12:40 -0800446 if (audio) {
447 if (allocatedAudio >= mProperties.num_audio_sources) {
448 ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
Eric Laurent53810822015-03-12 09:12:01 -0700449 preemtedClient = oldestAudio;
Eric Laurent4e090692015-03-05 15:12:40 -0800450 }
451 } else {
452 if (allocatedAudio + allocatedTuners >= mProperties.num_tuners) {
453 if (allocatedTuners != 0) {
454 ALOG_ASSERT(oldestTuner != 0, "addClient() allocatedTuners/oldestTuner mismatch");
Eric Laurent53810822015-03-12 09:12:01 -0700455 preemtedClient = oldestTuner;
Eric Laurent4e090692015-03-05 15:12:40 -0800456 } else {
457 ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
Eric Laurent53810822015-03-12 09:12:01 -0700458 preemtedClient = oldestAudio;
Eric Laurent4e090692015-03-05 15:12:40 -0800459 }
460 }
461 }
Eric Laurent53810822015-03-12 09:12:01 -0700462 if (preemtedClient != 0) {
463 halTuner = preemtedClient->getTuner();
Eric Laurent01d267e2016-10-21 08:16:10 -0700464 sp<TunerInterface> clear;
465 preemtedClient->setTuner(clear);
466 mHwDevice->closeTuner(halTuner);
Eric Laurent53810822015-03-12 09:12:01 -0700467 if (preemtedClient->audio()) {
468 notifyDeviceConnection(false, "");
469 }
470 }
Eric Laurent4e090692015-03-05 15:12:40 -0800471
Eric Laurent01d267e2016-10-21 08:16:10 -0700472 ret = mHwDevice->openTuner(&halConfig, audio,
473 moduleClient,
474 halTuner);
Eric Laurent4e090692015-03-05 15:12:40 -0800475 if (ret == 0) {
Eric Laurent01d267e2016-10-21 08:16:10 -0700476 ALOGV("addClient() setTuner %p", halTuner.get());
Eric Laurent4e090692015-03-05 15:12:40 -0800477 moduleClient->setTuner(halTuner);
478 mModuleClients.add(moduleClient);
Eric Laurent53810822015-03-12 09:12:01 -0700479 if (audio) {
480 notifyDeviceConnection(true, "");
481 }
Eric Laurentf2f79cf2015-04-23 17:10:50 -0700482 ALOGV("addClient() DONE moduleClient %p", moduleClient.get());
Eric Laurent4e090692015-03-05 15:12:40 -0800483 } else {
Eric Laurentf2f79cf2015-04-23 17:10:50 -0700484 ALOGW("%s open_tuner failed with error %d", __FUNCTION__, ret);
Eric Laurent4e090692015-03-05 15:12:40 -0800485 moduleClient.clear();
486 }
487
Eric Laurent4e090692015-03-05 15:12:40 -0800488 return moduleClient;
489}
490
491void RadioService::Module::removeClient(const sp<ModuleClient>& moduleClient) {
492 ALOGV("removeClient()");
493 AutoMutex lock(mLock);
494 int ret;
495 ssize_t index = -1;
496
497 for (size_t i = 0; i < mModuleClients.size(); i++) {
498 if (mModuleClients[i] == moduleClient) {
499 index = i;
500 break;
501 }
502 }
503 if (index == -1) {
504 return;
505 }
506
507 mModuleClients.removeAt(index);
Eric Laurent01d267e2016-10-21 08:16:10 -0700508 sp<TunerInterface> halTuner = moduleClient->getTuner();
Eric Laurent4e090692015-03-05 15:12:40 -0800509 if (halTuner == NULL) {
510 return;
511 }
512
Eric Laurent01d267e2016-10-21 08:16:10 -0700513 if (mHwDevice != 0) {
514 mHwDevice->closeTuner(halTuner);
515 }
516
Eric Laurent53810822015-03-12 09:12:01 -0700517 if (moduleClient->audio()) {
518 notifyDeviceConnection(false, "");
519 }
Eric Laurent4e090692015-03-05 15:12:40 -0800520
Eric Laurent4e090692015-03-05 15:12:40 -0800521 mMute = true;
522
523 if (mModuleClients.isEmpty()) {
524 return;
525 }
526
Eric Laurent01d267e2016-10-21 08:16:10 -0700527 if (mHwDevice == 0) {
528 return;
529 }
530
Eric Laurent53810822015-03-12 09:12:01 -0700531 // Tuner reallocation logic:
532 // When a client is removed and was controlling a tuner, this tuner will be allocated to a
533 // previously preempted client. This client will be notified by a callback with
534 // RADIO_EVENT_CONTROL indicating gain of control.
535 // - If a preempted client is waiting for an audio source and one becomes available:
536 // Allocate the tuner to the most recently added client waiting for an audio source
537 // - If not:
538 // Allocate the tuner to the most recently added client.
539 // Each time a tuner using the audio source is opened or closed, the audio policy manager is
540 // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
541
Eric Laurent4e090692015-03-05 15:12:40 -0800542 sp<ModuleClient> youngestClient;
543 sp<ModuleClient> youngestClientAudio;
544 size_t allocatedTuners = 0;
545 size_t allocatedAudio = 0;
Eric Laurent53810822015-03-12 09:12:01 -0700546 for (ssize_t i = mModuleClients.size() - 1; i >= 0; i--) {
Eric Laurent4e090692015-03-05 15:12:40 -0800547 if (mModuleClients[i]->getTuner() == NULL) {
548 if (mModuleClients[i]->audio()) {
549 if (youngestClientAudio == 0) {
550 youngestClientAudio = mModuleClients[i];
551 }
552 } else {
553 if (youngestClient == 0) {
554 youngestClient = mModuleClients[i];
555 }
556 }
557 } else {
558 if (mModuleClients[i]->audio()) {
559 allocatedAudio++;
560 } else {
561 allocatedTuners++;
562 }
563 }
564 }
565
566 ALOG_ASSERT(allocatedTuners + allocatedAudio < mProperties.num_tuners,
567 "removeClient() removed client but no tuner available");
568
569 ALOG_ASSERT(!moduleClient->audio() || allocatedAudio < mProperties.num_audio_sources,
570 "removeClient() removed audio client but no tuner with audio available");
571
572 if (allocatedAudio < mProperties.num_audio_sources && youngestClientAudio != 0) {
573 youngestClient = youngestClientAudio;
574 }
575
576 ALOG_ASSERT(youngestClient != 0, "removeClient() removed client no candidate found for tuner");
577
578 struct radio_hal_band_config halConfig = youngestClient->halConfig();
Eric Laurent01d267e2016-10-21 08:16:10 -0700579 ret = mHwDevice->openTuner(&halConfig, youngestClient->audio(),
580 moduleClient,
581 halTuner);
Eric Laurent4e090692015-03-05 15:12:40 -0800582
Eric Laurent4e090692015-03-05 15:12:40 -0800583 if (ret == 0) {
584 youngestClient->setTuner(halTuner);
Eric Laurent53810822015-03-12 09:12:01 -0700585 if (youngestClient->audio()) {
586 notifyDeviceConnection(true, "");
587 }
Eric Laurent4e090692015-03-05 15:12:40 -0800588 }
589}
590
591status_t RadioService::Module::setMute(bool mute)
592{
593 Mutex::Autolock _l(mLock);
594 if (mute != mMute) {
595 mMute = mute;
596 //TODO notifify audio policy manager of media activity on radio audio device
597 }
598 return NO_ERROR;
599}
600
601status_t RadioService::Module::getMute(bool *mute)
602{
603 Mutex::Autolock _l(mLock);
604 *mute = mMute;
605 return NO_ERROR;
606}
607
608
609const struct radio_band_config *RadioService::Module::getDefaultConfig() const
610{
611 if (mProperties.num_bands == 0) {
612 return NULL;
613 }
614 return &mProperties.bands[0];
615}
616
Eric Laurent53810822015-03-12 09:12:01 -0700617void RadioService::Module::notifyDeviceConnection(bool connected,
618 const char *address) {
619 int64_t token = IPCThreadState::self()->clearCallingIdentity();
620 AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_FM_TUNER,
621 connected ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE :
622 AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
623 address, kRadioTunerAudioDeviceName);
624 IPCThreadState::self()->restoreCallingIdentity(token);
625}
626
Eric Laurent4e090692015-03-05 15:12:40 -0800627#undef LOG_TAG
628#define LOG_TAG "RadioService::ModuleClient"
629
630RadioService::ModuleClient::ModuleClient(const sp<Module>& module,
631 const sp<IRadioClient>& client,
632 const struct radio_band_config *config,
633 bool audio)
Eric Laurent01d267e2016-10-21 08:16:10 -0700634 : mModule(module), mClient(client), mConfig(*config), mAudio(audio), mTuner(0)
Eric Laurent4e090692015-03-05 15:12:40 -0800635{
636}
637
638void RadioService::ModuleClient::onFirstRef()
639{
640 mCallbackThread = new CallbackThread(this);
641 IInterface::asBinder(mClient)->linkToDeath(this);
642}
643
644RadioService::ModuleClient::~ModuleClient() {
645 if (mClient != 0) {
646 IInterface::asBinder(mClient)->unlinkToDeath(this);
647 mClient.clear();
648 }
649 if (mCallbackThread != 0) {
650 mCallbackThread->exit();
651 }
652}
653
Eric Laurent01d267e2016-10-21 08:16:10 -0700654void RadioService::ModuleClient::onEvent(radio_hal_event_t *halEvent)
655{
656 mCallbackThread->sendEvent(halEvent);
657}
658
Eric Laurent4e090692015-03-05 15:12:40 -0800659status_t RadioService::ModuleClient::dump(int fd __unused,
660 const Vector<String16>& args __unused) {
661 String8 result;
662 return NO_ERROR;
663}
664
665void RadioService::ModuleClient::detach() {
666 ALOGV("%s", __FUNCTION__);
667 sp<ModuleClient> strongMe = this;
668 {
669 AutoMutex lock(mLock);
670 if (mClient != 0) {
671 IInterface::asBinder(mClient)->unlinkToDeath(this);
672 mClient.clear();
673 }
674 }
675 sp<Module> module = mModule.promote();
676 if (module == 0) {
677 return;
678 }
679 module->removeClient(this);
680}
681
682radio_hal_band_config_t RadioService::ModuleClient::halConfig() const
683{
684 AutoMutex lock(mLock);
685 ALOGV("%s locked", __FUNCTION__);
686 return mConfig.band;
687}
688
Eric Laurent01d267e2016-10-21 08:16:10 -0700689sp<TunerInterface>& RadioService::ModuleClient::getTuner()
Eric Laurent4e090692015-03-05 15:12:40 -0800690{
691 AutoMutex lock(mLock);
692 ALOGV("%s locked", __FUNCTION__);
693 return mTuner;
694}
695
Eric Laurent01d267e2016-10-21 08:16:10 -0700696void RadioService::ModuleClient::setTuner(sp<TunerInterface>& tuner)
Eric Laurent4e090692015-03-05 15:12:40 -0800697{
698 ALOGV("%s %p", __FUNCTION__, this);
699
700 AutoMutex lock(mLock);
701 mTuner = tuner;
702 ALOGV("%s locked", __FUNCTION__);
703
704 radio_hal_event_t event;
705 event.type = RADIO_EVENT_CONTROL;
706 event.status = 0;
Eric Laurent01d267e2016-10-21 08:16:10 -0700707 event.on = mTuner != 0;
Eric Laurent4e090692015-03-05 15:12:40 -0800708 mCallbackThread->sendEvent(&event);
709 ALOGV("%s DONE", __FUNCTION__);
710
711}
712
713status_t RadioService::ModuleClient::setConfiguration(const struct radio_band_config *config)
714{
715 AutoMutex lock(mLock);
716 status_t status = NO_ERROR;
717 ALOGV("%s locked", __FUNCTION__);
718
Eric Laurent01d267e2016-10-21 08:16:10 -0700719 if (mTuner != 0) {
Eric Laurent4e090692015-03-05 15:12:40 -0800720 struct radio_hal_band_config halConfig;
721 halConfig = config->band;
Eric Laurent01d267e2016-10-21 08:16:10 -0700722 status = (status_t)mTuner->setConfiguration(&halConfig);
Eric Laurent4e090692015-03-05 15:12:40 -0800723 if (status == NO_ERROR) {
724 mConfig = *config;
725 }
726 } else {
727 mConfig = *config;
Aurimas Liutikas13958742016-02-18 10:02:35 -0800728 status = INVALID_OPERATION;
Eric Laurent4e090692015-03-05 15:12:40 -0800729 }
730
731 return status;
732}
733
734status_t RadioService::ModuleClient::getConfiguration(struct radio_band_config *config)
735{
736 AutoMutex lock(mLock);
737 status_t status = NO_ERROR;
738 ALOGV("%s locked", __FUNCTION__);
739
Eric Laurent01d267e2016-10-21 08:16:10 -0700740 if (mTuner != 0) {
Eric Laurent4e090692015-03-05 15:12:40 -0800741 struct radio_hal_band_config halConfig;
Eric Laurent01d267e2016-10-21 08:16:10 -0700742 status = (status_t)mTuner->getConfiguration(&halConfig);
Eric Laurent4e090692015-03-05 15:12:40 -0800743 if (status == NO_ERROR) {
744 mConfig.band = halConfig;
745 }
746 }
747 *config = mConfig;
748
749 return status;
750}
751
752status_t RadioService::ModuleClient::setMute(bool mute)
753{
754 sp<Module> module;
755 {
756 Mutex::Autolock _l(mLock);
757 ALOGV("%s locked", __FUNCTION__);
Eric Laurent01d267e2016-10-21 08:16:10 -0700758 if (mTuner == 0 || !mAudio) {
Eric Laurent4e090692015-03-05 15:12:40 -0800759 return INVALID_OPERATION;
760 }
761 module = mModule.promote();
762 if (module == 0) {
763 return NO_INIT;
764 }
765 }
766 module->setMute(mute);
767 return NO_ERROR;
768}
769
770status_t RadioService::ModuleClient::getMute(bool *mute)
771{
772 sp<Module> module;
773 {
774 Mutex::Autolock _l(mLock);
775 ALOGV("%s locked", __FUNCTION__);
776 module = mModule.promote();
777 if (module == 0) {
778 return NO_INIT;
779 }
780 }
781 return module->getMute(mute);
782}
783
784status_t RadioService::ModuleClient::scan(radio_direction_t direction, bool skipSubChannel)
785{
786 AutoMutex lock(mLock);
787 ALOGV("%s locked", __FUNCTION__);
788 status_t status;
Eric Laurent01d267e2016-10-21 08:16:10 -0700789 if (mTuner != 0) {
790 status = (status_t)mTuner->scan(direction, skipSubChannel);
Eric Laurent4e090692015-03-05 15:12:40 -0800791 } else {
792 status = INVALID_OPERATION;
793 }
794 return status;
795}
796
797status_t RadioService::ModuleClient::step(radio_direction_t direction, bool skipSubChannel)
798{
799 AutoMutex lock(mLock);
800 ALOGV("%s locked", __FUNCTION__);
801 status_t status;
Eric Laurent01d267e2016-10-21 08:16:10 -0700802 if (mTuner != 0) {
803 status = (status_t)mTuner->step(direction, skipSubChannel);
Eric Laurent4e090692015-03-05 15:12:40 -0800804 } else {
805 status = INVALID_OPERATION;
806 }
807 return status;
808}
809
Eric Laurent01d267e2016-10-21 08:16:10 -0700810status_t RadioService::ModuleClient::tune(uint32_t channel, uint32_t subChannel)
Eric Laurent4e090692015-03-05 15:12:40 -0800811{
812 AutoMutex lock(mLock);
813 ALOGV("%s locked", __FUNCTION__);
814 status_t status;
Eric Laurent01d267e2016-10-21 08:16:10 -0700815 if (mTuner != 0) {
816 status = (status_t)mTuner->tune(channel, subChannel);
Eric Laurent4e090692015-03-05 15:12:40 -0800817 } else {
818 status = INVALID_OPERATION;
819 }
820 return status;
821}
822
823status_t RadioService::ModuleClient::cancel()
824{
825 AutoMutex lock(mLock);
826 ALOGV("%s locked", __FUNCTION__);
827 status_t status;
Eric Laurent01d267e2016-10-21 08:16:10 -0700828 if (mTuner != 0) {
829 status = (status_t)mTuner->cancel();
Eric Laurent4e090692015-03-05 15:12:40 -0800830 } else {
831 status = INVALID_OPERATION;
832 }
833 return status;
834}
835
836status_t RadioService::ModuleClient::getProgramInformation(struct radio_program_info *info)
837{
838 AutoMutex lock(mLock);
839 ALOGV("%s locked", __FUNCTION__);
840 status_t status;
841 if (mTuner != NULL) {
Eric Laurent01d267e2016-10-21 08:16:10 -0700842 status = (status_t)mTuner->getProgramInformation(info);
Eric Laurent4e090692015-03-05 15:12:40 -0800843 } else {
844 status = INVALID_OPERATION;
845 }
846 return status;
847}
848
849status_t RadioService::ModuleClient::hasControl(bool *hasControl)
850{
851 Mutex::Autolock lock(mLock);
852 ALOGV("%s locked", __FUNCTION__);
Eric Laurent01d267e2016-10-21 08:16:10 -0700853 *hasControl = mTuner != 0;
Eric Laurent4e090692015-03-05 15:12:40 -0800854 return NO_ERROR;
855}
856
857void RadioService::ModuleClient::onCallbackEvent(const sp<IMemory>& eventMemory)
858{
859 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
860 return;
861 }
862
863 sp<IRadioClient> client;
864 {
865 AutoMutex lock(mLock);
866 ALOGV("%s locked", __FUNCTION__);
867 radio_event_t *event = (radio_event_t *)eventMemory->pointer();
868 switch (event->type) {
869 case RADIO_EVENT_CONFIG:
870 mConfig.band = event->config.band;
871 event->config.region = mConfig.region;
872 break;
873 default:
874 break;
875 }
876
877 client = mClient;
878 }
879 if (client != 0) {
880 client->onEvent(eventMemory);
881 }
882}
883
884
885void RadioService::ModuleClient::binderDied(
886 const wp<IBinder> &who __unused) {
887 ALOGW("client binder died for client %p", this);
888 detach();
889}
890
891}; // namespace android