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

Commit d3fdf28b authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 7249665 from b1551812 to sc-release

Change-Id: I5147a191b0404194f832c9fe2d6ac7d40284c635
parents e84e2b37 b1551812
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@
#include <openssl/aes.h>
#include <utils/KeyedVector.h>
#include <utils/Mutex.h>
#include <utils/RefBase.h>

namespace android {
struct ABuffer;
@@ -30,7 +29,7 @@ struct ABuffer;
namespace clearkeycas {
class KeyFetcher;

class ClearKeyCasSession : public RefBase {
class ClearKeyCasSession {
public:
    explicit ClearKeyCasSession(CasPlugin *plugin);

+19 −1
Original line number Diff line number Diff line
@@ -997,7 +997,15 @@ void CCodec::configure(const sp<AMessage> &msg) {
                // needed for decoders.
                if (!(config->mDomain & Config::IS_ENCODER)) {
                    if (surface == nullptr) {
                        format = flexPixelFormat.value_or(COLOR_FormatYUV420Flexible);
                        const char *prefix = "";
                        if (flexSemiPlanarPixelFormat) {
                            format = COLOR_FormatYUV420SemiPlanar;
                            prefix = "semi-";
                        } else {
                            format = COLOR_FormatYUV420Planar;
                        }
                        ALOGD("Client requested ByteBuffer mode decoder w/o color format set: "
                                "using default %splanar color format", prefix);
                    } else {
                        format = COLOR_FormatSurface;
                    }
@@ -1935,6 +1943,12 @@ void CCodec::signalSetParameters(const sp<AMessage> &msg) {
        params->removeEntryAt(params->findEntryByName(KEY_BIT_RATE));
    }

    int32_t syncId = 0;
    if (params->findInt32("audio-hw-sync", &syncId)
            || params->findInt32("hw-av-sync-id", &syncId)) {
        configureTunneledVideoPlayback(comp, nullptr, params);
    }

    Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
    const std::unique_ptr<Config> &config = *configLocked;

@@ -2258,6 +2272,10 @@ status_t CCodec::configureTunneledVideoPlayback(
        return UNKNOWN_ERROR;
    }

    if (sidebandHandle == nullptr) {
        return OK;
    }

    std::vector<std::unique_ptr<C2Param>> params;
    c2err = comp->query({}, {C2PortTunnelHandleTuning::output::PARAM_TYPE}, C2_DONT_BLOCK, &params);
    if (c2err == C2_OK && params.size() == 1u) {
+3 −1
Original line number Diff line number Diff line
@@ -42,7 +42,9 @@ namespace /* unnamed */ {
         * Usage mask that is passed through from gralloc to Codec 2.0 usage.
         */
        PASSTHROUGH_USAGE_MASK =
            ~(GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_PROTECTED)
            ~static_cast<uint64_t>(GRALLOC_USAGE_SW_READ_MASK |
                                   GRALLOC_USAGE_SW_WRITE_MASK |
                                   GRALLOC_USAGE_PROTECTED)
    };

    // verify that passthrough mask is within the platform mask
+61 −0
Original line number Diff line number Diff line
@@ -94,6 +94,12 @@ struct TranscodingClientManager::ClientImpl : public BnTranscodingClient {
    Status getSessionWithId(int32_t /*in_sessionId*/, TranscodingSessionParcel* /*out_session*/,
                            bool* /*_aidl_return*/) override;

    Status addClientUid(int32_t /*in_sessionId*/, int32_t /*in_clientUid*/,
                        bool* /*_aidl_return*/) override;

    Status getClientUids(int32_t /*in_sessionId*/, std::vector<int32_t>* /*out_clientUids*/,
                         bool* /*_aidl_return*/) override;

    Status unregister() override;
};

@@ -217,6 +223,61 @@ Status TranscodingClientManager::ClientImpl::getSessionWithId(int32_t in_session
    return Status::ok();
}

Status TranscodingClientManager::ClientImpl::addClientUid(int32_t in_sessionId,
                                                          int32_t in_clientUid,
                                                          bool* _aidl_return) {
    *_aidl_return = false;

    std::shared_ptr<TranscodingClientManager> owner;
    if (mAbandoned || (owner = mOwner.lock()) == nullptr) {
        return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
    }

    if (in_sessionId < 0) {
        return Status::ok();
    }

    int32_t callingPid = AIBinder_getCallingPid();
    int32_t callingUid = AIBinder_getCallingUid();

    // Check if we can trust clientUid. Only privilege caller could add uid to existing sessions.
    if (in_clientUid == IMediaTranscodingService::USE_CALLING_UID) {
        in_clientUid = callingUid;
    } else if (in_clientUid < 0) {
        return Status::ok();
    } else if (in_clientUid != callingUid && !owner->isTrustedCaller(callingPid, callingUid)) {
        ALOGE("addClientUid rejected (clientUid %d) "
              "(don't trust callingUid %d)",
              in_clientUid, callingUid);
        return STATUS_ERROR_FMT(IMediaTranscodingService::ERROR_PERMISSION_DENIED,
                                "addClientUid rejected (clientUid %d) "
                                "(don't trust callingUid %d)",
                                in_clientUid, callingUid);
    }

    *_aidl_return = owner->mSessionController->addClientUid(mClientId, in_sessionId, in_clientUid);
    return Status::ok();
}

Status TranscodingClientManager::ClientImpl::getClientUids(int32_t in_sessionId,
                                                           std::vector<int32_t>* out_clientUids,
                                                           bool* _aidl_return) {
    *_aidl_return = false;

    std::shared_ptr<TranscodingClientManager> owner;
    if (mAbandoned || (owner = mOwner.lock()) == nullptr) {
        return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
    }

    if (in_sessionId < 0) {
        return Status::ok();
    }

    *_aidl_return =
            owner->mSessionController->getClientUids(mClientId, in_sessionId, out_clientUids);
    return Status::ok();
}

Status TranscodingClientManager::ClientImpl::unregister() {
    bool abandoned = mAbandoned.exchange(true);

+179 −68
Original line number Diff line number Diff line
@@ -193,8 +193,8 @@ struct TranscodingSessionController::Pacer {

    ~Pacer() = default;

    void onSessionCompleted(uid_t uid, std::chrono::microseconds runningTime);
    bool onSessionStarted(uid_t uid);
    void onSessionCompleted(uid_t uid, std::chrono::microseconds runningTime);

private:
    // Threshold of time between finish/start below which a back-to-back start is counted.
@@ -205,26 +205,20 @@ private:
    int32_t mBurstTimeQuotaSec;

    struct UidHistoryEntry {
        std::chrono::steady_clock::time_point lastCompletedTime;
        bool sessionActive = false;
        int32_t burstCount = 0;
        std::chrono::steady_clock::duration burstDuration{0};
        std::chrono::steady_clock::time_point lastCompletedTime;
    };
    std::map<uid_t, UidHistoryEntry> mUidHistoryMap;
};

void TranscodingSessionController::Pacer::onSessionCompleted(
        uid_t uid, std::chrono::microseconds runningTime) {
    if (mUidHistoryMap.find(uid) == mUidHistoryMap.end()) {
        mUidHistoryMap.emplace(uid, UidHistoryEntry{});
    }
    mUidHistoryMap[uid].lastCompletedTime = std::chrono::steady_clock::now();
    mUidHistoryMap[uid].burstCount++;
    mUidHistoryMap[uid].burstDuration += runningTime;
}

bool TranscodingSessionController::Pacer::onSessionStarted(uid_t uid) {
    // If uid doesn't exist, this uid has no completed sessions. Skip.
    // If uid doesn't exist, only insert the entry and mark session active. Skip quota checking.
    if (mUidHistoryMap.find(uid) == mUidHistoryMap.end()) {
        mUidHistoryMap.emplace(uid, UidHistoryEntry{});
        mUidHistoryMap[uid].sessionActive = true;
        ALOGV("Pacer::onSessionStarted: uid %d: new", uid);
        return true;
    }

@@ -236,25 +230,43 @@ bool TranscodingSessionController::Pacer::onSessionStarted(uid_t uid) {
            std::chrono::steady_clock::now() - mUidHistoryMap[uid].lastCompletedTime;
    if (mUidHistoryMap[uid].burstCount >= mBurstCountQuota &&
        mUidHistoryMap[uid].burstDuration >= std::chrono::seconds(mBurstTimeQuotaSec)) {
        ALOGW("Pacer: uid %d: over quota, burst count %d, time %lldms", uid,
              mUidHistoryMap[uid].burstCount, (long long)mUidHistoryMap[uid].burstDuration.count());
        ALOGW("Pacer::onSessionStarted: uid %d: over quota, burst count %d, time %lldms", uid,
              mUidHistoryMap[uid].burstCount,
              (long long)mUidHistoryMap[uid].burstDuration.count() / 1000000);
        return false;
    }

    // If not over quota, allow the session, and reset as long as this is not too close
    // to previous completion.
    if (timeSinceLastComplete > std::chrono::milliseconds(mBurstThresholdMs)) {
        ALOGV("Pacer: uid %d: reset quota", uid);
        ALOGV("Pacer::onSessionStarted: uid %d: reset quota", uid);
        mUidHistoryMap[uid].burstCount = 0;
        mUidHistoryMap[uid].burstDuration = std::chrono::milliseconds(0);
    } else {
        ALOGV("Pacer: uid %d: burst count %d, time %lldms", uid, mUidHistoryMap[uid].burstCount,
              (long long)mUidHistoryMap[uid].burstDuration.count());
        ALOGV("Pacer::onSessionStarted: uid %d: burst count %d, time %lldms", uid,
              mUidHistoryMap[uid].burstCount,
              (long long)mUidHistoryMap[uid].burstDuration.count() / 1000000);
    }

    mUidHistoryMap[uid].sessionActive = true;
    return true;
}

void TranscodingSessionController::Pacer::onSessionCompleted(
        uid_t uid, std::chrono::microseconds runningTime) {
    // Skip quota update if this uid missed the start. (Could happen if the uid is added via
    // addClientUid() after the session start.)
    if (mUidHistoryMap.find(uid) == mUidHistoryMap.end() || !mUidHistoryMap[uid].sessionActive) {
        ALOGV("Pacer::onSessionCompleted: uid %d: not started", uid);
        return;
    }
    ALOGV("Pacer::onSessionCompleted: uid %d: runningTime %lld", uid, runningTime.count() / 1000);
    mUidHistoryMap[uid].sessionActive = false;
    mUidHistoryMap[uid].burstCount++;
    mUidHistoryMap[uid].burstDuration += runningTime;
    mUidHistoryMap[uid].lastCompletedTime = std::chrono::steady_clock::now();
}

///////////////////////////////////////////////////////////////////////////////

TranscodingSessionController::TranscodingSessionController(
@@ -372,6 +384,14 @@ TranscodingSessionController::Session* TranscodingSessionController::getTopSessi
    }

    uid_t topUid = *mUidSortedList.begin();
    // If the current session is running, and it's in the topUid's queue, let it continue
    // to run even if it's not the earliest in that uid's queue.
    // For example, uid(B) is added to a session while it's pending in uid(A)'s queue, then
    // B is brought to front which caused the session to run, then user switches back to A.
    if (mCurrentSession != nullptr && mCurrentSession->getState() == Session::RUNNING &&
        mCurrentSession->allClientUids.count(topUid) > 0) {
        return mCurrentSession;
    }
    SessionKeyType topSessionKey = *mSessionQueues[topUid].begin();
    return &mSessionMap[topSessionKey];
}
@@ -427,7 +447,7 @@ void TranscodingSessionController::Session::setState(Session::State newState) {

void TranscodingSessionController::updateCurrentSession_l() {
    Session* curSession = mCurrentSession;
    Session* topSession = getTopSession_l();
    Session* topSession = nullptr;

    // Delayed init of transcoder and watchdog.
    if (mTranscoder == nullptr) {
@@ -458,9 +478,18 @@ void TranscodingSessionController::updateCurrentSession_l() {

        // Otherwise, ensure topSession is running.
        if (topSession->getState() == Session::NOT_STARTED) {
            if (!mPacer->onSessionStarted(topSession->clientUid)) {
                // Unfortunately this uid is out of quota for new sessions.
                // Drop this sesion and try another one.
            // Check if at least one client has quota to start the session.
            bool keepForClient = false;
            for (uid_t uid : topSession->allClientUids) {
                if (mPacer->onSessionStarted(uid)) {
                    keepForClient = true;
                    // DO NOT break here, because book-keeping still needs to happen
                    // for the other uids.
                }
            }
            if (!keepForClient) {
                // Unfortunately all uids requesting this session are out of quota.
                // Drop this session and try the next one.
                {
                    auto clientCallback = mSessionMap[topSession->key].callback.lock();
                    if (clientCallback != nullptr) {
@@ -484,8 +513,34 @@ void TranscodingSessionController::updateCurrentSession_l() {
    mCurrentSession = topSession;
}

void TranscodingSessionController::addUidToSession_l(uid_t clientUid,
                                                     const SessionKeyType& sessionKey) {
    // If it's an offline session, the queue was already added in constructor.
    // If it's a real-time sessions, check if a queue is already present for the uid,
    // and add a new queue if needed.
    if (clientUid != OFFLINE_UID) {
        if (mSessionQueues.count(clientUid) == 0) {
            mUidPolicy->registerMonitorUid(clientUid);
            if (mUidPolicy->isUidOnTop(clientUid)) {
                mUidSortedList.push_front(clientUid);
            } else {
                // Shouldn't be submitting real-time requests from non-top app,
                // put it in front of the offline queue.
                mUidSortedList.insert(mOfflineUidIterator, clientUid);
            }
        } else if (clientUid != *mUidSortedList.begin()) {
            if (mUidPolicy->isUidOnTop(clientUid)) {
                mUidSortedList.remove(clientUid);
                mUidSortedList.push_front(clientUid);
            }
        }
    }
    // Append this session to the uid's queue.
    mSessionQueues[clientUid].push_back(sessionKey);
}

void TranscodingSessionController::removeSession_l(const SessionKeyType& sessionKey,
                                                   Session::State finalState) {
                                                   Session::State finalState, bool keepForOffline) {
    ALOGV("%s: session %s", __FUNCTION__, sessionToString(sessionKey).c_str());

    if (mSessionMap.count(sessionKey) == 0) {
@@ -494,13 +549,17 @@ void TranscodingSessionController::removeSession_l(const SessionKeyType& session
    }

    // Remove session from uid's queue.
    const uid_t uid = mSessionMap[sessionKey].clientUid;
    bool uidQueueRemoved = false;
    for (uid_t uid : mSessionMap[sessionKey].allClientUids) {
        if (keepForOffline && uid == OFFLINE_UID) {
            continue;
        }
        SessionQueueType& sessionQueue = mSessionQueues[uid];
        auto it = std::find(sessionQueue.begin(), sessionQueue.end(), sessionKey);
        if (it == sessionQueue.end()) {
        ALOGE("couldn't find session %s in queue for uid %d", sessionToString(sessionKey).c_str(),
              uid);
        return;
            ALOGW("couldn't find session %s in queue for uid %d",
                  sessionToString(sessionKey).c_str(), uid);
            continue;
        }
        sessionQueue.erase(it);

@@ -510,10 +569,20 @@ void TranscodingSessionController::removeSession_l(const SessionKeyType& session
            mSessionQueues.erase(uid);
            mUidPolicy->unregisterMonitorUid(uid);

            uidQueueRemoved = true;
        }
    }

    if (uidQueueRemoved) {
        std::unordered_set<uid_t> topUids = mUidPolicy->getTopUids();
        moveUidsToTop_l(topUids, false /*preserveTopUid*/);
    }

    if (keepForOffline) {
        mSessionMap[sessionKey].allClientUids = {OFFLINE_UID};
        return;
    }

    // Clear current session.
    if (mCurrentSession == &mSessionMap[sessionKey]) {
        mCurrentSession = nullptr;
@@ -522,8 +591,9 @@ void TranscodingSessionController::removeSession_l(const SessionKeyType& session
    setSessionState_l(&mSessionMap[sessionKey], finalState);

    if (finalState == Session::FINISHED || finalState == Session::ERROR) {
        mPacer->onSessionCompleted(mSessionMap[sessionKey].clientUid,
                                   mSessionMap[sessionKey].runningTime);
        for (uid_t uid : mSessionMap[sessionKey].allClientUids) {
            mPacer->onSessionCompleted(uid, mSessionMap[sessionKey].runningTime);
        }
    }

    mSessionHistory.push_back(mSessionMap[sessionKey]);
@@ -617,34 +687,13 @@ bool TranscodingSessionController::submit(

    // Add session to session map.
    mSessionMap[sessionKey].key = sessionKey;
    mSessionMap[sessionKey].clientUid = clientUid;
    mSessionMap[sessionKey].callingUid = callingUid;
    mSessionMap[sessionKey].allClientUids.insert(clientUid);
    mSessionMap[sessionKey].request = request;
    mSessionMap[sessionKey].callback = callback;
    setSessionState_l(&mSessionMap[sessionKey], Session::NOT_STARTED);

    // If it's an offline session, the queue was already added in constructor.
    // If it's a real-time sessions, check if a queue is already present for the uid,
    // and add a new queue if needed.
    if (clientUid != OFFLINE_UID) {
        if (mSessionQueues.count(clientUid) == 0) {
            mUidPolicy->registerMonitorUid(clientUid);
            if (mUidPolicy->isUidOnTop(clientUid)) {
                mUidSortedList.push_front(clientUid);
            } else {
                // Shouldn't be submitting real-time requests from non-top app,
                // put it in front of the offline queue.
                mUidSortedList.insert(mOfflineUidIterator, clientUid);
            }
        } else if (clientUid != *mUidSortedList.begin()) {
            if (mUidPolicy->isUidOnTop(clientUid)) {
                mUidSortedList.remove(clientUid);
                mUidSortedList.push_front(clientUid);
            }
        }
    }
    // Append this session to the uid's queue.
    mSessionQueues[clientUid].push_back(sessionKey);
    addUidToSession_l(clientUid, sessionKey);

    updateCurrentSession_l();

@@ -657,16 +706,22 @@ bool TranscodingSessionController::cancel(ClientIdType clientId, SessionIdType s

    ALOGV("%s: session %s", __FUNCTION__, sessionToString(sessionKey).c_str());

    std::list<SessionKeyType> sessionsToRemove;
    std::list<SessionKeyType> sessionsToRemove, sessionsForOffline;

    std::scoped_lock lock{mLock};

    if (sessionId < 0) {
        for (auto it = mSessionMap.begin(); it != mSessionMap.end(); ++it) {
            if (it->first.first == clientId && it->second.clientUid != OFFLINE_UID) {
            if (it->first.first == clientId) {
                // If there is offline request, only keep the offline client;
                // otherwise remove the session.
                if (it->second.allClientUids.count(OFFLINE_UID) > 0) {
                    sessionsForOffline.push_back(it->first);
                } else {
                    sessionsToRemove.push_back(it->first);
                }
            }
        }
    } else {
        if (mSessionMap.count(sessionKey) == 0) {
            ALOGE("session %s doesn't exist", sessionToString(sessionKey).c_str());
@@ -688,6 +743,10 @@ bool TranscodingSessionController::cancel(ClientIdType clientId, SessionIdType s
        removeSession_l(*it, Session::CANCELED);
    }

    for (auto it = sessionsForOffline.begin(); it != sessionsForOffline.end(); ++it) {
        removeSession_l(*it, Session::CANCELED, true /*keepForOffline*/);
    }

    // Start next session.
    updateCurrentSession_l();

@@ -695,6 +754,51 @@ bool TranscodingSessionController::cancel(ClientIdType clientId, SessionIdType s
    return true;
}

bool TranscodingSessionController::addClientUid(ClientIdType clientId, SessionIdType sessionId,
                                                uid_t clientUid) {
    SessionKeyType sessionKey = std::make_pair(clientId, sessionId);

    std::scoped_lock lock{mLock};

    if (mSessionMap.count(sessionKey) == 0) {
        ALOGE("session %s doesn't exist", sessionToString(sessionKey).c_str());
        return false;
    }

    if (mSessionMap[sessionKey].allClientUids.count(clientUid) > 0) {
        ALOGE("session %s already has uid %d", sessionToString(sessionKey).c_str(), clientUid);
        return false;
    }

    mSessionMap[sessionKey].allClientUids.insert(clientUid);
    addUidToSession_l(clientUid, sessionKey);

    updateCurrentSession_l();

    validateState_l();
    return true;
}

bool TranscodingSessionController::getClientUids(ClientIdType clientId, SessionIdType sessionId,
                                                 std::vector<int32_t>* out_clientUids) {
    SessionKeyType sessionKey = std::make_pair(clientId, sessionId);

    std::scoped_lock lock{mLock};

    if (mSessionMap.count(sessionKey) == 0) {
        ALOGE("session %s doesn't exist", sessionToString(sessionKey).c_str());
        return false;
    }

    out_clientUids->clear();
    for (uid_t uid : mSessionMap[sessionKey].allClientUids) {
        if (uid != OFFLINE_UID) {
            out_clientUids->push_back(uid);
        }
    }
    return true;
}

bool TranscodingSessionController::getSession(ClientIdType clientId, SessionIdType sessionId,
                                              TranscodingRequestParcel* request) {
    SessionKeyType sessionKey = std::make_pair(clientId, sessionId);
@@ -938,7 +1042,8 @@ void TranscodingSessionController::validateState_l() {
    LOG_ALWAYS_FATAL_IF(*mOfflineUidIterator != OFFLINE_UID,
                        "mOfflineUidIterator not pointing to offline uid");
    LOG_ALWAYS_FATAL_IF(mUidSortedList.size() != mSessionQueues.size(),
                        "mUidList and mSessionQueues size mismatch");
                        "mUidSortedList and mSessionQueues size mismatch, %zu vs %zu",
                        mUidSortedList.size(), mSessionQueues.size());

    int32_t totalSessions = 0;
    for (auto uid : mUidSortedList) {
@@ -952,8 +1057,14 @@ void TranscodingSessionController::validateState_l() {

        totalSessions += mSessionQueues[uid].size();
    }
    LOG_ALWAYS_FATAL_IF(mSessionMap.size() != totalSessions,
                        "mSessions size doesn't match total sessions counted from uid queues");
    int32_t totalSessionsAlternative = 0;
    for (auto const& s : mSessionMap) {
        totalSessionsAlternative += s.second.allClientUids.size();
    }
    LOG_ALWAYS_FATAL_IF(totalSessions != totalSessionsAlternative,
                        "session count (including dup) from mSessionQueues doesn't match that from "
                        "mSessionMap, %d vs %d",
                        totalSessions, totalSessionsAlternative);
#endif  // VALIDATE_STATE
}

Loading