Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 52800b19 authored by Andy Hung's avatar Andy Hung Committed by Android (Google) Code Review
Browse files

Merge "AudioSystem: Move AudioFlinger fetch to ServiceHandler" into main

parents 71bc3daf da1fb07e
Loading
Loading
Loading
Loading
+143 −83
Original line number Diff line number Diff line
@@ -66,10 +66,6 @@ using media::audio::common::AudioUsage;
using media::audio::common::Int;

std::mutex AudioSystem::gMutex;
sp<IAudioFlinger> AudioSystem::gAudioFlinger;
sp<IBinder> AudioSystem::gAudioFlingerBinder;
sp<IAudioFlinger> AudioSystem::gLocalAudioFlinger;
sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient;
dynamic_policy_callback AudioSystem::gDynPolicyCallback = NULL;
record_config_callback AudioSystem::gRecordConfigCallback = NULL;
routing_callback AudioSystem::gRoutingCallback = NULL;
@@ -89,90 +85,167 @@ sp<AudioSystem::AudioPolicyServiceClient> AudioSystem::gAudioPolicyServiceClient
// from the system server.
// This allows specific isolated processes to access the audio system. Currently used only for the
// HotwordDetectionService.
void AudioSystem::setAudioFlingerBinder(const sp<IBinder>& audioFlinger) {
    if (audioFlinger->getInterfaceDescriptor() != media::IAudioFlingerService::descriptor) {
        ALOGE("setAudioFlingerBinder: received a binder of type %s",
              String8(audioFlinger->getInterfaceDescriptor()).c_str());
        return;
    }
    std::lock_guard _l(gMutex);
    if (gAudioFlinger != nullptr) {
        ALOGW("setAudioFlingerBinder: ignoring; AudioFlinger connection already established.");
        return;
    }
    gAudioFlingerBinder = audioFlinger;
}

status_t AudioSystem::setLocalAudioFlinger(const sp<IAudioFlinger>& af) {
    std::lock_guard _l(gMutex);
    if (gAudioFlinger != nullptr) return INVALID_OPERATION;
    gLocalAudioFlinger = af;
    return OK;
}
template <typename ServiceInterface, typename Client, typename AidlInterface,
        typename ServiceTraits>
