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

Commit b26a1c8d authored by Andy Hung's avatar Andy Hung
Browse files

MediaUtils: Create singleton UidInfo

A singleton optimizes for multiple calling sites, and
the info is contained in a shared pointer to avoid copying.

Test: adb shell dumpsys media.audio_flinger / media.metrics
Bug: 350114693
Flag: EXEMPT bugfix
Change-Id: I5578e49e61145812ea0378752cea485cbb5b57d8
parent 69cd79b7
Loading
Loading
Loading
Loading
+29 −13
Original line number Diff line number Diff line
@@ -473,35 +473,38 @@ void MediaPackageManager::dump(int fd, int spaces) const {
    }
}

namespace mediautils {

// How long we hold info before we re-fetch it (24 hours) if we found it previously.
static constexpr nsecs_t INFO_EXPIRATION_NS = 24 * 60 * 60 * NANOS_PER_SECOND;
// Maximum info records we retain before clearing everything.
static constexpr size_t INFO_CACHE_MAX = 1000;

// The original code is from MediaMetricsService.cpp.
mediautils::UidInfo::Info mediautils::UidInfo::getInfo(uid_t uid)
std::shared_ptr<const UidInfo::Info> UidInfo::getCachedInfo(uid_t uid)
{
    std::shared_ptr<const UidInfo::Info> info;

    const nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
    struct mediautils::UidInfo::Info info;
    {
        std::lock_guard _l(mLock);
        auto it = mInfoMap.find(uid);
        if (it != mInfoMap.end()) {
            info = it->second;
            ALOGV("%s: uid %d expiration %lld now %lld",
                    __func__, uid, (long long)info.expirationNs, (long long)now);
            if (info.expirationNs <= now) {
                    __func__, uid, (long long)info->expirationNs, (long long)now);
            if (info->expirationNs <= now) {
                // purge the stale entry and fall into re-fetching
                ALOGV("%s: entry for uid %d expired, now %lld",
                        __func__, uid, (long long)now);
                mInfoMap.erase(it);
                info.uid = (uid_t)-1;  // this is always fully overwritten
                info.reset();  // force refetch
            }
        }
    }

    // if we did not find it in our map, look it up
    if (info.uid == (uid_t)(-1)) {
    if (!info) {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<content::pm::IPackageManagerNative> package_mgr;
        if (sm.get() == nullptr) {
@@ -586,17 +589,30 @@ mediautils::UidInfo::Info mediautils::UidInfo::getInfo(uid_t uid)
        // first clear if we have too many cached elements.  This would be rare.
        if (mInfoMap.size() >= INFO_CACHE_MAX) mInfoMap.clear();

        // always overwrite
        info.uid = uid;
        info.package = std::move(pkg);
        info.installer = std::move(installer);
        info.versionCode = versionCode;
        info.expirationNs = now + (notFound ? 0 : INFO_EXPIRATION_NS);
        info = std::make_shared<const UidInfo::Info>(
                uid,
                std::move(pkg),
                std::move(installer),
                versionCode,
                now + (notFound ? 0 : INFO_EXPIRATION_NS));
        ALOGV("%s: adding uid %d package '%s' expirationNs: %lld",
                __func__, uid, info.package.c_str(), (long long)info.expirationNs);
                __func__, uid, info->package.c_str(), (long long)info->expirationNs);
        mInfoMap[uid] = info;
    }
    return info;
}

/* static */
UidInfo& UidInfo::getUidInfo() {
    [[clang::no_destroy]] static UidInfo uidInfo;
    return uidInfo;
}

/* static */
std::shared_ptr<const UidInfo::Info> UidInfo::getInfo(uid_t uid) {
    return UidInfo::getUidInfo().getCachedInfo(uid);
}

} // namespace mediautils

} // namespace android
+9 −2
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <unistd.h>

#include <android/content/pm/IPackageManagerNative.h>
#include <android-base/thread_annotations.h>
#include <binder/IMemory.h>
#include <binder/PermissionController.h>
#include <cutils/multiuser.h>
@@ -167,12 +168,18 @@ public:
     *
     * \param uid is the uid of the app or service.
     */
    Info getInfo(uid_t uid);
    std::shared_ptr<const Info> getCachedInfo(uid_t uid);

    /* return a singleton */
    static UidInfo& getUidInfo();

    /* returns a non-null pointer to a const Info struct */
    static std::shared_ptr<const Info> getInfo(uid_t uid);

private:
    std::mutex mLock;
    // TODO: use concurrent hashmap with striped lock.
    std::unordered_map<uid_t, Info> mInfoMap; // GUARDED_BY(mLock)
    std::unordered_map<uid_t, std::shared_ptr<const Info>> mInfoMap GUARDED_BY(mLock);
};

} // namespace mediautils
+6 −4
Original line number Diff line number Diff line
@@ -754,17 +754,19 @@ void AudioFlinger::dumpClients_ll(int fd, const Vector<String16>& args __unused)
    for (size_t i = 0; i < mNotificationClients.size(); ++i) {
        const pid_t pid = mNotificationClients[i]->getPid();
        const uid_t uid = mNotificationClients[i]->getUid();
        const mediautils::UidInfo::Info info = mUidInfo.getInfo(uid);
        result.appendFormat("%6d %6u  %s\n", pid, uid, info.package.c_str());
        const std::shared_ptr<const mediautils::UidInfo::Info> info =
                mediautils::UidInfo::getInfo(uid);
        result.appendFormat("%6d %6u  %s\n", pid, uid, info->package.c_str());
    }

    result.append("Global session refs:\n");
    result.append("  session  cnt     pid    uid  name\n");
    for (size_t i = 0; i < mAudioSessionRefs.size(); i++) {
        AudioSessionRef *r = mAudioSessionRefs[i];
        const mediautils::UidInfo::Info info = mUidInfo.getInfo(r->mUid);
        const std::shared_ptr<const mediautils::UidInfo::Info> info =
                mediautils::UidInfo::getInfo(r->mUid);
        result.appendFormat("  %7d %4d %7d %6u  %s\n", r->mSessionid, r->mCnt, r->mPid,
                r->mUid, info.package.c_str());
                r->mUid, info->package.c_str());
    }
    write(fd, result.c_str(), result.size());
}
+0 −2
Original line number Diff line number Diff line
@@ -777,8 +777,6 @@ private:
    bool mSystemReady GUARDED_BY(mutex()) = false;
    std::atomic<bool> mAudioPolicyReady = false;

    mediautils::UidInfo mUidInfo GUARDED_BY(mutex());

    // no mutex needed.
    SimpleLog  mRejectedSetParameterLog;
    SimpleLog  mAppSetParameterLog;
+4 −8
Original line number Diff line number Diff line
@@ -92,16 +92,12 @@ bool MediaMetricsService::useUidForPackage(
/* static */
std::pair<std::string, int64_t>
MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid_t uid) {
    // Meyer's singleton, initialized on first access.
    // mUidInfo is locked internally.
    static mediautils::UidInfo uidInfo;

    // get info.
    mediautils::UidInfo::Info info = uidInfo.getInfo(uid);
    if (useUidForPackage(info.package, info.installer)) {
    const std::shared_ptr<const mediautils::UidInfo::Info> info =
            mediautils::UidInfo::getInfo(uid);
    if (useUidForPackage(info->package, info->installer)) {
        return { std::to_string(uid), /* versionCode */ 0 };
    } else {
        return { info.package, info.versionCode };
        return { info->package, info->versionCode };
    }
}