cameraservice handleEvictionsLocked函数简单分析。

来源:互联网 发布:迷你笔记本电脑知乎 编辑:程序博客网 时间:2024/06/05 14:28
status_t CameraService::handleEvictionsLocked(const String8& cameraId, int clientPid,        apiLevel effectiveApiLevel, const sp<IBinder>& remoteCallback, const String8& packageName,        /*out*/        sp<BasicClient>* client,        std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>* partial) {    ATRACE_CALL();    status_t ret = NO_ERROR;    std::vector<DescriptorPtr> evictedClients;    DescriptorPtr clientDescriptor;    {        if (effectiveApiLevel == API_1) {            // If we are using API1, any existing client for this camera ID with the same remote            // should be returned rather than evicted to allow MediaRecorder to work properly.            auto current = mActiveClientManager.get(cameraId);           if (current != nullptr) {                auto clientSp = current->getValue();                if (clientSp.get() != nullptr) { // should never be needed                    if (!clientSp->canCastToApiClient(effectiveApiLevel)) {                        ALOGW("CameraService connect called from same client, but with a different"                                " API level, evicting prior client...");                    } else if (clientSp->getRemote() == remoteCallback) {                        ALOGI("CameraService::connect X (PID %d) (second call from same"                                " app binder, returning the same client)", clientPid);                      *client = clientSp;                        return NO_ERROR;                    }                }            }        }       // Get current active client PIDs        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);        // Get priorites of all active PIDs        ProcessInfoService::getProcessStatesFromPids(ownerPids.size(), &ownerPids[0],                /*out*/&priorities[0]);        // Update all active clients' priorities        std::map<int,int> pidToPriorityMap;     //!++        ALOGI("Incoming clientPid(%d) packageName(%s) priorities(%d)",clientPid,packageName.string(),priorities[priorities.size() - 1]);        if(strcmp("mtk_vt_use", packageName) == 0)        {            ALOGI("Incoming client is mtk_vt_use, set priorities(old:%d) = 0",priorities[priorities.size() - 1]);            priorities[priorities.size() - 1] = 0;        }        //!--                //  modify for preventing 3rd party pre-empty beginfor(size_t n = 0; n< 2; n++ ){String8 id = String8::format("%zu", n);String8 pkg;if(mActiveClientManager.getCameraClient(id)!=0){pkg = String8(mActiveClientManager.getCameraClient(id)->getPackageName().string());}else{ALOGI("Camera[%zu] has no client NOW",n);continue;}if(0 == strcmp("com.mediatek.camera",pkg.string())&& 0 == strcmp("com.google.android.apps.photos",packageName.string())){ALOGI("mediatek camera is running, google photo is excluded");return BAD_VALUE;}}//modify for preventing 3rd party pre-empty end            for (size_t i = 0; i < ownerPids.size() - 1; i++) {            //!++            //make sure VT has top priority            if( mActiveClientManager.getCameraClient(cameraId) != 0 &&                strcmp("mtk_vt_use", String8(mActiveClientManager.getCameraClient(cameraId)->getPackageName().string())) == 0)          {                int clientPid_vt = mActiveClientManager.getCameraClient(cameraId)->getClientPid();                if(clientPid_vt == ownerPids[i])                {                    priorities[i] = 0;                   ALOGI("i(%zu) pid(%d) => mtk_vt_use, set priorities(old:%d) = 0",i,ownerPids[i],priorities[i]);                }            }            else if(strcmp("mtk_vt_use", packageName) == 0)            {                priorities[i] = INT_MAX;              ALOGI("i(%zu) pid(%d) not mtk_vt_use, set priorities(old:%d) = INT_MAX",i,ownerPids[i],priorities[i]);            }            ALOGI("i(%zu) pid(%d) priorities(%d),Priority(%d)",i,ownerPids[i],priorities[i],getCameraPriorityFromProcState(priorities[i]));            //!--            pidToPriorityMap.emplace(ownerPids[i], getCameraPriorityFromProcState(priorities[i]));        }       mActiveClientManager.updatePriorities(pidToPriorityMap);        // Get state for the given cameraId        auto state = getCameraState(cameraId);        if (state == nullptr) {            ALOGE("CameraService::connect X (PID %d) rejected (no camera device with ID %s)",               clientPid, cameraId.string());            // Should never get here because validateConnectLocked should have errored out            return BAD_VALUE;        }        // Make descriptor for incoming client        clientDescriptor = CameraClientManager::makeClientDescriptor(cameraId,                sp<BasicClient>{nullptr}, static_cast<int32_t>(state->getCost()),                state->getConflicting(),                getCameraPriorityFromProcState(priorities[priorities.size() - 1]), clientPid);        // Find clients that would be evicted        auto evicted = mActiveClientManager.wouldEvict(clientDescriptor);        // If the incoming client was 'evicted,' higher priority clients have the camera in the        // background, so we cannot do evictions        if (std::find(evicted.begin(), evicted.end(), clientDescriptor) != evicted.end()) {            ALOGE("CameraService::connect X (PID %d) rejected (existing client(s) with higher"                    " priority).", clientPid);            sp<BasicClient> clientSp = clientDescriptor->getValue();            String8 curTime = getFormattedCurrentTime();            auto incompatibleClients =                    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(),                    cameraId.string(), packageName.string(), clientPid,                    getCameraPriorityFromProcState(priorities[priorities.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());                ALOGE("   Conflicts with: Device %s, client package %s (PID %"                       PRId32 ", priority %" PRId32 ")", i->getKey().string(),                        String8{i->getValue()->getPackageName()}.string(), i->getOwnerId(),                        i->getPriority());            }            // Log the client's attempt            Mutex::Autolock l(mLogLock);            mEventLog.add(msg);            return -EBUSY;        }      for (auto& i : evicted) {            sp<BasicClient> clientSp = i->getValue();            if (clientSp.get() == nullptr) {                ALOGE("%s: Invalid state: Null client in active client list.", __FUNCTION__);                // TODO: Remove this              LOG_ALWAYS_FATAL("%s: Invalid state for CameraService, null client in active list",                        __FUNCTION__);                mActiveClientManager.remove(i);                continue;            }           ALOGE("CameraService::connect evicting conflicting client for camera ID %s",                    i->getKey().string());            evictedClients.push_back(i);            // 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 ")",                    i->getKey().string(), String8{clientSp->getPackageName()}.string(),                    i->getOwnerId(), i->getPriority(), cameraId.string(),                    packageName.string(), clientPid,                    getCameraPriorityFromProcState(priorities[priorities.size() - 1])));            // Notify the client of disconnection            clientSp->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED,                    CaptureResultExtras());        }    }    // Do not hold mServiceLock while disconnecting clients, but retain the condition blocking    // other clients from connecting in mServiceLockWrapper if held    mServiceLock.unlock();    // Clear caller identity temporarily so client disconnect PID checks work correctly    int64_t token = IPCThreadState::self()->clearCallingIdentity();   // Destroy evicted clients    for (auto& i : evictedClients) {        // Disconnect is blocking, and should only have returned when HAL has cleaned up        i->getValue()->disconnect(); // Clients will remove themselves from the active client list    }    IPCThreadState::self()->restoreCallingIdentity(token);  for (const auto& i : evictedClients) {        ALOGV("%s: Waiting for disconnect to complete for client for device %s (PID %" PRId32 ")",                __FUNCTION__, i->getKey().string(), i->getOwnerId());        ret = mActiveClientManager.waitUntilRemoved(i, DEFAULT_DISCONNECT_TIMEOUT_NS);       if (ret == TIMED_OUT) {            ALOGE("%s: Timed out waiting for client for device %s to disconnect, "                    "current clients:\n%s", __FUNCTION__, i->getKey().string(),                    mActiveClientManager.toString().string());            return -EBUSY;        }      if (ret != NO_ERROR) {            ALOGE("%s: Received error waiting for client for device %s to disconnect: %s (%d), "                    "current clients:\n%s", __FUNCTION__, i->getKey().string(), strerror(-ret),                    ret, mActiveClientManager.toString().string());            return ret;        }    }    evictedClients.clear();    // Once clients have been disconnected, relock    mServiceLock.lock();    // Check again if the device was unplugged or something while we weren't holding mServiceLock    if ((ret = checkIfDeviceIsUsable(cameraId)) != NO_ERROR) {        return ret;    }    *partial = clientDescriptor;    return NO_ERROR;}

阅读全文
0 0
原创粉丝点击