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

Commit 5e84c1ae authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Camera: Filter camera characteristics"

parents 4cb2780e e20c637e
Loading
Loading
Loading
Loading
+73 −1
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@

#include <binder/Parcel.h>
#include <camera/CameraMetadata.h>
#include <camera/VendorTagDescriptor.h>

namespace android {

@@ -409,6 +408,79 @@ status_t CameraMetadata::erase(uint32_t tag) {
    return res;
}

status_t CameraMetadata::removePermissionEntries(metadata_vendor_id_t vendorId,
        std::vector<int32_t> *tagsRemoved) {
    uint32_t tagCount = 0;
    std::vector<uint32_t> tagsToRemove;

    if (tagsRemoved == nullptr) {
        return BAD_VALUE;
    }

    sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
    if ((nullptr == vTags.get()) || (0 >= vTags->getTagCount())) {
        sp<VendorTagDescriptorCache> cache =
            VendorTagDescriptorCache::getGlobalVendorTagCache();
        if (cache.get()) {
            cache->getVendorTagDescriptor(vendorId, &vTags);
        }
    }

    if ((nullptr != vTags.get()) && (vTags->getTagCount() > 0)) {
        tagCount = vTags->getTagCount();
        uint32_t *vendorTags = new uint32_t[tagCount];
        if (nullptr == vendorTags) {
            return NO_MEMORY;
        }
        vTags->getTagArray(vendorTags);

        tagsToRemove.reserve(tagCount);
        tagsToRemove.insert(tagsToRemove.begin(), vendorTags, vendorTags + tagCount);

        delete [] vendorTags;
        tagCount = 0;
    }

    auto tagsNeedingPermission = get_camera_metadata_permission_needed(&tagCount);
    if (tagCount > 0) {
        tagsToRemove.reserve(tagsToRemove.capacity() + tagCount);
        tagsToRemove.insert(tagsToRemove.end(), tagsNeedingPermission,
                tagsNeedingPermission + tagCount);
    }

    tagsRemoved->reserve(tagsToRemove.size());
    for (const auto &it : tagsToRemove) {
        if (exists(it)) {
            auto rc = erase(it);
            if (NO_ERROR != rc) {
                ALOGE("%s: Failed to erase tag: %x", __func__, it);
                return rc;
            }
            tagsRemoved->push_back(it);
        }
    }

    // Update the available characterstics accordingly
    if (exists(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS)) {
        std::vector<uint32_t> currentKeys;

        std::sort(tagsRemoved->begin(), tagsRemoved->end());
        auto keys = find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
        currentKeys.reserve(keys.count);
        currentKeys.insert(currentKeys.end(), keys.data.i32, keys.data.i32 + keys.count);
        std::sort(currentKeys.begin(), currentKeys.end());

        std::vector<int32_t> newKeys(keys.count);
        auto end = std::set_difference(currentKeys.begin(), currentKeys.end(), tagsRemoved->begin(),
                tagsRemoved->end(), newKeys.begin());
        newKeys.resize(end - newKeys.begin());

        update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, newKeys.data(), newKeys.size());
    }

    return NO_ERROR;
}

void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
    dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
}
+7 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <utils/String8.h>
#include <utils/Vector.h>
#include <binder/Parcelable.h>
#include <camera/VendorTagDescriptor.h>

