blob: 49feda6da5150cde28491c3ecc1bf8834c153f9c [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_HARDWARE_RADIO_SERVICE_H
#define ANDROID_HARDWARE_RADIO_SERVICE_H
#include <utils/Vector.h>
//#include <binder/AppOpsManager.h>
#include <binder/MemoryDealer.h>
#include <binder/BinderService.h>
#include <binder/IAppOpsCallback.h>
#include <radio/IRadioService.h>
#include <radio/IRadio.h>
#include <radio/IRadioClient.h>
#include <system/radio.h>
#include <hardware/radio.h>
namespace android {
class MemoryHeapBase;
class RadioService :
public BinderService<RadioService>,
public BnRadioService
{
friend class BinderService<RadioService>;
public:
class ModuleClient;
class Module;
static char const* getServiceName() { return "media.radio"; }
RadioService();
virtual ~RadioService();
// IRadioService
virtual status_t listModules(struct radio_properties *properties,
uint32_t *numModules);
virtual status_t attach(radio_handle_t handle,
const sp<IRadioClient>& client,
const struct radio_band_config *config,
bool withAudio,
sp<IRadio>& radio);
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);
virtual status_t dump(int fd, const Vector<String16>& args);
class Module : public virtual RefBase {
public:
Module(radio_hw_device* hwDevice,
struct radio_properties properties);
virtual ~Module();
sp<ModuleClient> addClient(const sp<IRadioClient>& client,
const struct radio_band_config *config,
bool audio);
void removeClient(const sp<ModuleClient>& moduleClient);
status_t setMute(bool mute);
status_t getMute(bool *mute);
virtual status_t dump(int fd, const Vector<String16>& args);
const struct radio_hw_device *hwDevice() const { return mHwDevice; }
const struct radio_properties properties() const { return mProperties; }
const struct radio_band_config *getDefaultConfig() const ;
private:
void notifyDeviceConnection(bool connected, const char *address);
Mutex mLock; // protects mModuleClients
const struct radio_hw_device *mHwDevice; // HAL hardware device
const struct radio_properties mProperties; // cached hardware module properties
Vector< sp<ModuleClient> > mModuleClients; // list of attached clients
bool mMute; // radio audio source state
// when unmuted, audio is routed to the
// output device selected for media use case.
}; // class Module
class CallbackThread : public Thread {
public:
CallbackThread(const wp<ModuleClient>& moduleClient);
virtual ~CallbackThread();
// Thread virtuals
virtual bool threadLoop();
// RefBase
virtual void onFirstRef();
void exit();
void sendEvent(radio_hal_event_t *halEvent);
sp<IMemory> prepareEvent(radio_hal_event_t *halEvent);
private:
wp<ModuleClient> mModuleClient; // client module the thread belongs to
Condition mCallbackCond; // condition signaled when a new event is posted
Mutex mCallbackLock; // protects mEventQueue
Vector< sp<IMemory> > mEventQueue; // pending callback events
sp<MemoryDealer> mMemoryDealer; // shared memory for callback event
}; // class CallbackThread
class ModuleClient : public BnRadio,
public IBinder::DeathRecipient {
public:
ModuleClient(const sp<Module>& module,
const sp<IRadioClient>& client,
const struct radio_band_config *config,
bool audio);
virtual ~ModuleClient();
// IRadio
virtual void detach();
virtual status_t setConfiguration(const struct radio_band_config *config);
virtual status_t getConfiguration(struct radio_band_config *config);
virtual status_t setMute(bool mute);
virtual status_t getMute(bool *mute);
virtual status_t scan(radio_direction_t direction, bool skipSubChannel);
virtual status_t step(radio_direction_t direction, bool skipSubChannel);
virtual status_t tune(unsigned int channel, unsigned int subChannel);
virtual status_t cancel();
virtual status_t getProgramInformation(struct radio_program_info *info);
virtual status_t hasControl(bool *hasControl);
virtual status_t dump(int fd, const Vector<String16>& args);
sp<IRadioClient> client() const { return mClient; }
wp<Module> module() const { return mModule; }
radio_hal_band_config_t halConfig() const;
sp<CallbackThread> callbackThread() const { return mCallbackThread; }
void setTuner(const struct radio_tuner *tuner);
const struct radio_tuner *getTuner() const;
bool audio() const { return mAudio; }
void onCallbackEvent(const sp<IMemory>& event);
virtual void onFirstRef();
// IBinder::DeathRecipient implementation
virtual void binderDied(const wp<IBinder> &who);
private:
mutable Mutex mLock; // protects mClient, mConfig and mTuner
wp<Module> mModule; // The module this client is attached to
sp<IRadioClient> mClient; // event callback binder interface
radio_band_config_t mConfig; // current band configuration
sp<CallbackThread> mCallbackThread; // event callback thread
const bool mAudio;
const struct radio_tuner *mTuner; // HAL tuner interface. NULL indicates that
// this client does not have control on any
// tuner
}; // class ModuleClient
static void callback(radio_hal_event_t *halEvent, void *cookie);
private:
virtual void onFirstRef();
static void convertProperties(radio_properties_t *properties,
const radio_hal_properties_t *halProperties);
Mutex mServiceLock; // protects mModules
volatile int32_t mNextUniqueId; // for module ID allocation
DefaultKeyedVector< radio_handle_t, sp<Module> > mModules;
};
} // namespace android
#endif // ANDROID_HARDWARE_RADIO_SERVICE_H