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

Commit b0f7df30 authored by Jyoti Bhayana's avatar Jyoti Bhayana
Browse files

Camera multi-client priority changes update

When multiple clients have opened the camera in shared mode, and the
priority of any client changes in the middle of session then notify
the clients of any shared client priority changes from either primary
to secondary or vice versa.

Flag: com.android.internal.camera.flags.camera_multi_client
Bug: 392781619
Test: run CTS test SharedCameraTest#testClientSharedAccessPriorityChanged
Change-Id: I50111a5338521c2e25bbf049e97b707f01ce6773
parent 462c24b3
Loading
Loading
Loading
Loading
+139 −24
Original line number Diff line number Diff line
@@ -3221,6 +3221,56 @@ void CameraService::notifyMonitoredUids(const std::unordered_set<uid_t> &notifyU
    }
}

void CameraService::updateSharedClientAccessPriorities(std::vector<int> sharedClientPids) {
    Mutex::Autolock lock(mServiceLock);
    if (!flags::camera_multi_client() || sharedClientPids.empty()) {
        return;
    }
    std::vector<int> scores(sharedClientPids.size());
    std::vector<int> states(sharedClientPids.size());
    status_t err = ProcessInfoService::getProcessStatesScoresFromPids(sharedClientPids.size(),
                &sharedClientPids[0], /*out*/&states[0], /*out*/&scores[0]);
    if (err != OK) {
        return;
    }
    for (size_t i = 0; i < sharedClientPids.size(); i++) {
        auto clientDescriptorPtr = mActiveClientManager.getSharedClient(sharedClientPids[i]);
        if (clientDescriptorPtr == nullptr) {
            continue;
        }
        const auto& clientPriority = clientDescriptorPtr->getPriority();
        int score = clientPriority.getScore();
        int state = clientPriority.getState();
        if ((score != scores[i])  || (state != states[i])){
            clientDescriptorPtr->setPriority(resource_policy::ClientPriority(scores[i], states[i],
                    false, 0));
            notifySharedClientPrioritiesChanged(clientDescriptorPtr->getKey());
        }
    }
}

void CameraService::notifySharedClientPrioritiesChanged(const std::string& cameraId) {
    if (!flags::camera_multi_client()) {
        return;
    }
    auto primaryClientDesc = mActiveClientManager.getPrimaryClient(cameraId);
    if (primaryClientDesc == nullptr) {
        return;
    }
    auto primaryClient = primaryClientDesc->getValue();
    if (primaryClient == nullptr) {
        return;
    }
    auto highestPriorityClient = mActiveClientManager.getHighestPrioritySharedClient(cameraId);
    if (highestPriorityClient == primaryClient) {
        return;
    }
    highestPriorityClient->setPrimaryClient(true);
    highestPriorityClient->notifyClientSharedAccessPriorityChanged(true);
    primaryClient->setPrimaryClient(false);
    primaryClient->notifyClientSharedAccessPriorityChanged(false);
}

