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

Commit b5f5cc5d authored by Eino-Ville Talvala's avatar Eino-Ville Talvala Committed by Android (Google) Code Review
Browse files

Merge "Camera: Move app ops to start/stop of streaming" into sc-dev

parents 58cf29d0 178e823b
Loading
Loading
Loading
Loading
+92 −33
Original line number Diff line number Diff line
@@ -2780,19 +2780,20 @@ CameraService::BasicClient::BasicClient(const sp<CameraService>& cameraService,
        const String8& cameraIdStr, int cameraFacing, int sensorOrientation,
        int clientPid, uid_t clientUid,
        int servicePid):
        mDestructionStarted(false),
        mCameraIdStr(cameraIdStr), mCameraFacing(cameraFacing), mOrientation(sensorOrientation),
        mClientPackageName(clientPackageName), mClientFeatureId(clientFeatureId),
        mClientPid(clientPid), mClientUid(clientUid),
        mServicePid(servicePid),
        mDisconnected(false), mUidIsTrusted(false),
        mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE),
        mRemoteBinder(remoteCallback)
        mRemoteBinder(remoteCallback),
        mOpsActive(false),
        mOpsStreaming(false)
{
    if (sCameraService == nullptr) {
        sCameraService = cameraService;
    }
    mOpsActive = false;
    mDestructionStarted = false;

    // In some cases the calling code has no access to the package it runs under.
    // For example, NDK camera API.
@@ -2927,32 +2928,14 @@ bool CameraService::BasicClient::isValidAudioRestriction(int32_t mode) {
    }
}

