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

Commit dddb7556 authored by Austin Borger's avatar Austin Borger
Browse files

UidObserver / Camera: Track the OOM adj of a uid via UidObserver.

Previously, onUidProcAdjChanged merely signaled that the OOM adj of a
uid changed, but did not provide the actual OOM adj score. Having this
information allows the camera service to cut out redundant calls to
onCameraAccessPrioritiesChanged and avoid overwhelming apps.

The number of calls to onCameraAccessPrioritiesChanged is reduced by
only signaling when it's likely the uid owning a camera would lose
access to it if another uid tried to open that camera. This is opposed
to the status quo, which signals every time a watched uid changes its
OOM adj, which is highly inefficient.

Bug: 274486653
Test: -- on physical device:
      -- testCamera2AccessCallbackInSplitMode x10
      -- ActivityManagerServiceTest
      -- ActivityManagerProcessStateTest
      -- ActivityManagerFgsBgStartTest
      -- UidObserverControllerTest
      -- Alternate focus in split screen between Camera2 + GCA x20
Change-Id: I3e00490b835aefb74443c047e02c47d784e45f67
parent 95d65e20
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1694,7 +1694,7 @@ void AudioPolicyService::UidPolicy::onUidStateChanged(uid_t uid,
    }
}

void AudioPolicyService::UidPolicy::onUidProcAdjChanged(uid_t uid __unused) {
void AudioPolicyService::UidPolicy::onUidProcAdjChanged(uid_t uid __unused, int32_t adj __unused) {
}

void AudioPolicyService::UidPolicy::updateOverrideUid(uid_t uid, bool active, bool insert) {
+1 −1
Original line number Diff line number Diff line
@@ -484,7 +484,7 @@ private:
        void onUidIdle(uid_t uid, bool disabled) override;
        void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq,
                int32_t capability) override;
        void onUidProcAdjChanged(uid_t uid) override;
        void onUidProcAdjChanged(uid_t uid, int32_t adj) override;

        void addOverrideUid(uid_t uid, bool active) { updateOverrideUid(uid, active, true); }
        void removeOverrideUid(uid_t uid) { updateOverrideUid(uid, false, false); }
+63 −13
Original line number Diff line number Diff line
@@ -2602,6 +2602,19 @@ void CameraService::notifyMonitoredUids() {
    }
}

void CameraService::notifyMonitoredUids(const std::unordered_set<uid_t> &notifyUidSet) {
    Mutex::Autolock lock(mStatusListenerLock);

    for (const auto& it : mListenerList) {
        if (notifyUidSet.find(it->getListenerUid()) != notifyUidSet.end()) {
            ALOGV("%s: notifying uid %d", __FUNCTION__, it->getListenerUid());
            auto ret = it->getListener()->onCameraAccessPrioritiesChanged();
            it->handleBinderStatus(ret, "%s: Failed to trigger permission callback for %d:%d: %d",
                    __FUNCTION__, it->getListenerUid(), it->getListenerPid(), ret.exceptionCode());
        }
    }
}

