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

Commit 5cc4c500 authored by Avichal Rakesh's avatar Avichal Rakesh Committed by Android (Google) Code Review
Browse files

Merge "cameraservice: Copy camera characteristics from session characteristics" into main

parents 6d58eb92 4baf7261
Loading
Loading
Loading
Loading
+93 −57
Original line number Diff line number Diff line
@@ -991,12 +991,6 @@ Status CameraService::getSessionCharacteristics(const std::string& unresolvedCam
        /*out*/ CameraMetadata* outMetadata) {
    ATRACE_CALL();

    if (!mInitialized) {
        ALOGE("%s: Camera HAL couldn't be initialized", __FUNCTION__);
        logServiceError("Camera subsystem is not available", ERROR_DISCONNECTED);
        return STATUS_ERROR(ERROR_DISCONNECTED, "Camera subsystem is not available");
    }

    if (outMetadata == nullptr) {
        std::string msg =
                fmt::sprintf("Camera %s: Invalid 'outMetadata' input!", unresolvedCameraId.c_str());
@@ -1004,6 +998,12 @@ Status CameraService::getSessionCharacteristics(const std::string& unresolvedCam
        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
    }

    if (!mInitialized) {
        ALOGE("%s: Camera HAL couldn't be initialized", __FUNCTION__);
        logServiceError("Camera subsystem is not available", ERROR_DISCONNECTED);
        return STATUS_ERROR(ERROR_DISCONNECTED, "Camera subsystem is not available");
    }

    std::optional<std::string> cameraIdOptional = resolveCameraId(unresolvedCameraId, deviceId,
                                                                  devicePolicy, getCallingUid());
    if (!cameraIdOptional.has_value()) {
@@ -1014,16 +1014,19 @@ Status CameraService::getSessionCharacteristics(const std::string& unresolvedCam
    }
    std::string cameraId = cameraIdOptional.value();

    if (shouldRejectSystemCameraConnection(cameraId)) {
        return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                                "Unable to retrieve camera"
                                "characteristics for system only device %s: ",
                                cameraId.c_str());
    }

    bool overrideForPerfClass = SessionConfigurationUtils::targetPerfClassPrimaryCamera(
            mPerfClassPrimaryCameraIds, cameraId, targetSdkVersion);

    status_t ret = mCameraProviderManager->getSessionCharacteristics(
            cameraId, sessionConfiguration, overrideForPerfClass, overrideToPortrait, outMetadata);

    // TODO(b/303645857): Remove fingerprintable metadata if the caller process does not have
    //                    camera access permission.

    Status res = Status::ok();
    switch (ret) {
        case OK:
            // Expected, no handling needed.
@@ -1033,18 +1036,90 @@ Status CameraService::getSessionCharacteristics(const std::string& unresolvedCam
                        "Camera %s: Session characteristics query not supported!",
                        cameraId.c_str());
                ALOGD("%s: %s", __FUNCTION__, msg.c_str());
                res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
                logServiceError(msg, CameraService::ERROR_INVALID_OPERATION);
                outMetadata->clear();
                return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
            }
            break;
        case NAME_NOT_FOUND: {
                std::string msg = fmt::sprintf(
                        "Camera %s: Unknown camera ID.",
                        cameraId.c_str());
                ALOGD("%s: %s", __FUNCTION__, msg.c_str());
                logServiceError(msg, CameraService::ERROR_ILLEGAL_ARGUMENT);
                outMetadata->clear();
                return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
            }
            break;
        default: {
                std::string msg = fmt::sprintf("Camera %s: Error: %s (%d)", cameraId.c_str(),
                                               strerror(-ret), ret);
                std::string msg = fmt::sprintf(
                        "Unable to retrieve session characteristics for camera device %s: "
                        "Error: %s (%d)",
                        cameraId.c_str(), strerror(-ret), ret);
                ALOGE("%s: %s", __FUNCTION__, msg.c_str());
                res = STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
                logServiceError(msg, CameraService::ERROR_INVALID_OPERATION);
                outMetadata->clear();
                return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
            }
    }

    return res;
    return filterSensitiveMetadataIfNeeded(cameraId, outMetadata);
}

