1 AudioFlingerクラスを作成する
AudioFlinger は、audioserver プロセスの開始時に次のように構築および初期化されます。
int main(int argc __unused, char **argv)
{
...
AudioFlinger::instantiate();
...
}
1.1 AudioFlingerはBinderServiceを継承した派生クラスであり、BinderServiceのデータメンバとメンバ関数を継承しています。AudioFlinger::instantiate() は、実際には BinderService::instantiate() 関数を呼び出し、最後にpublish() 関数を呼び出します。
template<typename SERVICE>
class BinderService
{
public:
static status_t publish(bool allowIsolated = false,
int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,
dumpFlags);
}
...
static void instantiate() { publish(); }
..
};
1.2 sp<IServiceManager> sm(defaultServiceManager()) を通じて IServiceManager オブジェクトを取得します。これは、ServiceManager と通信し、AudioFlinger サービスを登録するためです。デザインはシングルトンパターンを採用。
1.3 addService 関数は、Binder サービスを登録するために使用されます。
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated = false,
int dumpsysFlags = DUMP_FLAG_PRIORITY_DEFAULT) = 0;
sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,
dumpFlags)
1.4 バインダーサービス名:SERVICE::getServiceName(),AudioFlinger::getServiceName()
static const char* getServiceName() ANDROID_API { return "media.audio_flinger"; }
1.5 new SERVICE()、テンプレート クラス、new AudioFlinger() と同等。クラスが作成されると、そのコンストラクターが呼び出されます。
1.6 AudioFlinger を addService 関数の const sp<IBinder>& サービス パラメータとして渡し、それを強参照ポインタとして定義します。最初に参照されると、その onFirstRef 関数が呼び出されます。
2 AudioFlinger::AudioFlinger() コンストラクター
AudioFlinger::AudioFlinger()
: BnAudioFlinger(), //
mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
mPrimaryHardwareDev(NULL),
mAudioHwDevs(NULL),
...
{
..
//2.2
mDevicesFactoryHal = DevicesFactoryHalInterface::create();
//2.3
mEffectsFactoryHal = EffectsFactoryHalInterface::create();
...
}
2.1 メンバーの初期化
BnAudioFlinger
基本クラスのデフォルトのコンストラクターを呼び出します。mMediaLogNotifier、mPrimaryHardwareDev、mAudioHwDevs などのメンバー変数の初期化。
2.2 オーディオ HAL との接続を確立してデバイスを開く機能を取得する
mDevicesFactoryHal = DevicesFactoryHalInterface::create() 、名前から大まかに 2 つの情報がわかります。関数は HAL デバイスを開くことに関連している必要があり、DevicesFactoryHalInterface は、mDevicesFactoryHal を作成するために create メソッドを呼び出す Factory ファクトリ クラスです。コード呼び出しプロセスは次のとおりです。
// frameworks/av/media/libaudiohal/DevicesFactoryHalInterface.cpp
//根据IDevicesFactory的版本(HAL provider进程 android.hardware.audio)调用createDevicesFactoryHal,其实最终是同一个函数。
sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
if (hardware::audio::V5_0::IDevicesFactory::getService() != nullptr) {
return V5_0::createDevicesFactoryHal();
}
if (hardware::audio::V4_0::IDevicesFactory::getService() != nullptr) {
return V4_0::createDevicesFactoryHal();
}
if (hardware::audio::V2_0::IDevicesFactory::getService() != nullptr) {
return V2_0::createDevicesFactoryHal();
}
return nullptr;
}
//DevicesFactoryHalHybrid.h frameworks\av\media\libaudiohal\impl
sp<DevicesFactoryHalInterface> createDevicesFactoryHal() {
return new DevicesFactoryHalHybrid();
}
上記のコードから、 mDevicesFactoryHalHybrid クラスが実際に作成されていることがわかります: mDevicesFactoryHal = new DevicesFactoryHalHybrid()。これまでのところ、Audio HAL との関連付けを確認して、DevicesFactoryHalHybrid クラスのコンストラクターを分析することはできません。
DevicesFactoryHalHybrid.cpp frameworks\av\media\libaudiohal\impl
DevicesFactoryHalHybrid::DevicesFactoryHalHybrid()
: mLocalFactory(new DevicesFactoryHalLocal()),
mHidlFactory(new DevicesFactoryHalHidl()) {
}
DevicesFactoryHalHybrid.cpp frameworks\av\media\libaudiohal\impl
status_t DevicesFactoryHalHybrid::openDevice(const char *name, sp<DeviceHalInterface> *device) {
if (mHidlFactory != 0 && strcmp(AUDIO_HARDWARE_MODULE_ID_A2DP, name) != 0 &&
strcmp(AUDIO_HARDWARE_MODULE_ID_HEARING_AID, name) != 0) {
return mHidlFactory->openDevice(name, device);
}
return mLocalFactory->openDevice(name, device);
}
2.2.1 新しい DevicesFactoryHalLocal() と新しい DevicesFactoryHalHidl() は、mLocalFactory と mHidlFactory という 2 つのクラスを作成します。
2.2.2 mLocalFactory、DevicesFactoryHalLocal::openDevice は、load_audio_interface を呼び出してオーディオ HAL ライブラリ ファイルをローカル (現在のプロセス) で開き、オーディオ HAL の audio_hw_device_t 構造体を取得して、それを DeviceHalLocal クラスにカプセル化します。これにより、AudioFlinger は、オーディオ装置。
2.2.3 mHidlFactory は、HAL ライブラリをローカルに直接ロードしませんが、HIDL を介してクロスプロセス呼び出しを行います。DevicesFactoryHalHidl コンストラクターは次のとおりです。
DevicesFactoryHalHidl::DevicesFactoryHalHidl() {
//1 defaultFactory函数定义,获得IDevicesFactory对象
sp<IDevicesFactory> defaultFactory{IDevicesFactory::getService()};
if (!defaultFactory) {
ALOGE("Failed to obtain IDevicesFactory/default service, terminating process.");
exit(1);
}
//2 获得IDevicesFactory对象,并保存在mDeviceFactories,使当前类具备与DevicesFactory通信的能力
mDeviceFactories.push_back(defaultFactory);
if (MAJOR_VERSION >= 4) {
// The MSD factory is optional and only available starting at HAL 4.0
sp<IDevicesFactory> msdFactory{IDevicesFactory::getService(AUDIO_HAL_SERVICE_NAME_MSD)};
if (msdFactory) {
mDeviceFactories.push_back(msdFactory);
}
}
for (const auto& factory : mDeviceFactories) {
// It is assumed that the DevicesFactoryHalInterface instance is owned
// by AudioFlinger and thus have the same lifespan.
factory->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
}
}
DevicesFactoryHalHidl::openDevice は、HIDL を通じて IDevice を取得し、それを DeviceHalHidl クラスにカプセル化します。これにより、AudioFlinger がオーディオ デバイスを制御できるようになります。関係の概略図は次のとおりです。
audioserver [email protected]
_____________________________ _______________________
| | | |
| +----------------------+ | | +------------------+ |
| |DevicesFactoryHalHIDL +------IDevicesFactory-->| DevicesFactory | |
| +----------------------+ | openDevice | +---+--------------+ |
| | | | |
| +----------------------+ | |______|________________|
| |DevicesFactoryHalLocal| | |
| +---------------------++ | |
|________________________|____| | openDevice
DevicesFactoryHalHybrid | |
mDevicesFactoryHal | openDevice |
AudioFlinger | |
+--+------+ +----+----+
|Auido HAL| |Auido HAL|
+---------+ +---------+
————————————————————————————————————————————————————————————————————————————————————
______________________________________________________________________
| HW Binder(Linux Kernel) |
|_____________________________________________________________________|
2.2.4 a2dp およびHearing_Aid Audio HAL を開く場合は DevicesFactoryHalLocal を使用し、それ以外の場合は DevicesFactoryHalHidl を使用します。
概要: mDevicesFactoryHal = DevicesFactoryHalInterface::create() 呼び出しは、AudioFlinger と Audio HAL の間の接続を確立します。AudioFlinger は、mDevicesFactoryHal メンバーを通じて Audio HAL を開いて、オーディオ デバイスを制御する機能を取得できます。この時点では、AudioFlinger はまだ Audio を開いていないことに注意してください。ステージ、HAL。
2.3 AudioEffect サウンド制御チャネルの確立
Android は、一連のオーディオ処理フレームワーク Android Audio Effect を提供します。これにより、開発者はイコライザー、ステレオ エンハンサー、リバーブなどのさまざまなオーディオ エフェクトをアプリケーションに簡単に追加できます。Audio HAL と同様に、オーディオ エフェクト アルゴリズムもライブラリの形式でロードされます。
mEffectsFactoryHal = EffectsFactoryHalInterface::create()呼び出しプロセスは DevicesFactoryHalInterface とほぼ同様です。
EffectsFactoryHalInterface.cpp frameworks\av\media\libaudiohal
sp<EffectsFactoryHalInterface> EffectsFactoryHalInterface::create() {
if (hardware::audio::effect::V5_0::IEffectsFactory::getService() != nullptr) {
return effect::V5_0::createEffectsFactoryHal();
}
if (hardware::audio::effect::V4_0::IEffectsFactory::getService() != nullptr) {
return effect::V4_0::createEffectsFactoryHal();
}
if (hardware::audio::effect::V2_0::IEffectsFactory::getService() != nullptr) {
return effect::V2_0::createEffectsFactoryHal();
}
return nullptr;
}
EffectsFactoryHalHidl.h frameworks\av\media\libaudiohal\impl
sp<EffectsFactoryHalInterface> createEffectsFactoryHal() {
return new EffectsFactoryHalHidl();
}
mEffectsFactoryHal = new EffectsFactoryHalHidl();と同等です。
2.3.1 EffectsFactoryHalHidl コンストラクター
EffectsFactoryHalHidl::EffectsFactoryHalHidl() : ConversionHelperHidl("EffectsFactory") {
//获得IEffectsFactory对象,建立与EffectsFactory通信的通道
mEffectsFactory = IEffectsFactory::getService();
if (mEffectsFactory == 0) {
ALOGE("Failed to obtain IEffectsFactory service, terminating process.");
exit(1);
}
}
2.3.2 EffectsFactory Binder サービスも [email protected] プロセス空間にあり、関係図は次のとおりです。
audioserver [email protected]
_____________________________ _______________________
| | | |
| +----------------------+ | | +------------------+|
| |EffectsFactoryHalHidl +------IEffectsFactory-->| EffectsFactory ||
| +----------------------+ | | +-----------+------+|
| | | | |
|_____________________________| |______________|_______|
mEffectsFactoryHal createEffect/queryAllDescriptors/.. |
AudioFlinger |
+------+---+
|libeffects|
+----------+
—————————————————————————————————————————————————————————————————————————————
+----------------------------------------------------------------------+
| HW Binder(Linux Kernel) |
+----------------------------------------------------------------------+
3 AudioFlinger::onFirstRef() 関数
static const nsecs_t kDefaultStandbyTimeInNsecs = seconds(3);
void AudioFlinger::onFirstRef()
{
...
char val_str[PROPERTY_VALUE_MAX] = { 0 };
if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) {
uint32_t int_val;
if (1 == sscanf(val_str, "%u", &int_val)) {
mStandbyTimeInNsecs = milliseconds(int_val);
ALOGI("Using %u mSec as standby time.", int_val);
} else {
mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
ALOGI("Using default %u mSec as standby time.",
(uint32_t)(mStandbyTimeInNsecs / 1000000));
}
}
...
}
mStandbyTimeInNsecs が初期化され、property_get() 関数を呼び出してシステム プロパティから「ro.audio.flinger_standbytime_ms」プロパティの値が取得されます。値を取得できる場合は、それを mStandbyTimeInNsecs に割り当てます。それ以外の場合は、デフォルト値の mStandbyTimeInNsecs (3 秒) を使用します。
再生スレッドが mStandbyTimeInNsecs の期間内にクライアント (オーディオトラック) からデータを受信しない場合にのみ、スタンバイ コマンドをオーディオ HAL に送信し、オーディオ ループ全体の終了を制御します。