class ServiceHandler {
public:
    sp<ServiceInterface> getService(bool canStartThreadPool = true)
            EXCLUDES(mMutex) NO_THREAD_SAFETY_ANALYSIS {  // std::unique_ptr
        sp<ServiceInterface> service;
        sp<Client> client;

// establish binder interface to AudioFlinger service
const sp<IAudioFlinger> AudioSystem::getAudioFlingerImpl(bool canStartThreadPool = true) {
    sp<IAudioFlinger> af;
    sp<AudioFlingerClient> afc;
        bool reportNoError = false;
        {
        std::lock_guard _l(gMutex);
        if (gAudioFlinger != nullptr) {
            return gAudioFlinger;
            std::lock_guard _l(mMutex);
            if (mService != nullptr) {
                return mService;
            }
        }

        if (gAudioFlingerClient == nullptr) {
            gAudioFlingerClient = sp<AudioFlingerClient>::make();
        std::unique_lock ul_only1thread(mSingleGetter);
        std::unique_lock ul(mMutex);
        if (mService != nullptr) {
            return mService;
        }
        if (mClient == nullptr) {
            mClient = sp<Client>::make();
        } else {
            reportNoError = true;
        }
        while (true) {
            mService = mLocalService;
            if (mService != nullptr) break;

        if (gLocalAudioFlinger != nullptr) {
            gAudioFlinger = gLocalAudioFlinger;
        } else {
            sp<IBinder> binder;
            if (gAudioFlingerBinder != nullptr) {
                binder = gAudioFlingerBinder;
            } else {
            sp<IBinder> binder = mBinder;
            if (binder == nullptr) {
                sp <IServiceManager> sm = defaultServiceManager();
                binder = sm->waitForService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME));
                binder = sm->checkService(String16(ServiceTraits::SERVICE_NAME));
                if (binder == nullptr) {
                    return nullptr;
                    ALOGD("%s: waiting for %s", __func__, ServiceTraits::SERVICE_NAME);

                    // if the condition variable is present, setLocalService() and
                    // setBinder() is allowed to use it to notify us.
                    if (mCvGetter == nullptr) {
                        mCvGetter = std::make_shared<std::condition_variable>();
                    }
                    mCvGetter->wait_for(ul, std::chrono::seconds(1));
                    continue;
                }
            }
            binder->linkToDeath(gAudioFlingerClient);
            const auto afs = interface_cast<media::IAudioFlingerService>(binder);
            LOG_ALWAYS_FATAL_IF(afs == nullptr);
            gAudioFlinger = sp<AudioFlingerClientAdapter>::make(afs);
            binder->linkToDeath(mClient);
            auto aidlInterface = interface_cast<AidlInterface>(binder);
            LOG_ALWAYS_FATAL_IF(aidlInterface == nullptr);
            if constexpr (std::is_same_v<ServiceInterface, AidlInterface>) {
                mService = std::move(aidlInterface);
            } else /* constexpr */ {
                mService = ServiceTraits::createServiceAdapter(aidlInterface);
            }
        afc = gAudioFlingerClient;
        af = gAudioFlinger;
        // Make sure callbacks can be received by gAudioFlingerClient
            break;
        }
        if (mCvGetter) mCvGetter.reset();  // remove condition variable.
        client = mClient;
        service = mService;
        // Make sure callbacks can be received by the client
        if (canStartThreadPool) {
            ProcessState::self()->startThreadPool();
        }
        ul.unlock();
        ul_only1thread.unlock();
        ServiceTraits::onServiceCreate(service, client);
        if (reportNoError) AudioSystem::reportError(NO_ERROR);
        return service;
    }

    status_t setLocalService(const sp<ServiceInterface>& service) EXCLUDES(mMutex) {
        std::lock_guard _l(mMutex);
        // we allow clearing once set, but not a double non-null set.
        if (mService != nullptr && service != nullptr) return INVALID_OPERATION;
        mLocalService = service;
        if (mCvGetter) mCvGetter->notify_one();
        return OK;
    }

    sp<Client> getClient() EXCLUDES(mMutex)  {
        const auto service = getService();
        if (service == nullptr) return nullptr;
        std::lock_guard _l(mMutex);
        return mClient;
    }

    void setBinder(const sp<IBinder>& binder) EXCLUDES(mMutex)  {
        std::lock_guard _l(mMutex);
        if (mService != nullptr) {
            ALOGW("%s: ignoring; %s connection already established.",
                    __func__, ServiceTraits::SERVICE_NAME);
            return;
        }
        mBinder = binder;
        if (mCvGetter) mCvGetter->notify_one();
    }

    void clearService() EXCLUDES(mMutex)  {
        std::lock_guard _l(mMutex);
        mService.clear();
        if (mClient) ServiceTraits::onClearService(mClient);
    }

private:
    std::mutex mSingleGetter;
    std::mutex mMutex;
    std::shared_ptr<std::condition_variable> mCvGetter GUARDED_BY(mMutex);
    sp<IBinder> mBinder GUARDED_BY(mMutex);
    sp<ServiceInterface> mLocalService GUARDED_BY(mMutex);
    sp<ServiceInterface> mService GUARDED_BY(mMutex);
    sp<Client> mClient GUARDED_BY(mMutex);
};

struct AudioFlingerTraits {
    static void onServiceCreate(
            const sp<IAudioFlinger>& af, const sp<AudioSystem::AudioFlingerClient>& afc) {
        const int64_t token = IPCThreadState::self()->clearCallingIdentity();
        af->registerClient(afc);
        IPCThreadState::self()->restoreCallingIdentity(token);
    if (reportNoError) reportError(NO_ERROR);
    return af;
    }

    static sp<IAudioFlinger> createServiceAdapter(
            const sp<media::IAudioFlingerService>& aidlInterface) {
        return sp<AudioFlingerClientAdapter>::make(aidlInterface);
    }

    static void onClearService(const sp<AudioSystem::AudioFlingerClient>& afc) {
        afc->clearIoCache();
    }

    static constexpr const char* SERVICE_NAME = IAudioFlinger::DEFAULT_SERVICE_NAME;
};

[[clang::no_destroy]] static constinit ServiceHandler<IAudioFlinger,
        AudioSystem::AudioFlingerClient, media::IAudioFlingerService,
        AudioFlingerTraits> gAudioFlingerServiceHandler;

sp<IAudioFlinger> AudioSystem::get_audio_flinger() {
    return getAudioFlingerImpl();
    return gAudioFlingerServiceHandler.getService();
}

sp<IAudioFlinger> AudioSystem::get_audio_flinger_for_fuzzer() {
    return getAudioFlingerImpl(false);
    return gAudioFlingerServiceHandler.getService(false /* canStartThreadPool */);
}

const sp<AudioSystem::AudioFlingerClient> AudioSystem::getAudioFlingerClient() {
    // calling get_audio_flinger() will initialize gAudioFlingerClient if needed
    const sp<IAudioFlinger> af = get_audio_flinger();
    if (af == 0) return 0;
    std::lock_guard _l(gMutex);
    return gAudioFlingerClient;
sp<AudioSystem::AudioFlingerClient> AudioSystem::getAudioFlingerClient() {
    return gAudioFlingerServiceHandler.getClient();
}

void AudioSystem::setAudioFlingerBinder(const sp<IBinder>& audioFlinger) {
    if (audioFlinger->getInterfaceDescriptor() != media::IAudioFlingerService::descriptor) {
        ALOGE("%s: received a binder of type %s",
                __func__, String8(audioFlinger->getInterfaceDescriptor()).c_str());
        return;
    }
    gAudioFlingerServiceHandler.setBinder(audioFlinger);
}

status_t AudioSystem::setLocalAudioFlinger(const sp<IAudioFlinger>& af) {
    return gAudioFlingerServiceHandler.setLocalService(af);
}

sp<AudioIoDescriptor> AudioSystem::getIoDescriptor(audio_io_handle_t ioHandle) {
@@ -557,14 +630,7 @@ void AudioSystem::AudioFlingerClient::clearIoCache() {
}

void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who __unused) {
    {
        std::lock_guard _l(AudioSystem::gMutex);
        AudioSystem::gAudioFlinger.clear();
    }

    // clear output handles and stream to output map caches
    clearIoCache();

    gAudioFlingerServiceHandler.clearService();
    reportError(DEAD_OBJECT);

    ALOGW("AudioFlinger server died!");
@@ -1501,13 +1567,7 @@ status_t AudioSystem::setLowRamDevice(bool isLowRamDevice, int64_t totalMemory)
void AudioSystem::clearAudioConfigCache() {
    // called by restoreTrack_l(), which needs new IAudioFlinger and IAudioPolicyService instances
    ALOGV("clearAudioConfigCache()");
    {
        std::lock_guard _l(gMutex);
        if (gAudioFlingerClient != 0) {
            gAudioFlingerClient->clearIoCache();
        }
        gAudioFlinger.clear();
    }
    gAudioFlingerServiceHandler.clearService();
    clearAudioPolicyService();
}

+7 −8
Original line number Diff line number Diff line
@@ -100,6 +100,10 @@ class AudioSystem
    friend class AudioFlingerClient;
    friend class AudioPolicyServiceClient;
    friend class CaptureStateListenerImpl;
    template <typename ServiceInterface, typename Client, typename AidlInterface,
            typename ServiceTraits>
    friend class ServiceHandler;

public:

    // FIXME Declare in binder opcode order, similarly to IAudioFlinger.h and IAudioFlinger.cpp
@@ -781,8 +785,6 @@ public:

    static int32_t getAAudioHardwareBurstMinUsec();

private:

    class AudioFlingerClient: public IBinder::DeathRecipient, public media::BnAudioFlingerClient
    {
    public:
@@ -892,19 +894,16 @@ private:
        std::set<sp<AudioVolumeGroupCallback>> mAudioVolumeGroupCallbacks GUARDED_BY(mMutex);
    };

    private:

    static audio_io_handle_t getOutput(audio_stream_type_t stream);
    static const sp<AudioFlingerClient> getAudioFlingerClient();
    static sp<AudioFlingerClient> getAudioFlingerClient();
    static sp<AudioIoDescriptor> getIoDescriptor(audio_io_handle_t ioHandle);
    static const sp<IAudioFlinger> getAudioFlingerImpl(bool canStartThreadPool);

    // Invokes all registered error callbacks with the given error code.
    static void reportError(status_t err);

    [[clang::no_destroy]] static std::mutex gMutex;
    [[clang::no_destroy]] static sp<IAudioFlinger> gAudioFlinger GUARDED_BY(gMutex);
    [[clang::no_destroy]] static sp<IBinder> gAudioFlingerBinder GUARDED_BY(gMutex);
    [[clang::no_destroy]] static sp<IAudioFlinger> gLocalAudioFlinger GUARDED_BY(gMutex);
    [[clang::no_destroy]] static sp<AudioFlingerClient> gAudioFlingerClient GUARDED_BY(gMutex);
    static dynamic_policy_callback gDynPolicyCallback GUARDED_BY(gMutex);
    static record_config_callback gRecordConfigCallback GUARDED_BY(gMutex);
    static routing_callback gRoutingCallback GUARDED_BY(gMutex);