Status CameraService::filterSensitiveMetadataIfNeeded(
        const std::string& cameraId, CameraMetadata* metadata) {
    int callingPid = getCallingPid();
    int callingUid = getCallingUid();

    if (callingPid == getpid()) {
        // Caller is cameraserver; no need to remove keys
        return Status::ok();
    }

    SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
    if (getSystemCameraKind(cameraId, &deviceKind) != OK) {
        ALOGE("%s: Couldn't get camera kind for camera id %s", __FUNCTION__, cameraId.c_str());
        metadata->clear();
        return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                                "Unable to retrieve camera kind for device %s", cameraId.c_str());
    }
    if (deviceKind == SystemCameraKind::SYSTEM_ONLY_CAMERA) {
        // Attempting to query system only camera without system camera permission would have
        // failed the shouldRejectSystemCameraConnection in the caller. So if we get here
        // for a system only camera, then the caller has the required permission.
        // No need to remove keys
        return Status::ok();
    }

    std::vector<int32_t> tagsRemoved;
    bool hasCameraPermission = hasPermissionsForCamera(cameraId, callingPid, callingUid);
    if (hasCameraPermission) {
        // Caller has camera permission; no need to remove keys
        return Status::ok();
    }

    status_t ret = metadata->removePermissionEntries(
            mCameraProviderManager->getProviderTagIdLocked(cameraId), &tagsRemoved);
    if (ret != OK) {
        metadata->clear();
        return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                                "Failed to remove camera characteristics needing camera permission "
                                "for device %s:%s (%d)",
                                cameraId.c_str(), strerror(-ret), ret);
    }

    if (!tagsRemoved.empty()) {
        ret = metadata->update(ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION,
                                  tagsRemoved.data(), tagsRemoved.size());
        if (ret != OK) {
            metadata->clear();
            return STATUS_ERROR_FMT(
                    ERROR_INVALID_OPERATION,
                    "Failed to insert camera keys needing permission for device %s: %s (%d)",
                    cameraId.c_str(), strerror(-ret), ret);
        }
    }
    return Status::ok();
}

Status CameraService::parseCameraIdRemapping(
@@ -1381,8 +1456,6 @@ Status CameraService::getCameraCharacteristics(const std::string& unresolvedCame
                "characteristics for system only device %s: ", cameraId.c_str());
    }

    Status ret{};

    bool overrideForPerfClass =
            SessionConfigurationUtils::targetPerfClassPrimaryCamera(mPerfClassPrimaryCameraIds,
                    cameraId, targetSdkVersion);
@@ -1401,45 +1474,8 @@ Status CameraService::getCameraCharacteristics(const std::string& unresolvedCame
                    strerror(-res), res);
        }
    }
    SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
    if (getSystemCameraKind(cameraId, &deviceKind) != OK) {
        ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, cameraId.c_str());
        return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera kind "
                "for device %s", cameraId.c_str());
    }
    int callingPid = getCallingPid();
    int callingUid = getCallingUid();
    std::vector<int32_t> tagsRemoved;
    // If it's not calling from cameraserver, check the permission only if
    // android.permission.CAMERA is required. If android.permission.SYSTEM_CAMERA was needed,
    // it would've already been checked in shouldRejectSystemCameraConnection.
    bool checkPermissionForCamera = hasPermissionsForCamera(cameraId, callingPid, callingUid);
    if ((callingPid != getpid()) &&
            (deviceKind != SystemCameraKind::SYSTEM_ONLY_CAMERA) &&
            !checkPermissionForCamera) {
        res = cameraInfo->removePermissionEntries(
                mCameraProviderManager->getProviderTagIdLocked(cameraId),
                &tagsRemoved);
        if (res != OK) {
            cameraInfo->clear();
            return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Failed to remove camera"
                    " characteristics needing camera permission for device %s: %s (%d)",
                    cameraId.c_str(), strerror(-res), res);
        }
    }

    if (!tagsRemoved.empty()) {
        res = cameraInfo->update(ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION,
                tagsRemoved.data(), tagsRemoved.size());
        if (res != OK) {
            cameraInfo->clear();
            return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Failed to insert camera "
                    "keys needing permission for device %s: %s (%d)", cameraId.c_str(),
                    strerror(-res), res);
        }
    }

    return ret;
    return filterSensitiveMetadataIfNeeded(cameraId, cameraInfo);
}