Status CameraService::notifyDeviceStateChange(int64_t newState) {
    const int pid = CameraThreadState::getCallingPid();
    const int selfPid = getpid();
@@ -2823,7 +2836,7 @@ Status CameraService::addListenerHelper(const sp<ICameraServiceListener>& listen
        // permissions the listener process has / whether it is a vendor listener. Since it might be
        // eligible to listen to other camera ids.
        mListenerList.emplace_back(serviceListener);
        mUidPolicy->registerMonitorUid(clientUid);
        mUidPolicy->registerMonitorUid(clientUid, /*openCamera*/false);
    }

    /* Collect current devices and status */
@@ -2891,7 +2904,7 @@ Status CameraService::removeListener(const sp<ICameraServiceListener>& listener)
        Mutex::Autolock lock(mStatusListenerLock);
        for (auto it = mListenerList.begin(); it != mListenerList.end(); it++) {
            if (IInterface::asBinder((*it)->getListener()) == IInterface::asBinder(listener)) {
                mUidPolicy->unregisterMonitorUid((*it)->getListenerUid());
                mUidPolicy->unregisterMonitorUid((*it)->getListenerUid(), /*closeCamera*/false);
                IInterface::asBinder(listener)->unlinkToDeath(*it);
                mListenerList.erase(it);
                return Status::ok();
@@ -3680,7 +3693,7 @@ status_t CameraService::BasicClient::startCameraOps() {
    // Transition device availability listeners from PRESENT -> NOT_AVAILABLE
    sCameraService->updateStatus(StatusInternal::NOT_AVAILABLE, mCameraIdStr);

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

    // Notify listeners of camera open/close status
    sCameraService->updateOpenCloseStatus(mCameraIdStr, true/*open*/, mClientPackageName);
@@ -3788,7 +3801,7 @@ status_t CameraService::BasicClient::finishCameraOps() {
    }
    mOpsCallback.clear();

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

    // Notify listeners of camera open/close status
    sCameraService->updateOpenCloseStatus(mCameraIdStr, false/*open*/, mClientPackageName);
@@ -3988,24 +4001,51 @@ void CameraService::UidPolicy::onUidStateChanged(uid_t uid, int32_t procState,
    }
}

void CameraService::UidPolicy::onUidProcAdjChanged(uid_t uid) {
    bool procAdjChange = false;
/**
 * When the OOM adj of the uid owning the camera changes, a different uid waiting on camera
 * privileges may take precedence if the owner's new OOM adj is greater than the waiting package.
 * Here, we track which monitoredUid has the camera, and track its adj relative to other
 * monitoredUids. If it is revised above some other monitoredUid, signal
 * onCameraAccessPrioritiesChanged. This only needs to capture the case where there are two
 * foreground apps in split screen - state changes will capture all other cases.
 */
void CameraService::UidPolicy::onUidProcAdjChanged(uid_t uid, int32_t adj) {
    std::unordered_set<uid_t> notifyUidSet;
    {
        Mutex::Autolock _l(mUidLock);
        if (mMonitoredUids.find(uid) != mMonitoredUids.end()) {
            procAdjChange = true;
        auto it = mMonitoredUids.find(uid);

        if (it != mMonitoredUids.end()) {
            if (it->second.hasCamera) {
                for (auto &monitoredUid : mMonitoredUids) {
                    if (monitoredUid.first != uid && adj > monitoredUid.second.procAdj) {
                        notifyUidSet.emplace(monitoredUid.first);
                    }
                }
                notifyUidSet.emplace(uid);
            } else {
                for (auto &monitoredUid : mMonitoredUids) {
                    if (monitoredUid.second.hasCamera && adj < monitoredUid.second.procAdj) {
                        notifyUidSet.emplace(uid);
                    }
                }
            }
            it->second.procAdj = adj;
        }
    }

    if (procAdjChange) {
    if (notifyUidSet.size() > 0) {
        sp<CameraService> service = mService.promote();
        if (service != nullptr) {
            service->notifyMonitoredUids();
            service->notifyMonitoredUids(notifyUidSet);
        }
    }
}

void CameraService::UidPolicy::registerMonitorUid(uid_t uid) {
/**
 * Register a uid for monitoring, and note whether it owns a camera.
 */
void CameraService::UidPolicy::registerMonitorUid(uid_t uid, bool openCamera) {
    Mutex::Autolock _l(mUidLock);
    auto it = mMonitoredUids.find(uid);
    if (it != mMonitoredUids.end()) {
@@ -4013,18 +4053,28 @@ void CameraService::UidPolicy::registerMonitorUid(uid_t uid) {
    } else {
        MonitoredUid monitoredUid;
        monitoredUid.procState = ActivityManager::PROCESS_STATE_NONEXISTENT;
        monitoredUid.procAdj = resource_policy::UNKNOWN_ADJ;
        monitoredUid.refCount = 1;
        mMonitoredUids.emplace(std::pair<uid_t, MonitoredUid>(uid, monitoredUid));
        it = mMonitoredUids.emplace(std::pair<uid_t, MonitoredUid>(uid, monitoredUid)).first;
    }

    if (openCamera) {
        it->second.hasCamera = true;
    }
}

void CameraService::UidPolicy::unregisterMonitorUid(uid_t uid) {
/**
 * Unregister a uid for monitoring, and note whether it lost ownership of a camera.
 */
void CameraService::UidPolicy::unregisterMonitorUid(uid_t uid, bool closeCamera) {
    Mutex::Autolock _l(mUidLock);
    auto it = mMonitoredUids.find(uid);
    if (it != mMonitoredUids.end()) {
        it->second.refCount--;
        if (it->second.refCount == 0) {
            mMonitoredUids.erase(it);
        } else if (closeCamera) {
            it->second.hasCamera = false;
        }
    } else {
        ALOGE("%s: Trying to unregister uid: %d which is not monitored!", __FUNCTION__, uid);
+6 −3
Original line number Diff line number Diff line
@@ -233,6 +233,7 @@ public:

    // Monitored UIDs availability notification
    void                notifyMonitoredUids();
    void                notifyMonitoredUids(const std::unordered_set<uid_t> &notifyUidSet);

    // Stores current open session device info in temp file.
    void cacheDump();
@@ -763,13 +764,13 @@ private:
        void onUidIdle(uid_t uid, bool disabled) override;
        void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq,
                int32_t capability) override;
        void onUidProcAdjChanged(uid_t uid) override;
        void onUidProcAdjChanged(uid_t uid, int adj) override;

        void addOverrideUid(uid_t uid, String16 callingPackage, bool active);
        void removeOverrideUid(uid_t uid, String16 callingPackage);

        void registerMonitorUid(uid_t uid);
        void unregisterMonitorUid(uid_t uid);
        void registerMonitorUid(uid_t uid, bool openCamera);
        void unregisterMonitorUid(uid_t uid, bool closeCamera);

        // Implementation of IServiceManager::LocalRegistrationCallback
        virtual void onServiceRegistration(const String16& name,
@@ -784,6 +785,8 @@ private:

        struct MonitoredUid {
            int32_t procState;
            int32_t procAdj;
            bool hasCamera;
            size_t refCount;
        };

+2 −2
Original line number Diff line number Diff line
@@ -264,7 +264,7 @@ status_t CameraOfflineSessionClient::startCameraOps() {
    mOpsActive = true;

    // Transition device state to OPEN
    sCameraService->mUidPolicy->registerMonitorUid(mClientUid);
    sCameraService->mUidPolicy->registerMonitorUid(mClientUid, /*openCamera*/true);

    return OK;
}
@@ -288,7 +288,7 @@ status_t CameraOfflineSessionClient::finishCameraOps() {
    }
    mOpsCallback.clear();

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

    return OK;
}
Loading