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

Commit 9fb6f3dc authored by Andy Hung's avatar Andy Hung
Browse files

AudioSystem: Ensure onNewService callback is complete before returning service

A race condition with two threads starting at identical times
obtaining the AudioFlinger service the very first time may result
in an AudioTrack creation failure because the second thread continues
before the onNewService callback is complete.

Here the second thread will wait for the onNewService to complete.

Flag: EXEMPT bugfix
Test: atest CtsMediaAudioTestCases
Test: atest WvtsDeviceTestCases:com.google.android.wvts.MediaDrmParameterizedTests#testResourceRatingTierNumKeys[L1] --iterations=100 -- --abi arm64-v8a
Bug: 402768417
Change-Id: Id011af3bcc0ff701beb7e986e415913260606669
parent ae8dfbee
Loading
Loading
Loading
Loading
+16 −0
Original line number Original line Diff line number Diff line
@@ -195,6 +195,7 @@ public:
        }
        }
        if (mValid) return mService;
        if (mValid) return mService;
        if (waitMs.count() < 0) waitMs = mWaitMs;
        if (waitMs.count() < 0) waitMs = mWaitMs;
        auto timepointLimit = std::chrono::steady_clock::now() + waitMs;
        ul.unlock();
        ul.unlock();


        // mediautils::getService() installs a persistent new service notification.
        // mediautils::getService() installs a persistent new service notification.
@@ -205,6 +206,7 @@ public:
        ul.lock();
        ul.lock();
        // return the IAudioFlinger interface which is adapted
        // return the IAudioFlinger interface which is adapted
        // from the media::IAudioFlingerService.
        // from the media::IAudioFlingerService.
        mCv.wait_until(ul, timepointLimit, isServiceValid_l);
        return mService;
        return mService;
    }
    }


@@ -289,6 +291,7 @@ private:
            mService = service;
            mService = service;
            client = mClient;
            client = mClient;
            mValid = true;
            mValid = true;
            mCv.notify_all();
        }
        }
        // TODO(b/375280520) consider registerClient() within mMutex lock.
        // TODO(b/375280520) consider registerClient() within mMutex lock.
        const int64_t token = IPCThreadState::self()->clearCallingIdentity();
        const int64_t token = IPCThreadState::self()->clearCallingIdentity();
@@ -303,7 +306,12 @@ private:
        return sp<AudioFlingerClientAdapter>::make(af);
        return sp<AudioFlingerClientAdapter>::make(af);
    }
    }


    static bool isServiceValid_l() REQUIRES(mMutex) {
        return mValid;
    }

    static inline constinit std::mutex mMutex;
    static inline constinit std::mutex mMutex;
    static inline constinit std::condition_variable mCv;
    static inline constinit sp<AudioSystem::AudioFlingerClient> mClient GUARDED_BY(mMutex);
    static inline constinit sp<AudioSystem::AudioFlingerClient> mClient GUARDED_BY(mMutex);
    static inline constinit sp<IAudioFlinger> mService GUARDED_BY(mMutex);
    static inline constinit sp<IAudioFlinger> mService GUARDED_BY(mMutex);
    static inline constinit std::chrono::milliseconds mWaitMs
    static inline constinit std::chrono::milliseconds mWaitMs
@@ -1022,6 +1030,7 @@ public:
            client = mClient;
            client = mClient;
            mService = aps;
            mService = aps;
            mValid = true;
            mValid = true;
            mCv.notify_all();
        }
        }
        // TODO(b/375280520) consider registerClient() within mMutex lock.
        // TODO(b/375280520) consider registerClient() within mMutex lock.
        const int64_t token = IPCThreadState::self()->clearCallingIdentity();
        const int64_t token = IPCThreadState::self()->clearCallingIdentity();
@@ -1082,6 +1091,7 @@ public:
        }
        }
        if (mValid) return mService;
        if (mValid) return mService;
        if (waitMs.count() < 0) waitMs = mWaitMs;
        if (waitMs.count() < 0) waitMs = mWaitMs;
        auto timepointLimit = std::chrono::steady_clock::now() + waitMs;
        ul.unlock();
        ul.unlock();


        auto service = mediautils::getService<
        auto service = mediautils::getService<
@@ -1092,6 +1102,7 @@ public:
        // (whereupon mService contained the actual local service pointer to use).
        // (whereupon mService contained the actual local service pointer to use).
        // we should always return mService.
        // we should always return mService.
        ul.lock();
        ul.lock();
        mCv.wait_until(ul, timepointLimit, isServiceValid_l);
        return mService;
        return mService;
    }
    }


@@ -1140,7 +1151,12 @@ public:
    }
    }
private:
private:


    static bool isServiceValid_l() REQUIRES(mMutex) {
        return mValid;
    }

    static inline constinit std::mutex mMutex;
    static inline constinit std::mutex mMutex;
    static inline constinit std::condition_variable mCv;
    static inline constinit sp<AudioSystem::AudioPolicyServiceClient> mClient GUARDED_BY(mMutex);
    static inline constinit sp<AudioSystem::AudioPolicyServiceClient> mClient GUARDED_BY(mMutex);
    static inline constinit sp<IAudioPolicyService> mService GUARDED_BY(mMutex);
    static inline constinit sp<IAudioPolicyService> mService GUARDED_BY(mMutex);
    static inline constinit bool mValid GUARDED_BY(mMutex) = false;
    static inline constinit bool mValid GUARDED_BY(mMutex) = false;