blob: f7a73c36fd29b67f0c89f9894741f247f0533f2a [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);
Eric Laurent4e090692015-03-05 15:12:40 -080071 convertProperties(&properties, &halProperties);
Tomasz Wasilczyk164f3682017-02-08 09:18:08 -080072
73 ALOGI("loaded default module %s, ver %s, handle %d", properties.product,
74 properties.version, properties.handle);
75
Eric Laurent53810822015-03-12 09:12:01 -070076 sp<Module> module = new Module(dev, properties);
Eric Laurent4e090692015-03-05 15:12:40 -080077 mModules.add(properties.handle, module);
78}
79
80RadioService::~RadioService()
81{
Eric Laurent4e090692015-03-05 15:12:40 -080082}
83
84status_t RadioService::listModules(struct radio_properties *properties,
85 uint32_t *numModules)
86{
87 ALOGV("listModules");
88
89 AutoMutex lock(mServiceLock);
90 if (numModules == NULL || (*numModules != 0 && properties == NULL)) {
91 return BAD_VALUE;
92 }
Eric Laurent01d267e2016-10-21 08:16:10 -070093 uint32_t maxModules = *numModules;
Eric Laurent4e090692015-03-05 15:12:40 -080094 *numModules = mModules.size();
95 for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
96 properties[i] = mModules.valueAt(i)->properties();
97 }
98 return NO_ERROR;
99}
100
101status_t RadioService::attach(radio_handle_t handle,
102 const sp<IRadioClient>& client,
103 const struct radio_band_config *config,
104 bool withAudio,
105 sp<IRadio>& radio)
106{
107 ALOGV("%s %d config %p withAudio %d", __FUNCTION__, handle, config, withAudio);
108
109 AutoMutex lock(mServiceLock);
110 radio.clear();
111 if (client == 0) {
112 return BAD_VALUE;
113 }
114 ssize_t index = mModules.indexOfKey(handle);
115 if (index < 0) {
116 return BAD_VALUE;
117 }
118 sp<Module> module = mModules.valueAt(index);
119
120 if (config == NULL) {
121 config = module->getDefaultConfig();
122 if (config == NULL) {
123 return INVALID_OPERATION;
124 }
125 }
126 ALOGV("%s region %d type %d", __FUNCTION__, config->region, config->band.type);
127
128 radio = module->addClient(client, config, withAudio);
129
130 if (radio == 0) {
Eric Laurentf2f79cf2015-04-23 17:10:50 -0700131 return NO_INIT;
Eric Laurent4e090692015-03-05 15:12:40 -0800132 }
133 return NO_ERROR;
134}
135
136
137static const int kDumpLockRetries = 50;
138static const int kDumpLockSleep = 60000;
139
140static bool tryLock(Mutex& mutex)
141{
142 bool locked = false;
143 for (int i = 0; i < kDumpLockRetries; ++i) {
144 if (mutex.tryLock() == NO_ERROR) {
145 locked = true;
146 break;
147 }
148 usleep(kDumpLockSleep);
149 }
150 return locked;
151}
152
153status_t RadioService::dump(int fd, const Vector<String16>& args __unused) {
154 String8 result;
155 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
156 result.appendFormat("Permission Denial: can't dump RadioService");
157 write(fd, result.string(), result.size());
158 } else {
159 bool locked = tryLock(mServiceLock);
160 // failed to lock - RadioService is probably deadlocked
161 if (!locked) {
162 result.append("RadioService may be deadlocked\n");
163 write(fd, result.string(), result.size());
164 }
165
166 if (locked) mServiceLock.unlock();
167 }
168 return NO_ERROR;
169}
170
171status_t RadioService::onTransact(
172 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
173 return BnRadioService::onTransact(code, data, reply, flags);
174}
175
176
Eric Laurent4e090692015-03-05 15:12:40 -0800177/* static */
178void RadioService::convertProperties(radio_properties_t *properties,
179 const radio_hal_properties_t *halProperties)
180{
181 memset(properties, 0, sizeof(struct radio_properties));
182 properties->class_id = halProperties->class_id;
183 strlcpy(properties->implementor, halProperties->implementor,
184 RADIO_STRING_LEN_MAX);
185 strlcpy(properties->product, halProperties->product,
186 RADIO_STRING_LEN_MAX);
187 strlcpy(properties->version, halProperties->version,
188 RADIO_STRING_LEN_MAX);
189 strlcpy(properties->serial, halProperties->serial,
190 RADIO_STRING_LEN_MAX);
191 properties->num_tuners = halProperties->num_tuners;
192 properties->num_audio_sources = halProperties->num_audio_sources;
193 properties->supports_capture = halProperties->supports_capture;
194
195 for (size_t i = 0; i < ARRAY_SIZE(sKnownRegionConfigs); i++) {
196 const radio_hal_band_config_t *band = &sKnownRegionConfigs[i].band;
197 size_t j;
198 for (j = 0; j < halProperties->num_bands; j++) {
199 const radio_hal_band_config_t *halBand = &halProperties->bands[j];
200 size_t k;
201 if (band->type != halBand->type) continue;
202 if (band->lower_limit < halBand->lower_limit) continue;
203 if (band->upper_limit > halBand->upper_limit) continue;
204 for (k = 0; k < halBand->num_spacings; k++) {
205 if (band->spacings[0] == halBand->spacings[k]) break;
206 }
207 if (k == halBand->num_spacings) continue;
208 if (band->type == RADIO_BAND_AM) break;
209 if ((band->fm.deemphasis & halBand->fm.deemphasis) == 0) continue;
210 if (halBand->fm.rds == 0) break;
211 if ((band->fm.rds & halBand->fm.rds) != 0) break;
212 }
213 if (j == halProperties->num_bands) continue;
214
215 ALOGI("convertProperties() Adding band type %d region %d",
216 sKnownRegionConfigs[i].band.type , sKnownRegionConfigs[i].region);
217
218 memcpy(&properties->bands[properties->num_bands++],
219 &sKnownRegionConfigs[i],
220 sizeof(radio_band_config_t));
221 }
222}
223
224#undef LOG_TAG
225#define LOG_TAG "RadioService::CallbackThread"
226
227RadioService::CallbackThread::CallbackThread(const wp<ModuleClient>& moduleClient)
228 : mModuleClient(moduleClient), mMemoryDealer(new MemoryDealer(1024 * 1024, "RadioService"))
229{
230}
231
232RadioService::CallbackThread::~CallbackThread()
233{
234 mEventQueue.clear();
235}
236
237void RadioService::CallbackThread::onFirstRef()
238{
239 run("RadioService cbk", ANDROID_PRIORITY_URGENT_AUDIO);
240}
241
242bool RadioService::CallbackThread::threadLoop()
243{
244 while (!exitPending()) {
245 sp<IMemory> eventMemory;
246 sp<ModuleClient> moduleClient;
247 {
248 Mutex::Autolock _l(mCallbackLock);
249 while (mEventQueue.isEmpty() && !exitPending()) {
250 ALOGV("CallbackThread::threadLoop() sleep");
251 mCallbackCond.wait(mCallbackLock);
252 ALOGV("CallbackThread::threadLoop() wake up");
253 }
254 if (exitPending()) {
255 break;
256 }
257 eventMemory = mEventQueue[0];
258 mEventQueue.removeAt(0);
259 moduleClient = mModuleClient.promote();
260 }
261 if (moduleClient != 0) {
262 moduleClient->onCallbackEvent(eventMemory);
263 eventMemory.clear();
264 }
265 }
266 return false;
267}
268
269void RadioService::CallbackThread::exit()
270{
271 Mutex::Autolock _l(mCallbackLock);
272 requestExit();
273 mCallbackCond.broadcast();
274}
275
276sp<IMemory> RadioService::CallbackThread::prepareEvent(radio_hal_event_t *halEvent)
277{
278 sp<IMemory> eventMemory;
279
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700280 // The event layout in shared memory is:
281 // sizeof(struct radio_event) bytes : the event itself
282 // 4 bytes : metadata size or 0
283 // N bytes : metadata if present
284 uint32_t metadataOffset = sizeof(struct radio_event) + sizeof(uint32_t);
285 uint32_t metadataSize = 0;
286
Eric Laurent4e090692015-03-05 15:12:40 -0800287 switch (halEvent->type) {
288 case RADIO_EVENT_TUNED:
289 case RADIO_EVENT_AF_SWITCH:
290 if (radio_metadata_check(halEvent->info.metadata) == 0) {
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700291 metadataSize = (uint32_t)radio_metadata_get_size(halEvent->info.metadata);
Eric Laurent4e090692015-03-05 15:12:40 -0800292 }
293 break;
294 case RADIO_EVENT_METADATA:
295 if (radio_metadata_check(halEvent->metadata) != 0) {
296 return eventMemory;
297 }
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700298 metadataSize = (uint32_t)radio_metadata_get_size(halEvent->metadata);
Eric Laurent4e090692015-03-05 15:12:40 -0800299 break;
300 default:
301 break;
302 }
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700303
304 eventMemory = mMemoryDealer->allocate(metadataOffset + metadataSize);
Eric Laurent4e090692015-03-05 15:12:40 -0800305 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
306 eventMemory.clear();
307 return eventMemory;
308 }
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700309
Eric Laurent4e090692015-03-05 15:12:40 -0800310 struct radio_event *event = (struct radio_event *)eventMemory->pointer();
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700311
312 *(uint32_t *)((uint8_t *)event + metadataOffset - sizeof(uint32_t)) = metadataSize;
313
Eric Laurent4e090692015-03-05 15:12:40 -0800314 event->type = halEvent->type;
315 event->status = halEvent->status;
316
317 switch (event->type) {
318 case RADIO_EVENT_CONFIG:
319 event->config.band = halEvent->config;
320 break;
321 case RADIO_EVENT_TUNED:
322 case RADIO_EVENT_AF_SWITCH:
323 event->info = halEvent->info;
324 if (metadataSize != 0) {
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700325 memcpy((uint8_t *)event + metadataOffset, halEvent->info.metadata, metadataSize);
Eric Laurent4e090692015-03-05 15:12:40 -0800326 }
327 break;
328 case RADIO_EVENT_TA:
Sanket Agarwalf639ba12015-10-12 13:05:53 -0700329 case RADIO_EVENT_EA:
Eric Laurent4e090692015-03-05 15:12:40 -0800330 case RADIO_EVENT_ANTENNA:
331 case RADIO_EVENT_CONTROL:
332 event->on = halEvent->on;
333 break;
334 case RADIO_EVENT_METADATA:
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700335 if (metadataSize != 0) {
336 memcpy((uint8_t *)event + metadataOffset, halEvent->metadata, metadataSize);
337 }
Eric Laurent4e090692015-03-05 15:12:40 -0800338 break;
339 case RADIO_EVENT_HW_FAILURE:
340 default:
341 break;
342 }
343
344 return eventMemory;
345}
346
347void RadioService::CallbackThread::sendEvent(radio_hal_event_t *event)
348 {
349 sp<IMemory> eventMemory = prepareEvent(event);
350 if (eventMemory == 0) {
351 return;
352 }
353
354 AutoMutex lock(mCallbackLock);
355 mEventQueue.add(eventMemory);
356 mCallbackCond.signal();
357 ALOGV("%s DONE", __FUNCTION__);
358}
359
360
361#undef LOG_TAG
362#define LOG_TAG "RadioService::Module"
363
Eric Laurent01d267e2016-10-21 08:16:10 -0700364RadioService::Module::Module(sp<RadioInterface> hwDevice, radio_properties properties)
Eric Laurent53810822015-03-12 09:12:01 -0700365 : mHwDevice(hwDevice), mProperties(properties), mMute(true)
Eric Laurent4e090692015-03-05 15:12:40 -0800366{
367}
368
369RadioService::Module::~Module() {
Eric Laurent01d267e2016-10-21 08:16:10 -0700370 mHwDevice.clear();
Eric Laurent4e090692015-03-05 15:12:40 -0800371 mModuleClients.clear();
372}
373
374status_t RadioService::Module::dump(int fd __unused, const Vector<String16>& args __unused) {
375 String8 result;
376 return NO_ERROR;
377}
378
379sp<RadioService::ModuleClient> RadioService::Module::addClient(const sp<IRadioClient>& client,
380 const struct radio_band_config *config,
381 bool audio)
382{
383 ALOGV("addClient() %p config %p product %s", this, config, mProperties.product);
Eric Laurent01d267e2016-10-21 08:16:10 -0700384
Eric Laurent4e090692015-03-05 15:12:40 -0800385 AutoMutex lock(mLock);
386 sp<ModuleClient> moduleClient;
387 int ret;
388
Eric Laurent01d267e2016-10-21 08:16:10 -0700389 if (mHwDevice == 0) {
390 return moduleClient;
391 }
392
Eric Laurent4e090692015-03-05 15:12:40 -0800393 for (size_t i = 0; i < mModuleClients.size(); i++) {
394 if (mModuleClients[i]->client() == client) {
395 // client already connected: reject
396 return moduleClient;
397 }
398 }
399 moduleClient = new ModuleClient(this, client, config, audio);
400
401 struct radio_hal_band_config halConfig;
402 halConfig = config->band;
403
Eric Laurent53810822015-03-12 09:12:01 -0700404 // Tuner preemption logic:
405 // There is a limited amount of tuners and a limited amount of radio audio sources per module.
406 // The minimum is one tuner and one audio source.
407 // The numbers of tuners and sources are indicated in the module properties.
408 // NOTE: current framework implementation only supports one radio audio source.
409 // It is possible to open more than one tuner at a time but only one tuner can be connected
410 // to the radio audio source (AUDIO_DEVICE_IN_FM_TUNER).
411 // The base rule is that a newly connected tuner always wins, i.e. always gets a tuner
412 // and can use the audio source if requested.
413 // If another client is preempted, it is notified by a callback with RADIO_EVENT_CONTROL
414 // indicating loss of control.
415 // - If the newly connected client requests the audio source (audio == true):
416 // - if an audio source is available
417 // no problem
418 // - if not:
419 // the oldest client in the list using audio is preempted.
420 // - If the newly connected client does not request the audio source (audio == false):
421 // - if a tuner is available
422 // no problem
423 // - if not:
424 // The oldest client not using audio is preempted first and if none is found the
425 // the oldest client using audio is preempted.
426 // Each time a tuner using the audio source is opened or closed, the audio policy manager is
427 // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
428
Eric Laurent4e090692015-03-05 15:12:40 -0800429 sp<ModuleClient> oldestTuner;
430 sp<ModuleClient> oldestAudio;
431 size_t allocatedTuners = 0;
432 size_t allocatedAudio = 0;
433 for (size_t i = 0; i < mModuleClients.size(); i++) {
434 if (mModuleClients[i]->getTuner() != NULL) {
435 if (mModuleClients[i]->audio()) {
436 if (oldestAudio == 0) {
437 oldestAudio = mModuleClients[i];
438 }
439 allocatedAudio++;
440 } else {
441 if (oldestTuner == 0) {
442 oldestTuner = mModuleClients[i];
443 }
444 allocatedTuners++;
445 }
446 }
447 }
448
Eric Laurent01d267e2016-10-21 08:16:10 -0700449 sp<TunerInterface> halTuner;
Eric Laurent53810822015-03-12 09:12:01 -0700450 sp<ModuleClient> preemtedClient;
Eric Laurent4e090692015-03-05 15:12:40 -0800451 if (audio) {
452 if (allocatedAudio >= mProperties.num_audio_sources) {
453 ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
Eric Laurent53810822015-03-12 09:12:01 -0700454 preemtedClient = oldestAudio;
Eric Laurent4e090692015-03-05 15:12:40 -0800455 }
456 } else {
457 if (allocatedAudio + allocatedTuners >= mProperties.num_tuners) {
458 if (allocatedTuners != 0) {
459 ALOG_ASSERT(oldestTuner != 0, "addClient() allocatedTuners/oldestTuner mismatch");
Eric Laurent53810822015-03-12 09:12:01 -0700460 preemtedClient = oldestTuner;
Eric Laurent4e090692015-03-05 15:12:40 -0800461 } else {
462 ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
Eric Laurent53810822015-03-12 09:12:01 -0700463 preemtedClient = oldestAudio;
Eric Laurent4e090692015-03-05 15:12:40 -0800464 }
465 }
466 }
Eric Laurent53810822015-03-12 09:12:01 -0700467 if (preemtedClient != 0) {
468 halTuner = preemtedClient->getTuner();
Eric Laurent01d267e2016-10-21 08:16:10 -0700469 sp<TunerInterface> clear;
470 preemtedClient->setTuner(clear);
471 mHwDevice->closeTuner(halTuner);
Eric Laurent53810822015-03-12 09:12:01 -0700472 if (preemtedClient->audio()) {
473 notifyDeviceConnection(false, "");
474 }
475 }
Eric Laurent4e090692015-03-05 15:12:40 -0800476
Eric Laurent01d267e2016-10-21 08:16:10 -0700477 ret = mHwDevice->openTuner(&halConfig, audio,
478 moduleClient,
479 halTuner);
Eric Laurent4e090692015-03-05 15:12:40 -0800480 if (ret == 0) {
Eric Laurent01d267e2016-10-21 08:16:10 -0700481 ALOGV("addClient() setTuner %p", halTuner.get());
Eric Laurent4e090692015-03-05 15:12:40 -0800482 moduleClient->setTuner(halTuner);
483 mModuleClients.add(moduleClient);
Eric Laurent53810822015-03-12 09:12:01 -0700484 if (audio) {
485 notifyDeviceConnection(true, "");
486 }
Eric Laurentf2f79cf2015-04-23 17:10:50 -0700487 ALOGV("addClient() DONE moduleClient %p", moduleClient.get());
Eric Laurent4e090692015-03-05 15:12:40 -0800488 } else {
Eric Laurentf2f79cf2015-04-23 17:10:50 -0700489 ALOGW("%s open_tuner failed with error %d", __FUNCTION__, ret);
Eric Laurent4e090692015-03-05 15:12:40 -0800490 moduleClient.clear();
491 }
492
Eric Laurent4e090692015-03-05 15:12:40 -0800493 return moduleClient;
494}
495
496void RadioService::Module::removeClient(const sp<ModuleClient>& moduleClient) {
497 ALOGV("removeClient()");
498 AutoMutex lock(mLock);
499 int ret;
500 ssize_t index = -1;
501
502 for (size_t i = 0; i < mModuleClients.size(); i++) {
503 if (mModuleClients[i] == moduleClient) {
504 index = i;
505 break;
506 }
507 }
508 if (index == -1) {
509 return;
510 }
511
512 mModuleClients.removeAt(index);
Eric Laurent01d267e2016-10-21 08:16:10 -0700513 sp<TunerInterface> halTuner = moduleClient->getTuner();
Eric Laurent4e090692015-03-05 15:12:40 -0800514 if (halTuner == NULL) {
515 return;
516 }
517
Eric Laurent01d267e2016-10-21 08:16:10 -0700518 if (mHwDevice != 0) {
519 mHwDevice->closeTuner(halTuner);
520 }
521
Eric Laurent53810822015-03-12 09:12:01 -0700522 if (moduleClient->audio()) {
523 notifyDeviceConnection(false, "");
524 }
Eric Laurent4e090692015-03-05 15:12:40 -0800525
Eric Laurent4e090692015-03-05 15:12:40 -0800526 mMute = true;
527
528 if (mModuleClients.isEmpty()) {
529 return;
530 }
531
Eric Laurent01d267e2016-10-21 08:16:10 -0700532 if (mHwDevice == 0) {
533 return;
534 }
535
Eric Laurent53810822015-03-12 09:12:01 -0700536 // Tuner reallocation logic:
537 // When a client is removed and was controlling a tuner, this tuner will be allocated to a
538 // previously preempted client. This client will be notified by a callback with
539 // RADIO_EVENT_CONTROL indicating gain of control.
540 // - If a preempted client is waiting for an audio source and one becomes available:
541 // Allocate the tuner to the most recently added client waiting for an audio source
542 // - If not:
543 // Allocate the tuner to the most recently added client.
544 // Each time a tuner using the audio source is opened or closed, the audio policy manager is
545 // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
546
Eric Laurent4e090692015-03-05 15:12:40 -0800547 sp<ModuleClient> youngestClient;
548 sp<ModuleClient> youngestClientAudio;
549 size_t allocatedTuners = 0;
550 size_t allocatedAudio = 0;
Eric Laurent53810822015-03-12 09:12:01 -0700551 for (ssize_t i = mModuleClients.size() - 1; i >= 0; i--) {
Eric Laurent4e090692015-03-05 15:12:40 -0800552 if (mModuleClients[i]->getTuner() == NULL) {
553 if (mModuleClients[i]->audio()) {
554 if (youngestClientAudio == 0) {
555 youngestClientAudio = mModuleClients[i];
556 }
557 } else {
558 if (youngestClient == 0) {
559 youngestClient = mModuleClients[i];
560 }
561 }
562 } else {
563 if (mModuleClients[i]->audio()) {
564 allocatedAudio++;
565 } else {
566 allocatedTuners++;
567 }
568 }
569 }
570
571 ALOG_ASSERT(allocatedTuners + allocatedAudio < mProperties.num_tuners,
572 "removeClient() removed client but no tuner available");
573
574 ALOG_ASSERT(!moduleClient->audio() || allocatedAudio < mProperties.num_audio_sources,
575 "removeClient() removed audio client but no tuner with audio available");
576
577 if (allocatedAudio < mProperties.num_audio_sources && youngestClientAudio != 0) {
578 youngestClient = youngestClientAudio;
579 }
580
581 ALOG_ASSERT(youngestClient != 0, "removeClient() removed client no candidate found for tuner");
582
583 struct radio_hal_band_config halConfig = youngestClient->halConfig();
Eric Laurent01d267e2016-10-21 08:16:10 -0700584 ret = mHwDevice->openTuner(&halConfig, youngestClient->audio(),
585 moduleClient,
586 halTuner);
Eric Laurent4e090692015-03-05 15:12:40 -0800587
Eric Laurent4e090692015-03-05 15:12:40 -0800588 if (ret == 0) {
589 youngestClient->setTuner(halTuner);
Eric Laurent53810822015-03-12 09:12:01 -0700590 if (youngestClient->audio()) {
591 notifyDeviceConnection(true, "");
592 }
Eric Laurent4e090692015-03-05 15:12:40 -0800593 }
594}
595
596status_t RadioService::Module::setMute(bool mute)
597{
598 Mutex::Autolock _l(mLock);
599 if (mute != mMute) {
600 mMute = mute;
601 //TODO notifify audio policy manager of media activity on radio audio device
602 }
603 return NO_ERROR;
604}
605
606status_t RadioService::Module::getMute(bool *mute)
607{
608 Mutex::Autolock _l(mLock);
609 *mute = mMute;
610 return NO_ERROR;
611}
612
613
614const struct radio_band_config *RadioService::Module::getDefaultConfig() const
615{
616 if (mProperties.num_bands == 0) {
617 return NULL;
618 }
619 return &mProperties.bands[0];
620}
621
Eric Laurent53810822015-03-12 09:12:01 -0700622void RadioService::Module::notifyDeviceConnection(bool connected,
623 const char *address) {
624 int64_t token = IPCThreadState::self()->clearCallingIdentity();
625 AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_FM_TUNER,
626 connected ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE :
627 AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
628 address, kRadioTunerAudioDeviceName);
629 IPCThreadState::self()->restoreCallingIdentity(token);
630}
631
Eric Laurent4e090692015-03-05 15:12:40 -0800632#undef LOG_TAG
633#define LOG_TAG "RadioService::ModuleClient"
634
635RadioService::ModuleClient::ModuleClient(const sp<Module>& module,
636 const sp<IRadioClient>& client,
637 const struct radio_band_config *config,
638 bool audio)
Eric Laurent01d267e2016-10-21 08:16:10 -0700639 : mModule(module), mClient(client), mConfig(*config), mAudio(audio), mTuner(0)
Eric Laurent4e090692015-03-05 15:12:40 -0800640{
641}
642
643void RadioService::ModuleClient::onFirstRef()
644{
645 mCallbackThread = new CallbackThread(this);
646 IInterface::asBinder(mClient)->linkToDeath(this);
647}
648
649RadioService::ModuleClient::~ModuleClient() {
650 if (mClient != 0) {
651 IInterface::asBinder(mClient)->unlinkToDeath(this);
652 mClient.clear();
653 }
654 if (mCallbackThread != 0) {
655 mCallbackThread->exit();
656 }
657}
658
Eric Laurent01d267e2016-10-21 08:16:10 -0700659void RadioService::ModuleClient::onEvent(radio_hal_event_t *halEvent)
660{
661 mCallbackThread->sendEvent(halEvent);
662}
663
Eric Laurent4e090692015-03-05 15:12:40 -0800664status_t RadioService::ModuleClient::dump(int fd __unused,
665 const Vector<String16>& args __unused) {
666 String8 result;
667 return NO_ERROR;
668}
669
670void RadioService::ModuleClient::detach() {
671 ALOGV("%s", __FUNCTION__);
672 sp<ModuleClient> strongMe = this;
673 {
674 AutoMutex lock(mLock);
675 if (mClient != 0) {
676 IInterface::asBinder(mClient)->unlinkToDeath(this);
677 mClient.clear();
678 }
679 }
680 sp<Module> module = mModule.promote();
681 if (module == 0) {
682 return;
683 }
684 module->removeClient(this);
685}
686
687radio_hal_band_config_t RadioService::ModuleClient::halConfig() const
688{
689 AutoMutex lock(mLock);
690 ALOGV("%s locked", __FUNCTION__);
691 return mConfig.band;
692}
693
Eric Laurent01d267e2016-10-21 08:16:10 -0700694sp<TunerInterface>& RadioService::ModuleClient::getTuner()
Eric Laurent4e090692015-03-05 15:12:40 -0800695{
696 AutoMutex lock(mLock);
697 ALOGV("%s locked", __FUNCTION__);
698 return mTuner;
699}
700
Eric Laurent01d267e2016-10-21 08:16:10 -0700701void RadioService::ModuleClient::setTuner(sp<TunerInterface>& tuner)
Eric Laurent4e090692015-03-05 15:12:40 -0800702{
703 ALOGV("%s %p", __FUNCTION__, this);
704
705 AutoMutex lock(mLock);
706 mTuner = tuner;
707 ALOGV("%s locked", __FUNCTION__);
708
709 radio_hal_event_t event;
710 event.type = RADIO_EVENT_CONTROL;
711 event.status = 0;
Eric Laurent01d267e2016-10-21 08:16:10 -0700712 event.on = mTuner != 0;
Eric Laurent4e090692015-03-05 15:12:40 -0800713 mCallbackThread->sendEvent(&event);
714 ALOGV("%s DONE", __FUNCTION__);
715
716}
717
718status_t RadioService::ModuleClient::setConfiguration(const struct radio_band_config *config)
719{
720 AutoMutex lock(mLock);
721 status_t status = NO_ERROR;
722 ALOGV("%s locked", __FUNCTION__);
723
Eric Laurent01d267e2016-10-21 08:16:10 -0700724 if (mTuner != 0) {
Eric Laurent4e090692015-03-05 15:12:40 -0800725 struct radio_hal_band_config halConfig;
726 halConfig = config->band;
Eric Laurent01d267e2016-10-21 08:16:10 -0700727 status = (status_t)mTuner->setConfiguration(&halConfig);
Eric Laurent4e090692015-03-05 15:12:40 -0800728 if (status == NO_ERROR) {
729 mConfig = *config;
730 }
731 } else {
732 mConfig = *config;
Aurimas Liutikas13958742016-02-18 10:02:35 -0800733 status = INVALID_OPERATION;
Eric Laurent4e090692015-03-05 15:12:40 -0800734 }
735
736 return status;
737}
738
739status_t RadioService::ModuleClient::getConfiguration(struct radio_band_config *config)
740{
741 AutoMutex lock(mLock);
742 status_t status = NO_ERROR;
743 ALOGV("%s locked", __FUNCTION__);
744
Eric Laurent01d267e2016-10-21 08:16:10 -0700745 if (mTuner != 0) {
Eric Laurent4e090692015-03-05 15:12:40 -0800746 struct radio_hal_band_config halConfig;
Eric Laurent01d267e2016-10-21 08:16:10 -0700747 status = (status_t)mTuner->getConfiguration(&halConfig);
Eric Laurent4e090692015-03-05 15:12:40 -0800748 if (status == NO_ERROR) {
749 mConfig.band = halConfig;
750 }
751 }
752 *config = mConfig;
753
754 return status;
755}
756
757status_t RadioService::ModuleClient::setMute(bool mute)
758{
759 sp<Module> module;
760 {
761 Mutex::Autolock _l(mLock);
762 ALOGV("%s locked", __FUNCTION__);
Eric Laurent01d267e2016-10-21 08:16:10 -0700763 if (mTuner == 0 || !mAudio) {
Eric Laurent4e090692015-03-05 15:12:40 -0800764 return INVALID_OPERATION;
765 }
766 module = mModule.promote();
767 if (module == 0) {
768 return NO_INIT;
769 }
770 }
771 module->setMute(mute);
772 return NO_ERROR;
773}
774
775status_t RadioService::ModuleClient::getMute(bool *mute)
776{
777 sp<Module> module;
778 {
779 Mutex::Autolock _l(mLock);
780 ALOGV("%s locked", __FUNCTION__);
781 module = mModule.promote();
782 if (module == 0) {
783 return NO_INIT;
784 }
785 }
786 return module->getMute(mute);
787}
788
789status_t RadioService::ModuleClient::scan(radio_direction_t direction, bool skipSubChannel)
790{
791 AutoMutex lock(mLock);
792 ALOGV("%s locked", __FUNCTION__);
793 status_t status;
Eric Laurent01d267e2016-10-21 08:16:10 -0700794 if (mTuner != 0) {
795 status = (status_t)mTuner->scan(direction, skipSubChannel);
Eric Laurent4e090692015-03-05 15:12:40 -0800796 } else {
797 status = INVALID_OPERATION;
798 }
799 return status;
800}
801
802status_t RadioService::ModuleClient::step(radio_direction_t direction, bool skipSubChannel)
803{
804 AutoMutex lock(mLock);
805 ALOGV("%s locked", __FUNCTION__);
806 status_t status;
Eric Laurent01d267e2016-10-21 08:16:10 -0700807 if (mTuner != 0) {
808 status = (status_t)mTuner->step(direction, skipSubChannel);
Eric Laurent4e090692015-03-05 15:12:40 -0800809 } else {
810 status = INVALID_OPERATION;
811 }
812 return status;
813}
814
Eric Laurent01d267e2016-10-21 08:16:10 -0700815status_t RadioService::ModuleClient::tune(uint32_t channel, uint32_t subChannel)
Eric Laurent4e090692015-03-05 15:12:40 -0800816{
817 AutoMutex lock(mLock);
818 ALOGV("%s locked", __FUNCTION__);
819 status_t status;
Eric Laurent01d267e2016-10-21 08:16:10 -0700820 if (mTuner != 0) {
821 status = (status_t)mTuner->tune(channel, subChannel);
Eric Laurent4e090692015-03-05 15:12:40 -0800822 } else {
823 status = INVALID_OPERATION;
824 }
825 return status;
826}
827
828status_t RadioService::ModuleClient::cancel()
829{
830 AutoMutex lock(mLock);
831 ALOGV("%s locked", __FUNCTION__);
832 status_t status;
Eric Laurent01d267e2016-10-21 08:16:10 -0700833 if (mTuner != 0) {
834 status = (status_t)mTuner->cancel();
Eric Laurent4e090692015-03-05 15:12:40 -0800835 } else {
836 status = INVALID_OPERATION;
837 }
838 return status;
839}
840
841status_t RadioService::ModuleClient::getProgramInformation(struct radio_program_info *info)
842{
843 AutoMutex lock(mLock);
844 ALOGV("%s locked", __FUNCTION__);
845 status_t status;
846 if (mTuner != NULL) {
Eric Laurent01d267e2016-10-21 08:16:10 -0700847 status = (status_t)mTuner->getProgramInformation(info);
Eric Laurent4e090692015-03-05 15:12:40 -0800848 } else {
849 status = INVALID_OPERATION;
850 }
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700851
Eric Laurent4e090692015-03-05 15:12:40 -0800852 return status;
853}
854
855status_t RadioService::ModuleClient::hasControl(bool *hasControl)
856{
857 Mutex::Autolock lock(mLock);
858 ALOGV("%s locked", __FUNCTION__);
Eric Laurent01d267e2016-10-21 08:16:10 -0700859 *hasControl = mTuner != 0;
Eric Laurent4e090692015-03-05 15:12:40 -0800860 return NO_ERROR;
861}
862
863void RadioService::ModuleClient::onCallbackEvent(const sp<IMemory>& eventMemory)
864{
865 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
866 return;
867 }
868
869 sp<IRadioClient> client;
870 {
871 AutoMutex lock(mLock);
872 ALOGV("%s locked", __FUNCTION__);
873 radio_event_t *event = (radio_event_t *)eventMemory->pointer();
874 switch (event->type) {
875 case RADIO_EVENT_CONFIG:
876 mConfig.band = event->config.band;
877 event->config.region = mConfig.region;
878 break;
879 default:
880 break;
881 }
882
883 client = mClient;
884 }
885 if (client != 0) {
886 client->onEvent(eventMemory);
887 }
888}
889
890
891void RadioService::ModuleClient::binderDied(
892 const wp<IBinder> &who __unused) {
893 ALOGW("client binder died for client %p", this);
894 detach();
895}
896
897}; // namespace android