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

Commit d2b0b504 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Camera service: Update client eviction priorities"

parents ba05ff12 8131a269
Loading
Loading
Loading
Loading
+50 −48
Original line number Diff line number Diff line
@@ -651,22 +651,6 @@ String8 CameraService::getFormattedCurrentTime() {
    return String8(formattedTime);
}

int CameraService::getCameraPriorityFromProcState(int procState) {
    // Find the priority for the camera usage based on the process state.  Higher priority clients
    // win for evictions.
    if (procState < 0) {
        ALOGE("%s: Received invalid process state %d from ActivityManagerService!", __FUNCTION__,
                procState);
        return -1;
    }
    // Treat sleeping TOP processes the same as regular TOP processes, for
    // access priority.  This is important for lock-screen camera launch scenarios
    if (procState == PROCESS_STATE_TOP_SLEEPING) {
        procState = PROCESS_STATE_TOP;
    }
    return INT_MAX - procState;
}

Status CameraService::getCameraVendorTagDescriptor(
        /*out*/
        hardware::camera2::params::VendorTagDescriptor* desc) {
@@ -1212,20 +1196,24 @@ status_t CameraService::handleEvictionsLocked(const String8& cameraId, int clien
        std::vector<int> ownerPids(mActiveClientManager.getAllOwners());
        ownerPids.push_back(clientPid);

        // Use the value +PROCESS_STATE_NONEXISTENT, to avoid taking
        // address of PROCESS_STATE_NONEXISTENT as a reference argument
        // for the vector constructor. PROCESS_STATE_NONEXISTENT does
        // not have an out-of-class definition.
        std::vector<int> priorities(ownerPids.size(), +PROCESS_STATE_NONEXISTENT);
        std::vector<int> priorityScores(ownerPids.size());
        std::vector<int> states(ownerPids.size());

        // Get priorites of all active PIDs
        ProcessInfoService::getProcessStatesFromPids(ownerPids.size(), &ownerPids[0],
                /*out*/&priorities[0]);
        // Get priority scores of all active PIDs
        status_t err = ProcessInfoService::getProcessStatesScoresFromPids(
                ownerPids.size(), &ownerPids[0], /*out*/&states[0],
                /*out*/&priorityScores[0]);
        if (err != OK) {
            ALOGE("%s: Priority score query failed: %d",
                  __FUNCTION__, err);
            return err;
        }

        // Update all active clients' priorities
        std::map<int,int> pidToPriorityMap;
        std::map<int,resource_policy::ClientPriority> pidToPriorityMap;
        for (size_t i = 0; i < ownerPids.size() - 1; i++) {
            pidToPriorityMap.emplace(ownerPids[i], getCameraPriorityFromProcState(priorities[i]));
            pidToPriorityMap.emplace(ownerPids[i],
                    resource_policy::ClientPriority(priorityScores[i], states[i]));
        }
        mActiveClientManager.updatePriorities(pidToPriorityMap);

@@ -1242,7 +1230,9 @@ status_t CameraService::handleEvictionsLocked(const String8& cameraId, int clien
        clientDescriptor = CameraClientManager::makeClientDescriptor(cameraId,
                sp<BasicClient>{nullptr}, static_cast<int32_t>(state->getCost()),
                state->getConflicting(),
                getCameraPriorityFromProcState(priorities[priorities.size() - 1]), clientPid);
                priorityScores[priorityScores.size() - 1],
                clientPid,
                states[states.size() - 1]);

        // Find clients that would be evicted
        auto evicted = mActiveClientManager.wouldEvict(clientDescriptor);
@@ -1259,19 +1249,22 @@ status_t CameraService::handleEvictionsLocked(const String8& cameraId, int clien
                    mActiveClientManager.getIncompatibleClients(clientDescriptor);

            String8 msg = String8::format("%s : DENIED connect device %s client for package %s "
                    "(PID %d, priority %d) due to eviction policy", curTime.string(),
                    "(PID %d, score %d state %d) due to eviction policy", curTime.string(),
                    cameraId.string(), packageName.string(), clientPid,
                    getCameraPriorityFromProcState(priorities[priorities.size() - 1]));
                    priorityScores[priorityScores.size() - 1],
                    states[states.size() - 1]);

            for (auto& i : incompatibleClients) {
                msg.appendFormat("\n   - Blocked by existing device %s client for package %s"
                        "(PID %" PRId32 ", priority %" PRId32 ")", i->getKey().string(),
                        String8{i->getValue()->getPackageName()}.string(), i->getOwnerId(),
                        i->getPriority());
                        "(PID %" PRId32 ", score %" PRId32 ", state %" PRId32 ")",
                        i->getKey().string(),
                        String8{i->getValue()->getPackageName()}.string(),
                        i->getOwnerId(), i->getPriority().getScore(),
                        i->getPriority().getState());
                ALOGE("   Conflicts with: Device %s, client package %s (PID %"
                        PRId32 ", priority %" PRId32 ")", i->getKey().string(),
                        PRId32 ", score %" PRId32 ", state %" PRId32 ")", i->getKey().string(),
                        String8{i->getValue()->getPackageName()}.string(), i->getOwnerId(),
                        i->getPriority());
                        i->getPriority().getScore(), i->getPriority().getState());
            }

            // Log the client's attempt