namespace android {

@@ -169,6 +170,12 @@ class CameraMetadata: public Parcelable {
     */
    status_t erase(uint32_t tag);

    /**
     * Remove metadata entries that need additional permissions.
     */
    status_t removePermissionEntries(metadata_vendor_id_t vendorId,
            std::vector<int32_t> *tagsRemoved /*out*/);

    /**
     * Swap the underlying camera metadata between this and the other
     * metadata object.
+2 −1
Original line number Diff line number Diff line
@@ -19,7 +19,8 @@ LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_SRC_FILES:= \
	VendorTagDescriptorTests.cpp \
	CameraBinderTests.cpp \
	CameraZSLTests.cpp
	CameraZSLTests.cpp \
	CameraCharacteristicsPermission.cpp

LOCAL_SHARED_LIBRARIES := \
	liblog \
+96 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.
 */

#define LOG_NDEBUG 0
#define LOG_TAG "CameraCharacteristicsPermission"

#include <gtest/gtest.h>

#include <binder/ProcessState.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <camera/CameraMetadata.h>
#include <camera/Camera.h>
#include <android/hardware/ICameraService.h>

using namespace android;
using namespace android::hardware;

class CameraCharacteristicsPermission : public ::testing::Test {
protected:

    CameraCharacteristicsPermission() : numCameras(0){}
    //Gtest interface
    void SetUp() override;
    void TearDown() override;

    int32_t numCameras;
    sp<ICameraService> mCameraService;
};

void CameraCharacteristicsPermission::SetUp() {
    ::android::binder::Status rc;
    ProcessState::self()->startThreadPool();
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->getService(String16("media.camera"));
    mCameraService = interface_cast<ICameraService>(binder);
    rc = mCameraService->getNumberOfCameras(
            hardware::ICameraService::CAMERA_TYPE_ALL, &numCameras);
    EXPECT_TRUE(rc.isOk());
}

void CameraCharacteristicsPermission::TearDown() {
    mCameraService.clear();
}

// Revoking and acquiring permissions automatically might not be possible.
// Test the functionality for removal of camera characteristics needing
// a camera permission.
TEST_F(CameraCharacteristicsPermission, TestCameraPermission) {
    for (int32_t cameraId = 0; cameraId < numCameras; cameraId++) {

        String16 cameraIdStr = String16(String8::format("%d", cameraId));
        bool isSupported = false;
        auto rc = mCameraService->supportsCameraApi(cameraIdStr,
                hardware::ICameraService::API_VERSION_2, &isSupported);
        EXPECT_TRUE(rc.isOk());
        if (!isSupported) {
            continue;
        }

        CameraMetadata metadata;
        std::vector<int32_t> tagsNeedingPermission;
        rc = mCameraService->getCameraCharacteristics(cameraIdStr, &metadata);
        ASSERT_TRUE(rc.isOk());
        EXPECT_FALSE(metadata.isEmpty());
        EXPECT_EQ(metadata.removePermissionEntries(CAMERA_METADATA_INVALID_VENDOR_ID,
                    &tagsNeedingPermission), NO_ERROR);
        camera_metadata_entry_t availableCharacteristics =
                metadata.find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
        EXPECT_TRUE(0 < availableCharacteristics.count);

        std::vector<uint32_t> availableKeys;
        availableKeys.reserve(availableCharacteristics.count);
        availableKeys.insert(availableKeys.begin(), availableCharacteristics.data.i32,
                availableCharacteristics.data.i32 + availableCharacteristics.count);

        for (const auto &key : tagsNeedingPermission) {
            ASSERT_FALSE(metadata.exists(key));
            auto it = std::find(availableKeys.begin(), availableKeys.end(), key);
            ASSERT_TRUE(it == availableKeys.end());
        }
    }
}
+28 −0
Original line number Diff line number Diff line
@@ -491,6 +491,34 @@ Status CameraService::getCameraCharacteristics(const String16& cameraId,
                strerror(-res), res);
    }

    int callingPid = getCallingPid();
    int callingUid = getCallingUid();
    std::vector<int32_t> tagsRemoved;
    // If it's not calling from cameraserver, check the permission.
    if ((callingPid != getpid()) &&
            !checkPermission(String16("android.permission.CAMERA"), callingPid, callingUid)) {
        res = cameraInfo->removePermissionEntries(
                mCameraProviderManager->getProviderTagIdLocked(String8(cameraId).string()),
                &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)",
                    String8(cameraId).string(), 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)", String8(cameraId).string(),
                    strerror(-res), res);
        }
    }

    return ret;
}