Status CameraService::notifyDeviceStateChange(int64_t newState) {
    const int pid = getCallingPid();
    const int selfPid = getpid();
@@ -4357,6 +4407,10 @@ status_t CameraService::BasicClient::notifyCameraOpening() {

    sCameraService->mUidPolicy->registerMonitorUid(getClientUid(), /*openCamera*/ true);

    if (flags::camera_multi_client() && mSharedMode) {
        sCameraService->mUidPolicy->addSharedClientPid(getClientUid(), getClientCallingPid());
    }

    // Notify listeners of camera open/close status
    sCameraService->updateOpenCloseStatus(mCameraIdStr, true /*open*/, getPackageName(),
            mSharedMode);
@@ -4515,6 +4569,10 @@ status_t CameraService::BasicClient::notifyCameraClosing() {

    sCameraService->mUidPolicy->unregisterMonitorUid(getClientUid(), /*closeCamera*/ true);

    if (flags::camera_multi_client() && mSharedMode) {
        sCameraService->mUidPolicy->removeSharedClientPid(getClientUid(), getClientCallingPid());
    }

    // Notify listeners of camera open/close status
    sCameraService->updateOpenCloseStatus(mCameraIdStr, false /*open*/, getPackageName(),
            mSharedMode);
@@ -4783,21 +4841,35 @@ void CameraService::UidPolicy::onUidIdle(uid_t uid, bool /* disabled */) {
void CameraService::UidPolicy::onUidStateChanged(uid_t uid, int32_t procState,
        int64_t procStateSeq __unused, int32_t capability __unused) {
    bool procStateChange = false;
    std::vector<int> sharedPids;
    {
        Mutex::Autolock _l(mUidLock);
        if (mMonitoredUids.find(uid) != mMonitoredUids.end() &&
                mMonitoredUids[uid].procState != procState) {
        if (mMonitoredUids.find(uid) != mMonitoredUids.end()) {
            if (mMonitoredUids[uid].procState != procState) {
                mMonitoredUids[uid].procState = procState;
                procStateChange = true;
            }
            if (flags::camera_multi_client()) {
                std::unordered_set<int> sharedClientPids = mMonitoredUids[uid].sharedClientPids;
                if (!sharedClientPids.empty()) {
                  sharedPids.assign(sharedClientPids.begin(), sharedClientPids.end());
                }
            }
        }
    }

    if (procStateChange) {
    sp<CameraService> service = mService.promote();
    if (procStateChange) {
        if (service != nullptr) {
            service->notifyMonitoredUids();
        }
    }

    if (flags::camera_multi_client() && !sharedPids.empty()) {
        if (service != nullptr) {
            service->updateSharedClientAccessPriorities(sharedPids);
        }
    }
}

/**
@@ -4810,6 +4882,7 @@ void CameraService::UidPolicy::onUidStateChanged(uid_t uid, int32_t procState,
 */
void CameraService::UidPolicy::onUidProcAdjChanged(uid_t uid, int32_t adj) {
    std::unordered_set<uid_t> notifyUidSet;
    std::vector<int> sharedPids;
    {
        Mutex::Autolock _l(mUidLock);
        auto it = mMonitoredUids.find(uid);
@@ -4833,15 +4906,28 @@ void CameraService::UidPolicy::onUidProcAdjChanged(uid_t uid, int32_t adj) {
                }
            }
            it->second.procAdj = adj;
            if (flags::camera_multi_client()) {
                std::unordered_set<int> sharedClientPids = it->second.sharedClientPids;
                if (!sharedClientPids.empty()) {
                    sharedPids.assign(sharedClientPids.begin(), sharedClientPids.end());
                }
            }
        }
    }

    if (notifyUidSet.size() > 0) {
    sp<CameraService> service = mService.promote();

    if (notifyUidSet.size() > 0) {
        if (service != nullptr) {
            service->notifyMonitoredUids(notifyUidSet);
        }
    }

    if (flags::camera_multi_client() && !sharedPids.empty()) {
        if (service != nullptr) {
            service->updateSharedClientAccessPriorities(sharedPids);
        }
    }
}

/**
@@ -4975,6 +5061,20 @@ void CameraService::UidPolicy::removeOverrideUid(uid_t uid, const std::string &c
    updateOverrideUid(uid, callingPackage, false, false);
}

void CameraService::UidPolicy::addSharedClientPid(uid_t uid, int pid) {
    Mutex::Autolock _l(mUidLock);
    if (mMonitoredUids.find(uid) != mMonitoredUids.end()) {
        mMonitoredUids[uid].sharedClientPids.insert(pid);
    }
}

void CameraService::UidPolicy::removeSharedClientPid(uid_t uid, int pid) {
    Mutex::Autolock _l(mUidLock);
    if (mMonitoredUids.find(uid) != mMonitoredUids.end()) {
        mMonitoredUids[uid].sharedClientPids.erase(pid);
    }
}

void CameraService::UidPolicy::binderDied(const wp<IBinder>& /*who*/) {
    Mutex::Autolock _l(mUidLock);
    ALOGV("UidPolicy: ActivityManager has died");
@@ -5281,32 +5381,47 @@ sp<CameraService::BasicClient> CameraService::CameraClientManager::getCameraClie
    return descriptor->getValue();
}

void CameraService::CameraClientManager::remove(const CameraService::DescriptorPtr& value) {
    ClientManager::remove(value);
sp<CameraService::BasicClient> CameraService::CameraClientManager::getHighestPrioritySharedClient(
        const std::string& id) const {
    if (!flags::camera_multi_client()) {
        return;
        return sp<BasicClient>{nullptr};
    }
    auto clientToRemove = value->getValue();
    if ((clientToRemove.get() != nullptr) && clientToRemove->mSharedMode) {
      bool primaryClient = false;
      status_t ret = clientToRemove->isPrimaryClient(&primaryClient);
      if ((ret == OK) && primaryClient) {
            // Primary client is being removed. Find the next higher priority
            // client to become primary client.
            auto clientDescriptor = get(value->getKey());
    auto clientDescriptor = get(id);
    if (clientDescriptor == nullptr) {
        ALOGV("CameraService::CameraClientManager::no other clients are using same camera");
                return;
        return sp<BasicClient>{nullptr};
    }
    if (!clientDescriptor->getSharedMode()) {
        return sp<BasicClient>{nullptr};
    }
    resource_policy::ClientPriority highestPriority = clientDescriptor->getPriority();
    sp<BasicClient> highestPriorityClient = clientDescriptor->getValue();
            if (highestPriorityClient.get() != nullptr) {
    if (highestPriorityClient.get() == nullptr) {
        return sp<BasicClient>{nullptr};
    }
    for (auto& i : getAll()) {
                    if ((i->getKey() == value->getKey()) && (i->getPriority() < highestPriority)) {
        if ((i->getKey() == id) && (i->getSharedMode()) && (i->getPriority() < highestPriority)) {
            highestPriority = i->getPriority();
            highestPriorityClient = i->getValue();
        }
    }
    return highestPriorityClient;
}

void CameraService::CameraClientManager::remove(const CameraService::DescriptorPtr& value) {
    ClientManager::remove(value);
    if (!flags::camera_multi_client()) {
        return;
    }
    auto clientToRemove = value->getValue();
    if ((clientToRemove.get() != nullptr) && clientToRemove->mSharedMode) {
        bool primaryClient = false;
        status_t ret = clientToRemove->isPrimaryClient(&primaryClient);
        if ((ret == OK) && primaryClient) {
            // Primary client is being removed. Find the next higher priority
            // client to become primary client.
            auto highestPriorityClient = getHighestPrioritySharedClient(value->getKey());
            if (highestPriorityClient != nullptr) {
                highestPriorityClient->setPrimaryClient(true);
                highestPriorityClient->notifyClientSharedAccessPriorityChanged(true);
            }
+24 −0
Original line number Diff line number Diff line
@@ -644,6 +644,12 @@ public:
         */
        sp<CameraService::BasicClient> getCameraClient(const std::string& id) const;

        /**
         * Return a strong pointer to the highest priority client among all the clients which
         * have opened this camera ID in shared mode, or empty if none exists.
         */
        sp<CameraService::BasicClient> getHighestPrioritySharedClient(const std::string& id) const;

        /**
         * Return a string describing the current state.
         */
@@ -852,6 +858,9 @@ private:
        void registerMonitorUid(uid_t uid, bool openCamera);
        void unregisterMonitorUid(uid_t uid, bool closeCamera);

        void addSharedClientPid(uid_t uid, int pid);
        void removeSharedClientPid(uid_t uid, int pid);

        // Implementation of IServiceManager::LocalRegistrationCallback
        virtual void onServiceRegistration(const String16& name,
                        const sp<IBinder>& binder) override;
@@ -869,6 +878,9 @@ private:
            int32_t procAdj;
            bool hasCamera;
            size_t refCount;
            // This field is only valid when camera has been opened in shared mode, to adjust the
            // priority of active clients based on the latest process score and state.
            std::unordered_set<int> sharedClientPids;
        };

        Mutex mUidLock;
@@ -1102,6 +1114,18 @@ private:
    void finishConnectLocked(const sp<BasicClient>& client, const DescriptorPtr& desc,
            int oomScoreOffset, bool systemNativeClient);

    /**
     * When multiple clients open the camera in shared mode, adjust the priority of active clients
     * based on the latest process score and state.
     */
    void updateSharedClientAccessPriorities(std::vector<int> sharedClientPids);

    /**
     * Update all clients on any changes in the primary or secondary client status if the priority
     * of any client changes when multiple clients are sharing a camera.
     */
    void notifySharedClientPrioritiesChanged(const std::string& cameraId);

    /**
     * Returns the underlying camera Id string mapped to a camera id int
     * Empty string is returned when the cameraIdInt is invalid.
+20 −0
Original line number Diff line number Diff line
@@ -417,6 +417,12 @@ public:
     */
    std::vector<int32_t> getAllOwners() const;

    /**
     * Return the ClientDescriptor for a client which has opened the camera in
     * shared mode corresponding to the given pid.
     */
    std::shared_ptr<ClientDescriptor<KEY, VALUE>> getSharedClient(int pid) const;

    /**
     * Return the ClientDescriptor corresponding to the given key, or an empty shared pointer
     * if none exists.
@@ -684,6 +690,20 @@ std::vector<int32_t> ClientManager<KEY, VALUE, LISTENER>::getAllOwners() const {
    return std::vector<int32_t>(owners.begin(), owners.end());
}

template<class KEY, class VALUE, class LISTENER>
std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE, LISTENER>::getSharedClient(
        int pid) const {
    Mutex::Autolock lock(mLock);
    if (flags::camera_multi_client()) {
        for (const auto& i : mClients) {
            if ((i->getOwnerId() == pid) && (i->getSharedMode())) {
                return i;
            }
        }
    }
    return std::shared_ptr<ClientDescriptor<KEY, VALUE>>(nullptr);
}

template<class KEY, class VALUE, class LISTENER>
void ClientManager<KEY, VALUE, LISTENER>::updatePriorities(
        const std::map<int32_t,ClientPriority>& ownerPriorityList) {