@@ -1299,12 +1292,14 @@ status_t CameraService::handleEvictionsLocked(const String8& cameraId, int clien

            // Log the clients evicted
            logEvent(String8::format("EVICT device %s client held by package %s (PID"
                    " %" PRId32 ", priority %" PRId32 ")\n   - Evicted by device %s client for"
                    " package %s (PID %d, priority %" PRId32 ")",
                    " %" PRId32 ", score %" PRId32 ", state %" PRId32 ")\n - Evicted by device %s client for"
                    " package %s (PID %d, score %" PRId32 ", state %" PRId32 ")",
                    i->getKey().string(), String8{clientSp->getPackageName()}.string(),
                    i->getOwnerId(), i->getPriority(), cameraId.string(),
                    i->getOwnerId(), i->getPriority().getScore(),
                    i->getPriority().getState(), cameraId.string(),
                    packageName.string(), clientPid,
                    getCameraPriorityFromProcState(priorities[priorities.size() - 1])));
                    priorityScores[priorityScores.size() - 1],
                    states[states.size() - 1]));

            // Notify the client of disconnection
            clientSp->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED,
@@ -2142,9 +2137,11 @@ void CameraService::doUserSwitch(const std::vector<int32_t>& newUserIds) {

        // Log the clients evicted
        logEvent(String8::format("EVICT device %s client held by package %s (PID %"
                PRId32 ", priority %" PRId32 ")\n   - Evicted due to user switch.",
                i->getKey().string(), String8{clientSp->getPackageName()}.string(),
                i->getOwnerId(), i->getPriority()));
                PRId32 ", score %" PRId32 ", state %" PRId32 ")\n   - Evicted due"
                " to user switch.", i->getKey().string(),
                String8{clientSp->getPackageName()}.string(),
                i->getOwnerId(), i->getPriority().getScore(),
                i->getPriority().getState()));

    }

@@ -2680,7 +2677,8 @@ String8 CameraService::CameraClientManager::toString() const {
        String8 key = i->getKey();
        int32_t cost = i->getCost();
        int32_t pid = i->getOwnerId();
        int32_t priority = i->getPriority();
        int32_t score = i->getPriority().getScore();
        int32_t state = i->getPriority().getState();
        auto conflicting = i->getConflicting();
        auto clientSp = i->getValue();
        String8 packageName;
@@ -2690,8 +2688,8 @@ String8 CameraService::CameraClientManager::toString() const {
            uid_t clientUid = clientSp->getClientUid();
            clientUserId = multiuser_get_user_id(clientUid);
        }
        ret.appendFormat("\n(Camera ID: %s, Cost: %" PRId32 ", PID: %" PRId32 ", Priority: %"
                PRId32 ", ", key.string(), cost, pid, priority);
        ret.appendFormat("\n(Camera ID: %s, Cost: %" PRId32 ", PID: %" PRId32 ", Score: %"
                PRId32 ", State: %" PRId32, key.string(), cost, pid, score, state);

        if (clientSp.get() != nullptr) {
            ret.appendFormat("User Id: %d, ", clientUserId);
@@ -2713,16 +2711,18 @@ String8 CameraService::CameraClientManager::toString() const {

CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
        const String8& key, const sp<BasicClient>& value, int32_t cost,
        const std::set<String8>& conflictingKeys, int32_t priority, int32_t ownerId) {
        const std::set<String8>& conflictingKeys, int32_t score, int32_t ownerId,
        int32_t state) {

    return std::make_shared<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>(
            key, value, cost, conflictingKeys, priority, ownerId);
            key, value, cost, conflictingKeys, score, ownerId, state);
}

CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
        const sp<BasicClient>& value, const CameraService::DescriptorPtr& partial) {
    return makeClientDescriptor(partial->getKey(), value, partial->getCost(),
            partial->getConflicting(), partial->getPriority(), partial->getOwnerId());
            partial->getConflicting(), partial->getPriority().getScore(),
            partial->getOwnerId(), partial->getPriority().getState());
}

// ----------------------------------------------------------------------------
@@ -2800,7 +2800,9 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) {
        }
        dprintf(fd, "  Device %s is open. Client instance dump:\n",
                cameraId.string());
        dprintf(fd, "    Client priority level: %d\n", clientDescriptor->getPriority());
        dprintf(fd, "    Client priority score: %d state: %d\n",
                clientDescriptor->getPriority().getScore(),
                clientDescriptor->getPriority().getState());
        dprintf(fd, "    Client PID: %d\n", clientDescriptor->getOwnerId());

        auto client = clientDescriptor->getValue();