status_t CameraService::BasicClient::startCameraOps() {
    ATRACE_CALL();

    {
        ALOGV("%s: Start camera ops, package name = %s, client UID = %d",
              __FUNCTION__, String8(mClientPackageName).string(), mClientUid);
    }
    if (mAppOpsManager != nullptr) {
        // Notify app ops that the camera is not available
        mOpsCallback = new OpsCallback(this);
        int32_t res;
        mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA,
                mClientPackageName, mOpsCallback);
        res = mAppOpsManager->startOpNoThrow(AppOpsManager::OP_CAMERA, mClientUid,
                mClientPackageName, /*startIfModeDefault*/ false, mClientFeatureId,
                String16("start camera ") + String16(mCameraIdStr));

        if (res == AppOpsManager::MODE_ERRORED) {
status_t CameraService::BasicClient::handleAppOpMode(int32_t mode) {
    if (mode == AppOpsManager::MODE_ERRORED) {
        ALOGI("Camera %s: Access for \"%s\" has been revoked",
                mCameraIdStr.string(), String8(mClientPackageName).string());
        return PERMISSION_DENIED;
        }

    } else if (!mUidIsTrusted && mode == AppOpsManager::MODE_IGNORED) {
        // If the calling Uid is trusted (a native service), the AppOpsManager could
        // return MODE_IGNORED. Do not treat such case as error.
        if (!mUidIsTrusted && res == AppOpsManager::MODE_IGNORED) {
        bool isUidActive = sCameraService->mUidPolicy->isUidActive(mClientUid,
                mClientPackageName);
        bool isCameraPrivacyEnabled =
@@ -2965,6 +2948,30 @@ status_t CameraService::BasicClient::startCameraOps() {
            return -EACCES;
        }
    }
    return OK;
}

status_t CameraService::BasicClient::startCameraOps() {
    ATRACE_CALL();

    {
        ALOGV("%s: Start camera ops, package name = %s, client UID = %d",
              __FUNCTION__, String8(mClientPackageName).string(), mClientUid);
    }
    if (mAppOpsManager != nullptr) {
        // Notify app ops that the camera is not available
        mOpsCallback = new OpsCallback(this);
        mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA,
                mClientPackageName, mOpsCallback);

        // Just check for camera acccess here on open - delay startOp until
        // camera frames start streaming in startCameraStreamingOps
        int32_t mode = mAppOpsManager->checkOp(AppOpsManager::OP_CAMERA, mClientUid,
                mClientPackageName);
        status_t res = handleAppOpMode(mode);
        if (res != OK) {
            return res;
        }
    }

    mOpsActive = true;
@@ -2980,17 +2987,69 @@ status_t CameraService::BasicClient::startCameraOps() {
    return OK;
}

status_t CameraService::BasicClient::finishCameraOps() {
status_t CameraService::BasicClient::startCameraStreamingOps() {
    ATRACE_CALL();

    // Check if startCameraOps succeeded, and if so, finish the camera op
    if (mOpsActive) {
        // Notify app ops that the camera is available again
    if (!mOpsActive) {
        ALOGE("%s: Calling streaming start when not yet active", __FUNCTION__);
        return INVALID_OPERATION;
    }
    if (mOpsStreaming) {
        ALOGV("%s: Streaming already active!", __FUNCTION__);
        return OK;
    }

    ALOGV("%s: Start camera streaming ops, package name = %s, client UID = %d",
            __FUNCTION__, String8(mClientPackageName).string(), mClientUid);

    if (mAppOpsManager != nullptr) {
        int32_t mode = mAppOpsManager->startOpNoThrow(AppOpsManager::OP_CAMERA, mClientUid,
                mClientPackageName, /*startIfModeDefault*/ false, mClientFeatureId,
                String16("start camera ") + String16(mCameraIdStr));
        status_t res = handleAppOpMode(mode);
        if (res != OK) {
            return res;
        }
    }

    mOpsStreaming = true;

    return OK;
}

status_t CameraService::BasicClient::finishCameraStreamingOps() {
    ATRACE_CALL();

    if (!mOpsActive) {
        ALOGE("%s: Calling streaming start when not yet active", __FUNCTION__);
        return INVALID_OPERATION;
    }
    if (!mOpsStreaming) {
        ALOGV("%s: Streaming not active!", __FUNCTION__);
        return OK;
    }

    if (mAppOpsManager != nullptr) {
        mAppOpsManager->finishOp(AppOpsManager::OP_CAMERA, mClientUid,
                mClientPackageName, mClientFeatureId);
            mOpsActive = false;
        mOpsStreaming = false;
    }

    return OK;
}

status_t CameraService::BasicClient::finishCameraOps() {
    ATRACE_CALL();

    if (mOpsStreaming) {
        // Make sure we've notified everyone about camera stopping
        finishCameraStreamingOps();
    }

    // Check if startCameraOps succeeded, and if so, finish the camera op
    if (mOpsActive) {
        mOpsActive = false;

        // This function is called when a client disconnects. This should
        // release the camera, but actually only if it was in a proper
        // functional state, i.e. with status NOT_AVAILABLE
+15 −3
Original line number Diff line number Diff line
@@ -347,9 +347,18 @@ public:
        // - The app-side Binder interface to receive callbacks from us
        sp<IBinder>                     mRemoteBinder;   // immutable after constructor

        // permissions management
        // Permissions management methods for camera lifecycle

        // Notify rest of system/apps about camera opening, and check appops
        virtual status_t                startCameraOps();
        // Notify rest of system/apps about camera starting to stream data, and confirm appops
        virtual status_t                startCameraStreamingOps();
        // Notify rest of system/apps about camera stopping streaming data
        virtual status_t                finishCameraStreamingOps();
        // Notify rest of system/apps about camera closing
        virtual status_t                finishCameraOps();
        // Handle errors for start/checkOps
        virtual status_t                handleAppOpMode(int32_t mode);

        std::unique_ptr<AppOpsManager>  mAppOpsManager = nullptr;

@@ -364,9 +373,12 @@ public:
        }; // class OpsCallback

        sp<OpsCallback> mOpsCallback;
        // Track whether startCameraOps was called successfully, to avoid
        // finishing what we didn't start.
        // Track whether checkOps was called successfully, to avoid
        // finishing what we didn't start, on camera open.
        bool            mOpsActive;
        // Track whether startOps was called successfully on start of
        // camera streaming.
        bool            mOpsStreaming;

        // IAppOpsCallback interface, indirected through opListener
        virtual void opChanged(int32_t op, const String16& packageName);
+5 −0
Original line number Diff line number Diff line
@@ -275,12 +275,17 @@ void CameraOfflineSessionClient::notifyShutter(const CaptureResultExtras& result
    }
}

status_t CameraOfflineSessionClient::notifyActive() {
    return startCameraStreamingOps();
}

void CameraOfflineSessionClient::notifyIdle(
        int64_t /*requestCount*/, int64_t /*resultErrorCount*/, bool /*deviceError*/,
        const std::vector<hardware::CameraStreamStats>& /*streamStats*/) {
    if (mRemoteCallback.get() != nullptr) {
        mRemoteCallback->onDeviceIdle();
    }
    finishCameraStreamingOps();
}

void CameraOfflineSessionClient::notifyAutoFocus(uint8_t newState, int triggerId) {
+1 −0
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ public:
    // NotificationListener API
    void notifyError(int32_t errorCode, const CaptureResultExtras& resultExtras) override;
    void notifyShutter(const CaptureResultExtras& resultExtras, nsecs_t timestamp) override;
    status_t notifyActive() override;
    void notifyIdle(int64_t requestCount, int64_t resultErrorCount, bool deviceError,
            const std::vector<hardware::CameraStreamStats>& streamStats) override;
    void notifyAutoFocus(uint8_t newState, int triggerId) override;
+22 −5
Original line number Diff line number Diff line
@@ -249,11 +249,33 @@ void Camera2ClientBase<TClientBase>::notifyError(
          resultExtras.requestId);
}

template <typename TClientBase>
status_t Camera2ClientBase<TClientBase>::notifyActive() {
    if (!mDeviceActive) {
        status_t res = TClientBase::startCameraStreamingOps();
        if (res != OK) {
            ALOGE("%s: Camera %s: Error starting camera streaming ops: %d", __FUNCTION__,
                    TClientBase::mCameraIdStr.string(), res);
            return res;
        }
        CameraServiceProxyWrapper::logActive(TClientBase::mCameraIdStr);
    }
    mDeviceActive = true;

    ALOGV("Camera device is now active");
    return OK;
}

template <typename TClientBase>
void Camera2ClientBase<TClientBase>::notifyIdle(
        int64_t requestCount, int64_t resultErrorCount, bool deviceError,
        const std::vector<hardware::CameraStreamStats>& streamStats) {
    if (mDeviceActive) {
        status_t res = TClientBase::finishCameraStreamingOps();
        if (res != OK) {
            ALOGE("%s: Camera %s: Error finishing streaming ops: %d", __FUNCTION__,
                    TClientBase::mCameraIdStr.string(), res);
        }
        CameraServiceProxyWrapper::logIdle(TClientBase::mCameraIdStr,
                requestCount, resultErrorCount, deviceError, streamStats);
    }
@@ -268,11 +290,6 @@ void Camera2ClientBase<TClientBase>::notifyShutter(const CaptureResultExtras& re
    (void)resultExtras;
    (void)timestamp;

    if (!mDeviceActive) {
        CameraServiceProxyWrapper::logActive(TClientBase::mCameraIdStr);
    }
    mDeviceActive = true;

    ALOGV("%s: Shutter notification for request id %" PRId32 " at time %" PRId64,
            __FUNCTION__, resultExtras.requestId, timestamp);
}
Loading