Status CameraService::getTorchStrengthLevel(const std::string& unresolvedCameraId, int32_t deviceId,
+6 −0
Original line number Diff line number Diff line
@@ -1529,6 +1529,12 @@ private:
    // responsibility to acquire mLogLock before calling this functions.
    bool isClientWatchedLocked(const BasicClient *client);

    // Filters out fingerprintable keys if the calling process does not have CAMERA permission.
    // Note: function caller should ensure that shouldRejectSystemCameraConnection is checked
    // for the calling process before calling this function.
    binder::Status filterSensitiveMetadataIfNeeded(const std::string& cameraId,
                                                   CameraMetadata* metadata);

    /**
     * Get the current system time as a formatted string.
     */
+44 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#include <aidl/AidlUtils.h>
#include <aidl/ExtensionMetadataTags.h>
#include <aidl/SessionCharacteristicsTags.h>
#include <aidl/VndkVersionMetadataTags.h>
#include <aidlcommonsupport/NativeHandle.h>
#include <camera/StringUtils.h>
@@ -334,6 +335,49 @@ status_t filterVndkKeys(int vndkVersion, CameraMetadata &metadata, bool isStatic
    return OK;
}

status_t copySessionCharacteristics(const CameraMetadata& from, CameraMetadata* to,
                                    int queryVersion) {
    // Ensure the vendor ID are the same before attempting
    // anything else. If vendor IDs differ we cannot safely copy the characteristics.
    if (from.getVendorId() != to->getVendorId()) {
        ALOGE("%s: Incompatible CameraMetadata objects. Vendor IDs differ. From: %lu; To: %lu",
              __FUNCTION__, from.getVendorId(), to->getVendorId());
        return BAD_VALUE;
    }

    // Allow public tags according to the queryVersion
    std::unordered_set<uint32_t> validPublicTags;
    auto last = api_level_to_session_characteristic_keys.upper_bound(queryVersion);
    for (auto it = api_level_to_session_characteristic_keys.begin(); it != last; it++) {
        validPublicTags.insert(it->second.cbegin(), it->second.cend());
    }

    const camera_metadata_t* src = from.getAndLock();
    camera_metadata_ro_entry_t entry{};
    for (size_t i = 0; i < get_camera_metadata_entry_count(src); i++) {
        int ret = get_camera_metadata_ro_entry(src, i, &entry);
        if (ret != OK) {
            ALOGE("%s: Could not fetch entry at index %lu. Error: %d", __FUNCTION__, i, ret);
            from.unlock(src);
            return BAD_VALUE;
        }

        if (entry.tag < (uint32_t)VENDOR_SECTION_START &&
                validPublicTags.find(entry.tag) == validPublicTags.end()) {
            ALOGI("%s: Session Characteristics contains tag %s but not supported by query version "
                  "(%d)",
                  __FUNCTION__, get_camera_metadata_tag_name(entry.tag), queryVersion);
            continue;
        }

        // The entry is either a vendor tag, or a valid session characteristic key.
        // Copy over the value
        to->update(entry);
    }
    from.unlock(src);
    return OK;
}

bool areExtensionKeysSupported(const CameraMetadata& metadata) {
    auto requestKeys = metadata.find(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS);
    if (requestKeys.count == 0) {
+3 −0
Original line number Diff line number Diff line
@@ -122,6 +122,9 @@ bool areBindersEqual(const ndk::SpAIBinder& b1, const ndk::SpAIBinder& b2);

status_t filterVndkKeys(int vndkVersion, CameraMetadata &metadata, bool isStatic = true);

status_t copySessionCharacteristics(const CameraMetadata& from, CameraMetadata* to,
                                    int queryVersion);

bool areExtensionKeysSupported(const CameraMetadata& metadata);

status_t filterExtensionKeys(CameraMetadata* metadata /*out*/);
+37 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <map>
#include <vector>
#pragma once
/**
 * ! Do not edit this file directly !
 *
 * Generated automatically from session_characteristics_tags.mako. To be included in
 * libcameraservice only by aidl/AidlUtils.cpp.
 */

/**
 * Mapping of session characteristics to the INFO_SESSION_CONFIGURATION_QUERY_VERSION value
 * at which they were introduced.
 */
std::map<int, std::vector<camera_metadata_tag>> api_level_to_session_characteristic_keys {
        {35,
         {
                 ANDROID_CONTROL_ZOOM_RATIO_RANGE,
                 ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
         }},
};
Loading