+2 −12
Original line number Diff line number Diff line
@@ -75,11 +75,6 @@ public:
        API_2 = 2
    };

    // Process state (mirrors frameworks/base/core/java/android/app/ActivityManager.java)
    static const int PROCESS_STATE_NONEXISTENT = -1;
    static const int PROCESS_STATE_TOP = 2;
    static const int PROCESS_STATE_TOP_SLEEPING = 5;

    // 3 second busy timeout when other clients are connecting
    static const nsecs_t DEFAULT_CONNECT_TIMEOUT_NS = 3000000000;

@@ -402,8 +397,8 @@ public:
         * Make a ClientDescriptor object wrapping the given BasicClient strong pointer.
         */
        static DescriptorPtr makeClientDescriptor(const String8& key, const sp<BasicClient>& value,
                int32_t cost, const std::set<String8>& conflictingKeys, int32_t priority,
                int32_t ownerId);
                int32_t cost, const std::set<String8>& conflictingKeys, int32_t score,
                int32_t ownerId, int32_t state);

        /**
         * Make a ClientDescriptor object wrapping the given BasicClient strong pointer with
@@ -775,11 +770,6 @@ private:
     */
    static String8 getFormattedCurrentTime();

    /**
     * Get the camera eviction priority from the current process state given by ActivityManager.
     */
    static int getCameraPriorityFromProcState(int procState);

    static binder::Status makeClient(const sp<CameraService>& cameraService,
            const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
            int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
+60 −22
Original line number Diff line number Diff line
@@ -31,6 +31,43 @@
namespace android {
namespace resource_policy {

class ClientPriority {
public:
    ClientPriority(int32_t score, int32_t state) :
        mScore(score), mState(state) {}

    int32_t getScore() const { return mScore; }
    int32_t getState() const { return mState; }

    bool operator==(const ClientPriority& rhs) const {
        return (this->mScore == rhs.mScore) && (this->mState == rhs.mState);
    }

    bool operator< (const ClientPriority& rhs)  const {
        if (this->mScore == rhs.mScore) {
            return this->mState < rhs.mState;
        } else {
            return this->mScore < rhs.mScore;
        }
    }

    bool operator> (const ClientPriority& rhs) const {
        return rhs < *this;
    }

    bool operator<=(const ClientPriority& rhs) const {
        return !(*this > rhs);
    }

    bool operator>=(const ClientPriority& rhs) const {
        return !(*this < rhs);
    }

private:
        int32_t mScore;
        int32_t mState;
};

// --------------------------------------------------------------------------------

/**
@@ -45,9 +82,9 @@ template<class KEY, class VALUE>
class ClientDescriptor final {
public:
    ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
            const std::set<KEY>& conflictingKeys, int32_t priority, int32_t ownerId);
            const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state);
    ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost, std::set<KEY>&& conflictingKeys,
            int32_t priority, int32_t ownerId);
            int32_t score, int32_t ownerId, int32_t state);

    ~ClientDescriptor();

@@ -69,7 +106,7 @@ public:
    /**
     * Return the priority for this descriptor.
     */
    int32_t getPriority() const;
    const ClientPriority &getPriority() const;

    /**
     * Return the owner ID for this descriptor.
@@ -89,7 +126,7 @@ public:
    /**
     * Set the proirity for this descriptor.
     */
    void setPriority(int32_t priority);
    void setPriority(const ClientPriority& priority);

    // This class is ordered by key
    template<class K, class V>
@@ -100,7 +137,7 @@ private:
    VALUE mValue;
    int32_t mCost;
    std::set<KEY> mConflicting;
    int32_t mPriority;
    ClientPriority mPriority;
    int32_t mOwnerId;
}; // class ClientDescriptor

@@ -111,16 +148,17 @@ bool operator < (const ClientDescriptor<K, V>& a, const ClientDescriptor<K, V>&

template<class KEY, class VALUE>
ClientDescriptor<KEY, VALUE>::ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
        const std::set<KEY>& conflictingKeys, int32_t priority, int32_t ownerId) : mKey{key},
        mValue{value}, mCost{cost}, mConflicting{conflictingKeys}, mPriority{priority},
        const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state) :
        mKey{key}, mValue{value}, mCost{cost}, mConflicting{conflictingKeys},
        mPriority(score, state),
        mOwnerId{ownerId} {}

template<class KEY, class VALUE>
ClientDescriptor<KEY, VALUE>::ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost,
        std::set<KEY>&& conflictingKeys, int32_t priority, int32_t ownerId) :
        std::set<KEY>&& conflictingKeys, int32_t score, int32_t ownerId, int32_t state) :
        mKey{std::forward<KEY>(key)}, mValue{std::forward<VALUE>(value)}, mCost{cost},
        mConflicting{std::forward<std::set<KEY>>(conflictingKeys)}, mPriority{priority},
        mOwnerId{ownerId} {}
        mConflicting{std::forward<std::set<KEY>>(conflictingKeys)},
        mPriority(score, state), mOwnerId{ownerId} {}

