/* * Copyright (C) 2022 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. */ #include #include #include #include #define LOG_TAG "AHAL_Main" #include #include #include #include #include // alsa/global.h defines ATTRIBUTE_UNUSED with slightly different whitespace than // android-base/macros.h, triggering -Wmacro-redefined. Guard around it. #pragma push_macro("ATTRIBUTE_UNUSED") #undef ATTRIBUTE_UNUSED #include #pragma pop_macro("ATTRIBUTE_UNUSED") #include "core-impl/AudioPolicyConfigXmlConverter.h" #include "core-impl/ChildInterface.h" #include "core-impl/Config.h" #include "core-impl/Module.h" using aidl::android::hardware::audio::core::ChildInterface; using aidl::android::hardware::audio::core::Config; using aidl::android::hardware::audio::core::Module; using aidl::android::hardware::audio::core::internal::AudioPolicyConfigXmlConverter; namespace { ChildInterface createModule(const std::string& name, std::unique_ptr&& config) { ChildInterface result; { auto moduleType = Module::typeFromString(name); if (!moduleType.has_value()) { LOG(ERROR) << __func__ << ": module type \"" << name << "\" is not supported"; return result; } auto module = Module::createInstance(*moduleType, std::move(config)); if (module == nullptr) return result; result = std::move(module); } const std::string moduleFqn = std::string().append(Module::descriptor).append("/").append(name); binder_status_t status = AServiceManager_addService(result.getBinder(), moduleFqn.c_str()); if (status != STATUS_OK) { LOG(ERROR) << __func__ << ": failed to register service for \"" << moduleFqn << "\""; return ChildInterface(); } return result; }; } // namespace int main() { // Random values are used in the implementation. std::srand(std::time(nullptr)); // This is a debug implementation, always enable debug logging. android::base::SetMinimumLogSeverity(::android::base::DEBUG); // For more logs, use VERBOSE, however this may hinder performance. // android::base::SetMinimumLogSeverity(::android::base::VERBOSE); ABinderProcess_setThreadPoolMaxThreadCount(16); ABinderProcess_startThreadPool(); // Guaranteed log for b/210919187 and logd_integration_test LOG(INFO) << "Init for Audio AIDL HAL"; // Pre-warm the vc4-hdmi ALSA PCM before registering binder services. // The first snd_pcm_open("default:CARD=vc4hdmiX") blocks 5+ seconds while // the vc4-hdmi driver initialises, tripping AudioFlinger's 5 s TimeCheck // watchdog on IAudioFlinger::createTrack and crashing audioserver in a loop. // Doing it here — before any IModule service is registered — ensures the // driver is ready before audioserver can issue its first createTrack. { const std::string hdmiDev = android::base::GetProperty("persist.vendor.audio.device", "hdmi0"); if (hdmiDev == "hdmi0" || hdmiDev == "hdmi1") { const std::string pcmName = std::string("default:CARD=vc4") + hdmiDev; LOG(INFO) << "Pre-warming ALSA device: " << pcmName; snd_pcm_t* pcm = nullptr; if (snd_pcm_open(&pcm, pcmName.c_str(), SND_PCM_STREAM_PLAYBACK, 0) == 0) { snd_pcm_close(pcm); LOG(INFO) << "ALSA pre-warm complete"; } else { LOG(WARNING) << "ALSA pre-warm: could not open " << pcmName << " (non-fatal)"; } } } AudioPolicyConfigXmlConverter audioPolicyConverter{ ::android::audio_get_audio_policy_config_file()}; // Make the default config service auto config = ndk::SharedRefBase::make(audioPolicyConverter); const std::string configFqn = std::string().append(Config::descriptor).append("/default"); binder_status_t status = AServiceManager_addService(config->asBinder().get(), configFqn.c_str()); if (status != STATUS_OK) { LOG(ERROR) << "failed to register service for \"" << configFqn << "\""; } // Make modules std::vector> moduleInstances; auto configs(audioPolicyConverter.releaseModuleConfigs()); for (std::pair>& configPair : *configs) { std::string name = configPair.first; if (auto instance = createModule(name, std::move(configPair.second)); instance) { moduleInstances.push_back(std::move(instance)); } } ABinderProcess_joinThreadPool(); return EXIT_FAILURE; // should not reach }