template<class KEY, class VALUE>
ClientDescriptor<KEY, VALUE>::~ClientDescriptor() {}
@@ -141,7 +179,7 @@ int32_t ClientDescriptor<KEY, VALUE>::getCost() const {
}

template<class KEY, class VALUE>
int32_t ClientDescriptor<KEY, VALUE>::getPriority() const {
const ClientPriority& ClientDescriptor<KEY, VALUE>::getPriority() const {
    return mPriority;
}

@@ -165,7 +203,7 @@ std::set<KEY> ClientDescriptor<KEY, VALUE>::getConflicting() const {
}

template<class KEY, class VALUE>
void ClientDescriptor<KEY, VALUE>::setPriority(int32_t priority) {
void ClientDescriptor<KEY, VALUE>::setPriority(const ClientPriority& priority) {
    mPriority = priority;
}

@@ -231,7 +269,7 @@ public:
     * Given a map containing owner (pid) -> priority mappings, update the priority of each
     * ClientDescriptor with an owner in this mapping.
     */
    void updatePriorities(const std::map<int32_t,int32_t>& ownerPriorityList);
    void updatePriorities(const std::map<int32_t,ClientPriority>& ownerPriorityList);

    /**
     * Remove all ClientDescriptors.
@@ -383,17 +421,17 @@ ClientManager<KEY, VALUE, LISTENER>::wouldEvictLocked(

    const KEY& key = client->getKey();
    int32_t cost = client->getCost();
    int32_t priority = client->getPriority();
    ClientPriority priority = client->getPriority();
    int32_t owner = client->getOwnerId();

    int64_t totalCost = getCurrentCostLocked() + cost;

    // Determine the MRU of the owners tied for having the highest priority
    int32_t highestPriorityOwner = owner;
    int32_t highestPriority = priority;
    ClientPriority highestPriority = priority;
    for (const auto& i : mClients) {
        int32_t curPriority = i->getPriority();
        if (curPriority >= highestPriority) {
        ClientPriority curPriority = i->getPriority();
        if (curPriority <= highestPriority) {
            highestPriority = curPriority;
            highestPriorityOwner = i->getOwnerId();
        }
@@ -408,7 +446,7 @@ ClientManager<KEY, VALUE, LISTENER>::wouldEvictLocked(
    for (const auto& i : mClients) {
        const KEY& curKey = i->getKey();
        int32_t curCost = i->getCost();
        int32_t curPriority = i->getPriority();
        ClientPriority curPriority = i->getPriority();
        int32_t curOwner = i->getOwnerId();

        bool conflicting = (curKey == key || i->isConflicting(key) ||
@@ -417,13 +455,13 @@ ClientManager<KEY, VALUE, LISTENER>::wouldEvictLocked(
        if (!returnIncompatibleClients) {
            // Find evicted clients

            if (conflicting && curPriority > priority) {
            if (conflicting && curPriority < priority) {
                // Pre-existing conflicting client with higher priority exists
                evictList.clear();
                evictList.push_back(client);
                return evictList;
            } else if (conflicting || ((totalCost > mMaxCost && curCost > 0) &&
                    (curPriority <= priority) &&
                    (curPriority >= priority) &&
                    !(highestPriorityOwner == owner && owner == curOwner))) {
                // Add a pre-existing client to the eviction list if:
                // - We are adding a client with higher priority that conflicts with this one.
@@ -437,7 +475,7 @@ ClientManager<KEY, VALUE, LISTENER>::wouldEvictLocked(
        } else {
            // Find clients preventing the incoming client from being added

            if (curPriority > priority && (conflicting || (totalCost > mMaxCost && curCost > 0))) {
            if (curPriority < priority && (conflicting || (totalCost > mMaxCost && curCost > 0))) {
                // Pre-existing conflicting client with higher priority exists
                evictList.push_back(i);
            }
@@ -524,7 +562,7 @@ std::vector<int32_t> ClientManager<KEY, VALUE, LISTENER>::getAllOwners() const {

template<class KEY, class VALUE, class LISTENER>
void ClientManager<KEY, VALUE, LISTENER>::updatePriorities(
        const std::map<int32_t,int32_t>& ownerPriorityList) {
        const std::map<int32_t,ClientPriority>& ownerPriorityList) {
    Mutex::Autolock lock(mLock);
    for (auto& i : mClients) {
        auto j = ownerPriorityList.find(i->getOwnerId());