/*
 * Copyright (C) 2015 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 "ACameraManager"

#include "ACameraManager.h"
#include <android_companion_virtualdevice_flags.h>
#include <camera/CameraUtils.h>
#include <camera/StringUtils.h>
#include <camera/VendorTagDescriptor.h>
#include <cutils/properties.h>
#include <stdlib.h>
#include <utils/Vector.h>
#include <memory>
#include "ACameraDevice.h"
#include "ACameraMetadata.h"
#include <com_android_internal_camera_flags.h>

using namespace android::acam;
namespace vd_flags = android::companion::virtualdevice::flags;
namespace flags = com::android::internal::camera::flags;

namespace android {
namespace acam {
namespace {

using ::android::binder::Status;
using ::android::companion::virtualnative::IVirtualDeviceManagerNative;

// Return binder connection to VirtualDeviceManager.
//
// Subsequent calls return the same cached instance.
sp<IVirtualDeviceManagerNative> getVirtualDeviceManager() {
    auto connectToVirtualDeviceManagerNative = []() {
        sp<IBinder> binder =
                defaultServiceManager()->checkService(String16("virtualdevice_native"));
        if (binder == nullptr) {
            ALOGW("%s: Cannot get virtualdevice_native service", __func__);
            return interface_cast<IVirtualDeviceManagerNative>(nullptr);
        }
        return interface_cast<IVirtualDeviceManagerNative>(binder);
    };

    static sp<IVirtualDeviceManagerNative> vdm = connectToVirtualDeviceManagerNative();
    return vdm;
}

// Returns device id calling process is running on.
// If the process cannot be attributed to single virtual device id, returns default device id.
int getCurrentDeviceId() {
    if (!vd_flags::camera_device_awareness()) {
        return kDefaultDeviceId;
    }

    auto vdm = getVirtualDeviceManager();
    if (vdm == nullptr) {
        return kDefaultDeviceId;
    }

    const uid_t myUid = getuid();
    std::vector<int> deviceIds;
    Status status = vdm->getDeviceIdsForUid(myUid, &deviceIds);
    if (!status.isOk() || deviceIds.empty()) {
        ALOGE("%s: Failed to call getDeviceIdsForUid to determine device id for uid %d: %s",
              __func__, myUid, status.toString8().c_str());
        return kDefaultDeviceId;
    }

    // If the UID is associated with multiple virtual devices, use the default device's
    // camera as we cannot disambiguate here. This effectively means that the app has
    // activities on different devices at the same time.
    if (deviceIds.size() != 1) {
        return kDefaultDeviceId;
    }
    return deviceIds[0];
}

// Returns device policy for POLICY_TYPE_CAMERA corresponding to deviceId.
DevicePolicy getDevicePolicyForDeviceId(const int deviceId) {
    if (!vd_flags::camera_device_awareness() || deviceId == kDefaultDeviceId) {
        return DevicePolicy::DEVICE_POLICY_DEFAULT;
    }

    auto vdm = getVirtualDeviceManager();
    if (vdm == nullptr) {
        return DevicePolicy::DEVICE_POLICY_DEFAULT;
    }

    int policy = IVirtualDeviceManagerNative::DEVICE_POLICY_DEFAULT;
    Status status = vdm->getDevicePolicy(deviceId, IVirtualDeviceManagerNative::POLICY_TYPE_CAMERA,
                                         &policy);
    if (!status.isOk()) {
        ALOGE("%s: Failed to call getDevicePolicy to determine camera policy for device id %d: %s",
              __func__, deviceId, status.toString8().c_str());
        return DevicePolicy::DEVICE_POLICY_DEFAULT;
    }
    return static_cast<DevicePolicy>(policy);
}

// Returns true if camera owned by device cameraDeviceId can be accessed within deviceContext.
bool isCameraAccessible(const DeviceContext deviceContext, const int cameraDeviceId) {
    if (!vd_flags::camera_device_awareness() ||
        deviceContext.policy == DevicePolicy::DEVICE_POLICY_DEFAULT) {
        return cameraDeviceId == kDefaultDeviceId;
    }
    return deviceContext.deviceId == cameraDeviceId;
}

}  // namespace

// Static member definitions
const char* CameraManagerGlobal::kCameraIdKey   = "CameraId";
const char* CameraManagerGlobal::kPhysicalCameraIdKey   = "PhysicalCameraId";
const char* CameraManagerGlobal::kCallbackFpKey = "CallbackFp";
const char* CameraManagerGlobal::kContextKey    = "CallbackContext";
const nsecs_t CameraManagerGlobal::kCallbackDrainTimeout = 5000000; // 5 ms
Mutex                CameraManagerGlobal::sLock;
wp<CameraManagerGlobal> CameraManagerGlobal::sInstance = nullptr;

DeviceContext::DeviceContext() {
    deviceId = getCurrentDeviceId();
    policy = getDevicePolicyForDeviceId(deviceId);
}

sp<CameraManagerGlobal> CameraManagerGlobal::getInstance() {
    Mutex::Autolock _l(sLock);
    sp<CameraManagerGlobal> instance = sInstance.promote();
    if (instance == nullptr) {
        instance = new CameraManagerGlobal();
        sInstance = instance;
    }
    return instance;
}

CameraManagerGlobal::~CameraManagerGlobal() {
    // clear sInstance so next getInstance call knows to create a new one
    Mutex::Autolock _sl(sLock);
    sInstance = nullptr;
    Mutex::Autolock _l(mLock);
    if (mCameraService != nullptr) {
        IInterface::asBinder(mCameraService)->unlinkToDeath(mDeathNotifier);
        mCameraService->removeListener(mCameraServiceListener);
    }
    mDeathNotifier.clear();
    if (mCbLooper != nullptr) {
        mCbLooper->unregisterHandler(mHandler->id());
        mCbLooper->stop();
    }
    mCbLooper.clear();
    mHandler.clear();
    mCameraServiceListener.clear();
    mCameraService.clear();
}

sp<hardware::ICameraService> CameraManagerGlobal::getCameraService() {
    Mutex::Autolock _l(mLock);
    return getCameraServiceLocked();
}

sp<hardware::ICameraService> CameraManagerGlobal::getCameraServiceLocked() {
    if (mCameraService.get() != nullptr) {
        return mCameraService;
    }
    if (CameraUtils::isCameraServiceDisabled()) {
        return mCameraService;
    }

    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder;
    binder = sm->checkService(String16(kCameraServiceName));
    if (binder == nullptr) {
        ALOGE("%s: Could not get CameraService instance.", __FUNCTION__);
        return nullptr;
    }
    sp<hardware::ICameraService> cameraService = interface_cast<hardware::ICameraService>(binder);
    if (mDeathNotifier == nullptr) {
        mDeathNotifier = new DeathNotifier(this);
        binder->linkToDeath(mDeathNotifier);
    }

    // Setup looper thread to perform availability callbacks
    if (mCbLooper == nullptr) {
        mCbLooper = new ALooper;
        mCbLooper->setName("C2N-mgr-looper");
        status_t err = mCbLooper->start(
                /*runOnCallingThread*/false,
                /*canCallJava*/       true,
                PRIORITY_DEFAULT);
        if (err != OK) {
            ALOGE("%s: Unable to start camera service listener looper: %s (%d)",
                    __FUNCTION__, strerror(-err), err);
            mCbLooper.clear();
            return nullptr;
        }
        if (mHandler == nullptr) {
            mHandler = new CallbackHandler(this);
        }
        mCbLooper->registerHandler(mHandler);
    }

    // register ICameraServiceListener
    std::vector<hardware::CameraStatus> cameraStatuses{};
    if (mCameraServiceListener == nullptr) {
        mCameraServiceListener = new CameraServiceListener(this);
        cameraService->addListener(mCameraServiceListener, &cameraStatuses);
    }

    for (auto& c : cameraStatuses) {
        onStatusChangedLocked(c.status, c.deviceId, c.cameraId);

        for (auto& unavailablePhysicalId : c.unavailablePhysicalIds) {
            onStatusChangedLocked(hardware::ICameraServiceListener::STATUS_NOT_PRESENT,
                                    c.deviceId, c.cameraId, unavailablePhysicalId);
        }
    }
    // setup vendor tags
    if (!setupVendorTags(cameraService)) {
        ALOGE("%s: Vendor tag descriptor cache couldn't be set up", __FUNCTION__);
        return nullptr;
    }

    mCameraService = cameraService;
    ALOGE_IF(mCameraService == nullptr, "no CameraService!?");
    return mCameraService;
}

bool CameraManagerGlobal::setupVendorTags(sp<hardware::ICameraService> &cameraService) {
    sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
    binder::Status ret = cameraService->getCameraVendorTagDescriptor(/*out*/desc.get());
    if (!ret.isOk()) {
        if (ret.serviceSpecificErrorCode() ==
            hardware::ICameraService::ERROR_DEPRECATED_HAL) {
            ALOGW("%s: Camera HAL too old; does not support vendor tags",
                    __FUNCTION__);
            VendorTagDescriptor::clearGlobalVendorTagDescriptor();
        } else {
            ALOGE("%s: Failed to get vendor tag descriptors: %s",
                    __FUNCTION__, ret.toString8().c_str());
        }
        return false;
    }

    if (0 < desc->getTagCount()) {
        status_t err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
        if (err != OK) {
            ALOGE("%s: Failed to set vendor tag descriptors, received error %s (%d)",
                    __FUNCTION__, strerror(-err), err);
            return false;
        }
    } else {
        sp<VendorTagDescriptorCache> cache =
                new VendorTagDescriptorCache();
        binder::Status res =
                cameraService->getCameraVendorTagCache(
                        /*out*/cache.get());
        if (res.serviceSpecificErrorCode() ==
                hardware::ICameraService::ERROR_DISCONNECTED) {
            // No camera module available, not an error on devices with no cameras
            VendorTagDescriptorCache::clearGlobalVendorTagCache();
        } else if (res.isOk()) {
            status_t err =
                    VendorTagDescriptorCache::setAsGlobalVendorTagCache(
                            cache);
            if (err != OK) {
                ALOGE("%s: Failed to set vendor tag cache,"
                        "received error %s (%d)", __FUNCTION__,
                        strerror(-err), err);
                return false;
            }
        } else {
            VendorTagDescriptorCache::clearGlobalVendorTagCache();
            ALOGE("%s: Failed to setup vendor tag cache: %s",
                    __FUNCTION__, res.toString8().c_str());
            return false;
        }
    }

    return true;
}

void CameraManagerGlobal::DeathNotifier::binderDied(const wp<IBinder>&)
{
    ALOGE("Camera service binderDied!");
    sp<CameraManagerGlobal> cm = mCameraManager.promote();
    if (cm != nullptr) {
        AutoMutex lock(cm->mLock);
        std::vector<DeviceStatusMapKey> keysToRemove;
        keysToRemove.reserve(cm->mDeviceStatusMap.size());
        for (auto& pair : cm->mDeviceStatusMap) {
            keysToRemove.push_back(pair.first);
        }

        for (const DeviceStatusMapKey& key : keysToRemove) {
            cm->onStatusChangedLocked(CameraServiceListener::STATUS_NOT_PRESENT, key.deviceId,
                                      key.cameraId);
        }
        cm->mCameraService.clear();
        cm->mCameraServiceListener.clear();
        cm->mDeathNotifier.clear();
        // TODO: consider adding re-connect call here?
    }
}

void CameraManagerGlobal::registerExtendedAvailabilityCallback(
        const DeviceContext& deviceContext,
        const ACameraManager_ExtendedAvailabilityCallbacks* callback) {
    return registerAvailCallback<ACameraManager_ExtendedAvailabilityCallbacks>(deviceContext,
                                                                               callback);
}

void CameraManagerGlobal::unregisterExtendedAvailabilityCallback(
        const DeviceContext& deviceContext,
        const ACameraManager_ExtendedAvailabilityCallbacks* callback) {
    Mutex::Autolock _l(mLock);

    drainPendingCallbacksLocked();

    Callback cb(deviceContext, callback);
    mCallbacks.erase(cb);
}

void CameraManagerGlobal::registerAvailabilityCallback(
        const DeviceContext& deviceContext, const ACameraManager_AvailabilityCallbacks* callback) {
    return registerAvailCallback<ACameraManager_AvailabilityCallbacks>(deviceContext, callback);
}

void CameraManagerGlobal::unregisterAvailabilityCallback(
        const DeviceContext& deviceContext, const ACameraManager_AvailabilityCallbacks* callback) {
    Mutex::Autolock _l(mLock);

    drainPendingCallbacksLocked();

    Callback cb(deviceContext, callback);
    mCallbacks.erase(cb);
}

void CameraManagerGlobal::onCallbackCalled() {
    Mutex::Autolock _l(mLock);
    if (mPendingCallbackCnt > 0) {
        mPendingCallbackCnt--;
    }
    mCallbacksCond.signal();
}

void CameraManagerGlobal::drainPendingCallbacksLocked() {
    while (mPendingCallbackCnt > 0) {
        auto res = mCallbacksCond.waitRelative(mLock, kCallbackDrainTimeout);
        if (res != NO_ERROR) {
            ALOGE("%s: Error waiting to drain callbacks: %s(%d)",
                    __FUNCTION__, strerror(-res), res);
            break;
        }
    }
}

template <class T>
void CameraManagerGlobal::registerAvailCallback(const DeviceContext& deviceContext,
                                                const T* callback) {
    Mutex::Autolock _l(mLock);
    getCameraServiceLocked();
    Callback cb(deviceContext, callback);
    const auto& [_, newlyRegistered] = mCallbacks.insert(cb);
    // Send initial callbacks if callback is newly registered
    if (newlyRegistered) {
        for (auto& [key, statusAndHAL3Support] : mDeviceStatusMap) {
            if (!isCameraAccessible(deviceContext, key.deviceId)) {
                continue;
            }
            const std::string& cameraId = key.cameraId;
            int32_t status = statusAndHAL3Support.getStatus();
            // Don't send initial callbacks for camera ids which don't support
            // camera2
            if (!statusAndHAL3Support.supportsHAL3) {
                continue;
            }

            // Camera available/unavailable callback
            sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
            ACameraManager_AvailabilityCallback cbFunc = isStatusAvailable(status) ?
                    cb.mAvailable : cb.mUnavailable;
            msg->setPointer(kCallbackFpKey, (void *) cbFunc);
            msg->setPointer(kContextKey, cb.mContext);
            msg->setString(kCameraIdKey, AString(cameraId.c_str()));
            mPendingCallbackCnt++;
            msg->post();

            // Physical camera unavailable callback
            std::set<std::string> unavailablePhysicalCameras =
                    statusAndHAL3Support.getUnavailablePhysicalIds();
            for (const auto& physicalCameraId : unavailablePhysicalCameras) {
                sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
                ACameraManager_PhysicalCameraAvailabilityCallback cbFunc =
                        cb.mPhysicalCamUnavailable;
                msg->setPointer(kCallbackFpKey, (void *) cbFunc);
                msg->setPointer(kContextKey, cb.mContext);
                msg->setString(kCameraIdKey, AString(cameraId.c_str()));
                msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
                mPendingCallbackCnt++;
                msg->post();
            }
        }
    }
}

bool CameraManagerGlobal::supportsCamera2ApiLocked(const std::string &cameraId) {
    bool camera2Support = false;
    auto cs = getCameraServiceLocked();
    if (cs == nullptr) {
        return false;
    }
    binder::Status serviceRet =
        cs->supportsCameraApi(cameraId,
                hardware::ICameraService::API_VERSION_2, &camera2Support);
    if (!serviceRet.isOk()) {
        ALOGE("%s: supportsCameraApi2Locked() call failed for cameraId  %s",
                __FUNCTION__, cameraId.c_str());
        return false;
    }
    return camera2Support;
}

void CameraManagerGlobal::getCameraIdList(const DeviceContext& context,
        std::vector<std::string>* cameraIds) {
    // Ensure that we have initialized/refreshed the list of available devices
    Mutex::Autolock _l(mLock);
    // Needed to make sure we're connected to cameraservice
    getCameraServiceLocked();
    for (auto& [key, statusAndHAL3Support] : mDeviceStatusMap) {
        if (!isCameraAccessible(context, key.deviceId)) {
            continue;
        }

        int32_t status = statusAndHAL3Support.getStatus();
        if (status == hardware::ICameraServiceListener::STATUS_NOT_PRESENT ||
                status == hardware::ICameraServiceListener::STATUS_ENUMERATING) {
            continue;
        }
        if (!statusAndHAL3Support.supportsHAL3) {
            continue;
        }
        cameraIds->push_back(key.cameraId);
    }
}

bool CameraManagerGlobal::validStatus(int32_t status) {
    switch (status) {
        case hardware::ICameraServiceListener::STATUS_NOT_PRESENT:
        case hardware::ICameraServiceListener::STATUS_PRESENT:
        case hardware::ICameraServiceListener::STATUS_ENUMERATING:
        case hardware::ICameraServiceListener::STATUS_NOT_AVAILABLE:
            return true;
        default:
            return false;
    }
}

bool CameraManagerGlobal::isStatusAvailable(int32_t status) {
    switch (status) {
        case hardware::ICameraServiceListener::STATUS_PRESENT:
            return true;
        default:
            return false;
    }
}

void CameraManagerGlobal::CallbackHandler::onMessageReceived(
      const sp<AMessage> &msg) {
    onMessageReceivedInternal(msg);
    if (msg->what() == kWhatSendSingleCallback ||
            msg->what() == kWhatSendSingleAccessCallback ||
            msg->what() == kWhatSendSinglePhysicalCameraCallback) {
        notifyParent();
    }
}

void CameraManagerGlobal::CallbackHandler::onMessageReceivedInternal(
        const sp<AMessage> &msg) {
    switch (msg->what()) {
        case kWhatSendSingleCallback:
        {
            ACameraManager_AvailabilityCallback cb;
            void* context;
            AString cameraId;
            bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
            if (!found) {
                ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
                return;
            }
            found = msg->findPointer(kContextKey, &context);
            if (!found) {
                ALOGE("%s: Cannot find callback context!", __FUNCTION__);
                return;
            }
            found = msg->findString(kCameraIdKey, &cameraId);
            if (!found) {
                ALOGE("%s: Cannot find camera ID!", __FUNCTION__);
                return;
            }
            (*cb)(context, cameraId.c_str());
            break;
        }
        case kWhatSendSingleAccessCallback:
        {
            ACameraManager_AccessPrioritiesChangedCallback cb;
            void* context;
            AString cameraId;
            bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
            if (!found) {
                ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
                return;
            }
            found = msg->findPointer(kContextKey, &context);
            if (!found) {
                ALOGE("%s: Cannot find callback context!", __FUNCTION__);
                return;
            }
            (*cb)(context);
            break;
        }
        case kWhatSendSinglePhysicalCameraCallback:
        {
            ACameraManager_PhysicalCameraAvailabilityCallback cb;
            void* context;
            AString cameraId;
            AString physicalCameraId;
            bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
            if (!found) {
                ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
                return;
            }
            if (cb == nullptr) {
                // Physical camera callback is null
                return;
            }
            found = msg->findPointer(kContextKey, &context);
            if (!found) {
                ALOGE("%s: Cannot find callback context!", __FUNCTION__);
                return;
            }
            found = msg->findString(kCameraIdKey, &cameraId);
            if (!found) {
                ALOGE("%s: Cannot find camera ID!", __FUNCTION__);
                return;
            }
            found = msg->findString(kPhysicalCameraIdKey, &physicalCameraId);
            if (!found) {
                ALOGE("%s: Cannot find physical camera ID!", __FUNCTION__);
                return;
            }
            (*cb)(context, cameraId.c_str(), physicalCameraId.c_str());
            break;
        }
        default:
            ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what());
            break;
    }
}

void CameraManagerGlobal::CallbackHandler::notifyParent() {
    sp<CameraManagerGlobal> parent = mParent.promote();
    if (parent != nullptr) {
        parent->onCallbackCalled();
    }
}

binder::Status CameraManagerGlobal::CameraServiceListener::onCameraAccessPrioritiesChanged() {
    sp<CameraManagerGlobal> cm = mCameraManager.promote();
    if (cm != nullptr) {
        cm->onCameraAccessPrioritiesChanged();
    } else {
        ALOGE("Cannot deliver camera access priority callback. Global camera manager died");
    }
    return binder::Status::ok();
}

binder::Status CameraManagerGlobal::CameraServiceListener::onStatusChanged(
        int32_t status, const std::string& cameraId, int deviceId) {
    sp<CameraManagerGlobal> cm = mCameraManager.promote();
    if (cm != nullptr) {
        cm->onStatusChanged(status, deviceId, cameraId);
    }
    ALOGE_IF(cm == nullptr,
             "Cannot deliver physical camera status change. Global camera manager died");
    return binder::Status::ok();
}

binder::Status CameraManagerGlobal::CameraServiceListener::onPhysicalCameraStatusChanged(
        int32_t status, const std::string& cameraId, const std::string& physicalCameraId,
        int deviceId) {
    sp<CameraManagerGlobal> cm = mCameraManager.promote();
    if (cm != nullptr) {
        cm->onStatusChanged(status, deviceId, cameraId, physicalCameraId);
    }
    ALOGE_IF(cm == nullptr,
             "Cannot deliver physical camera status change. Global camera manager died");
    return binder::Status::ok();
}

void CameraManagerGlobal::onCameraAccessPrioritiesChanged() {
    Mutex::Autolock _l(mLock);
    for (auto cb : mCallbacks) {
        sp<AMessage> msg = new AMessage(kWhatSendSingleAccessCallback, mHandler);
        ACameraManager_AccessPrioritiesChangedCallback cbFp = cb.mAccessPriorityChanged;
        if (cbFp != nullptr) {
            msg->setPointer(kCallbackFpKey, (void *) cbFp);
            msg->setPointer(kContextKey, cb.mContext);
            mPendingCallbackCnt++;
            msg->post();
        }
    }
}

void CameraManagerGlobal::onStatusChanged(int32_t status, const int deviceId,
        const std::string& cameraId) {
    Mutex::Autolock _l(mLock);
    onStatusChangedLocked(status, deviceId, cameraId);
}

void CameraManagerGlobal::onStatusChangedLocked(int32_t status, const int deviceId,
        const std::string& cameraId) {
    if (!validStatus(status)) {
        ALOGE("%s: Invalid status %d", __FUNCTION__, status);
        return;
    }

    DeviceStatusMapKey key{.deviceId = deviceId, .cameraId = cameraId};

    bool firstStatus = (mDeviceStatusMap.count(key) == 0);
    int32_t oldStatus = firstStatus ? status :  // first status
                                mDeviceStatusMap[key].getStatus();

    if (!firstStatus &&
            isStatusAvailable(status) == isStatusAvailable(oldStatus)) {
        // No status update. No need to send callback
        return;
    }

    bool supportsHAL3 = supportsCamera2ApiLocked(cameraId);
    if (firstStatus) {
        mDeviceStatusMap.emplace(std::piecewise_construct, std::forward_as_tuple(key),
                                 std::forward_as_tuple(status, supportsHAL3));
    } else {
        mDeviceStatusMap[key].updateStatus(status);
    }
    // Iterate through all registered callbacks
    if (supportsHAL3) {
        for (auto cb : mCallbacks) {
            if (!isCameraAccessible(cb.mDeviceContext, deviceId)) {
                continue;
            }
            sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
            ACameraManager_AvailabilityCallback cbFp = isStatusAvailable(status) ?
                    cb.mAvailable : cb.mUnavailable;
            msg->setPointer(kCallbackFpKey, (void *) cbFp);
            msg->setPointer(kContextKey, cb.mContext);
            msg->setString(kCameraIdKey, AString(cameraId.c_str()));
            mPendingCallbackCnt++;
            msg->post();
        }
    }
    if (status == hardware::ICameraServiceListener::STATUS_NOT_PRESENT) {
        mDeviceStatusMap.erase(key);
    }
}

void CameraManagerGlobal::onStatusChanged(int32_t status, const int deviceId,
        const std::string& cameraId, const std::string& physicalCameraId) {
    Mutex::Autolock _l(mLock);
    onStatusChangedLocked(status, deviceId, cameraId, physicalCameraId);
}

void CameraManagerGlobal::onStatusChangedLocked(int32_t status, const int deviceId,
        const std::string& cameraId, const std::string& physicalCameraId) {
    if (!validStatus(status)) {
        ALOGE("%s: Invalid status %d", __FUNCTION__, status);
        return;
    }

    DeviceStatusMapKey key{.deviceId = deviceId, .cameraId = cameraId};
    auto logicalStatus = mDeviceStatusMap.find(key);
    if (logicalStatus == mDeviceStatusMap.end()) {
        ALOGE("%s: Physical camera id %s status change on a non-present id %s",
                __FUNCTION__, physicalCameraId.c_str(), cameraId.c_str());
        return;
    }
    int32_t logicalCamStatus = mDeviceStatusMap[key].getStatus();
    if (logicalCamStatus != hardware::ICameraServiceListener::STATUS_PRESENT &&
            logicalCamStatus != hardware::ICameraServiceListener::STATUS_NOT_AVAILABLE) {
        ALOGE("%s: Physical camera id %s status %d change for an invalid logical camera state %d",
                __FUNCTION__, physicalCameraId.c_str(), status, logicalCamStatus);
        return;
    }

    bool supportsHAL3 = supportsCamera2ApiLocked(cameraId);

    bool updated = false;
    if (status == hardware::ICameraServiceListener::STATUS_PRESENT) {
        updated = mDeviceStatusMap[key].removeUnavailablePhysicalId(physicalCameraId);
    } else {
        updated = mDeviceStatusMap[key].addUnavailablePhysicalId(physicalCameraId);
    }

    // Iterate through all registered callbacks
    if (supportsHAL3 && updated) {
        for (auto cb : mCallbacks) {
            if (!isCameraAccessible(cb.mDeviceContext, deviceId)) {
                continue;
            }
            sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
            ACameraManager_PhysicalCameraAvailabilityCallback cbFp = isStatusAvailable(status) ?
                    cb.mPhysicalCamAvailable : cb.mPhysicalCamUnavailable;
            msg->setPointer(kCallbackFpKey, (void *) cbFp);
            msg->setPointer(kContextKey, cb.mContext);
            msg->setString(kCameraIdKey, AString(cameraId.c_str()));
            msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
            mPendingCallbackCnt++;
            msg->post();
        }
    }
}

int32_t CameraManagerGlobal::StatusAndHAL3Support::getStatus() {
    std::lock_guard<std::mutex> lock(mLock);
    return status;
}

void CameraManagerGlobal::StatusAndHAL3Support::updateStatus(int32_t newStatus) {
    std::lock_guard<std::mutex> lock(mLock);
    status = newStatus;
}

bool CameraManagerGlobal::StatusAndHAL3Support::addUnavailablePhysicalId(
        const std::string& physicalCameraId) {
    std::lock_guard<std::mutex> lock(mLock);
    auto result = unavailablePhysicalIds.insert(physicalCameraId);
    return result.second;
}

bool CameraManagerGlobal::StatusAndHAL3Support::removeUnavailablePhysicalId(
        const std::string& physicalCameraId) {
    std::lock_guard<std::mutex> lock(mLock);
    auto count = unavailablePhysicalIds.erase(physicalCameraId);
    return count > 0;
}

std::set<std::string> CameraManagerGlobal::StatusAndHAL3Support::getUnavailablePhysicalIds() {
    std::lock_guard<std::mutex> lock(mLock);
    return unavailablePhysicalIds;
}

} // namespace acam
} // namespace android

/**
 * ACameraManger Implementation
 */
camera_status_t
ACameraManager::getCameraIdList(ACameraIdList** cameraIdList) {
    Mutex::Autolock _l(mLock);

    std::vector<std::string> idList;
    mGlobalManager->getCameraIdList(mDeviceContext, &idList);

    int numCameras = idList.size();
    ACameraIdList *out = new ACameraIdList;
    if (!out) {
        ALOGE("Allocate memory for ACameraIdList failed!");
        return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
    }
    out->numCameras = numCameras;
    out->cameraIds = new const char*[numCameras];
    if (!out->cameraIds) {
        ALOGE("Allocate memory for ACameraIdList failed!");
        deleteCameraIdList(out);
        return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
    }
    for (int i = 0; i < numCameras; i++) {
        const char* src = idList[i].c_str();
        size_t dstSize = strlen(src) + 1;
        char* dst = new char[dstSize];
        if (!dst) {
            ALOGE("Allocate memory for ACameraIdList failed!");
            deleteCameraIdList(out);
            return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
        }
        strlcpy(dst, src, dstSize);
        out->cameraIds[i] = dst;
    }
    *cameraIdList = out;
    return ACAMERA_OK;
}

void
ACameraManager::deleteCameraIdList(ACameraIdList* cameraIdList) {
    if (cameraIdList != nullptr) {
        if (cameraIdList->cameraIds != nullptr) {
            for (int i = 0; i < cameraIdList->numCameras; i ++) {
                if (cameraIdList->cameraIds[i] != nullptr) {
                    delete[] cameraIdList->cameraIds[i];
                }
            }
            delete[] cameraIdList->cameraIds;
        }
        delete cameraIdList;
    }
}

camera_status_t ACameraManager::getCameraCharacteristics(
        const char* cameraIdStr, sp<ACameraMetadata>* characteristics) {
    Mutex::Autolock _l(mLock);

    sp<hardware::ICameraService> cs = mGlobalManager->getCameraService();
    if (cs == nullptr) {
        ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
        return ACAMERA_ERROR_CAMERA_DISCONNECTED;
    }

    CameraMetadata rawMetadata;
    int targetSdkVersion = android_get_application_target_sdk_version();

    AttributionSourceState clientAttribution;
    clientAttribution.uid = hardware::ICameraService::USE_CALLING_UID;
    clientAttribution.pid = hardware::ICameraService::USE_CALLING_PID;
    clientAttribution.deviceId = mDeviceContext.deviceId;

    binder::Status serviceRet = cs->getCameraCharacteristics(cameraIdStr,
            targetSdkVersion, /*rotationOverride*/hardware::ICameraService::ROTATION_OVERRIDE_NONE,
            clientAttribution, static_cast<int32_t>(mDeviceContext.policy),
            &rawMetadata);
    if (!serviceRet.isOk()) {
        switch(serviceRet.serviceSpecificErrorCode()) {
            case hardware::ICameraService::ERROR_DISCONNECTED:
                ALOGE("%s: Camera %s has been disconnected", __FUNCTION__, cameraIdStr);
                return ACAMERA_ERROR_CAMERA_DISCONNECTED;
            case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
                ALOGE("%s: Camera ID %s does not exist!", __FUNCTION__, cameraIdStr);
                return ACAMERA_ERROR_INVALID_PARAMETER;
            default:
                ALOGE("Get camera characteristics from camera service failed: %s",
                        serviceRet.toString8().c_str());
                return ACAMERA_ERROR_UNKNOWN; // should not reach here
        }
    }

    *characteristics = new ACameraMetadata(
            rawMetadata.release(), ACameraMetadata::ACM_CHARACTERISTICS);
    return ACAMERA_OK;
}

camera_status_t
ACameraManager::isCameraDeviceSharingSupported(
        const char* cameraId,
        /*out*/bool* isSharingSupported) {
    if (!flags::camera_multi_client()) {
        return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
    }
    sp<ACameraMetadata> spChars;
    camera_status_t ret = getCameraCharacteristics(cameraId, &spChars);
    if (ret != ACAMERA_OK) {
        ALOGE("%s: cannot get camera characteristics for camera %s. err %d",
                __FUNCTION__, cameraId, ret);
        return ret;
    }

    ACameraMetadata* chars = spChars.get();
    ACameraMetadata_const_entry entry;
    ret = ACameraMetadata_getConstEntry(chars, ANDROID_SHARED_SESSION_OUTPUT_CONFIGURATIONS,
            &entry);
    if (ret != ACAMERA_OK) {
        return ret;
    }
    *isSharingSupported =  (entry.count > 0) ? true : false;
    return ACAMERA_OK;
}

camera_status_t
ACameraManager::openCamera(
        const char* cameraId, bool sharedMode,
        ACameraDevice_StateCallbacks* callback,
        /*out*/ACameraDevice** outDevice, /*out*/bool* primaryClient) {
    sp<ACameraMetadata> chars;
    camera_status_t ret = getCameraCharacteristics(cameraId, &chars);
    Mutex::Autolock _l(mLock);
    if (ret != ACAMERA_OK) {
        ALOGE("%s: cannot get camera characteristics for camera %s. err %d",
                __FUNCTION__, cameraId, ret);
        return ACAMERA_ERROR_INVALID_PARAMETER;
    }

    ACameraDevice* device = new ACameraDevice(cameraId, callback, chars, sharedMode);

    sp<hardware::ICameraService> cs = mGlobalManager->getCameraService();
    if (cs == nullptr) {
        ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
        delete device;
        return ACAMERA_ERROR_CAMERA_DISCONNECTED;
    }

    sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = device->getServiceCallback();
    sp<hardware::camera2::ICameraDeviceUser> deviceRemote;
    int targetSdkVersion = android_get_application_target_sdk_version();

    AttributionSourceState clientAttribution;
    clientAttribution.uid = hardware::ICameraService::USE_CALLING_UID;
    clientAttribution.pid = hardware::ICameraService::USE_CALLING_PID;
    clientAttribution.deviceId = mDeviceContext.deviceId;
    clientAttribution.packageName = "";
    clientAttribution.attributionTag = std::nullopt;
    clientAttribution.token = sp<BBinder>::make();

    // No way to get package name from native.
    // Send a zero length package name and let camera service figure it out from UID
    binder::Status serviceRet = cs->connectDevice(
            callbacks, cameraId, /*oomScoreOffset*/0,
            targetSdkVersion, /*rotationOverride*/hardware::ICameraService::ROTATION_OVERRIDE_NONE,
            clientAttribution, static_cast<int32_t>(mDeviceContext.policy), sharedMode,
            /*out*/&deviceRemote);

    if (!serviceRet.isOk()) {
        ALOGE("%s: connect camera device failed: %s", __FUNCTION__, serviceRet.toString8().c_str());
        // Convert serviceRet to camera_status_t
        switch(serviceRet.serviceSpecificErrorCode()) {
            case hardware::ICameraService::ERROR_DISCONNECTED:
                ret = ACAMERA_ERROR_CAMERA_DISCONNECTED;
                break;
            case hardware::ICameraService::ERROR_CAMERA_IN_USE:
                ret = ACAMERA_ERROR_CAMERA_IN_USE;
                break;
            case hardware::ICameraService::ERROR_MAX_CAMERAS_IN_USE:
                ret = ACAMERA_ERROR_MAX_CAMERA_IN_USE;
                break;
            case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
                ret = ACAMERA_ERROR_INVALID_PARAMETER;
                break;
            case hardware::ICameraService::ERROR_DEPRECATED_HAL:
                // Should not reach here since we filtered legacy HALs earlier
                ret = ACAMERA_ERROR_INVALID_PARAMETER;
                break;
            case hardware::ICameraService::ERROR_DISABLED:
                ret = ACAMERA_ERROR_CAMERA_DISABLED;
                break;
            case hardware::ICameraService::ERROR_PERMISSION_DENIED:
                ret = ACAMERA_ERROR_PERMISSION_DENIED;
                break;
            case hardware::ICameraService::ERROR_INVALID_OPERATION:
            default:
                ret = ACAMERA_ERROR_UNKNOWN;
                break;
        }

        delete device;
        return ret;
    }
    if (deviceRemote == nullptr) {
        ALOGE("%s: connect camera device failed! remote device is null", __FUNCTION__);
        delete device;
        return ACAMERA_ERROR_CAMERA_DISCONNECTED;
    }
    device->setRemoteDevice(deviceRemote);
    device->setDeviceMetadataQueues();
    if (flags::camera_multi_client() && sharedMode) {
        binder::Status remoteRet = deviceRemote->isPrimaryClient(primaryClient);
        if (!remoteRet.isOk()) {
            delete device;
            return ACAMERA_ERROR_UNKNOWN;
        }
        device->setPrimaryClient(*primaryClient);
    }
    *outDevice = device;
    return ACAMERA_OK;
}

void ACameraManager::registerAvailabilityCallback(
        const ACameraManager_AvailabilityCallbacks* callback) {
    mGlobalManager->registerAvailabilityCallback(mDeviceContext, callback);
}

void ACameraManager::unregisterAvailabilityCallback(
        const ACameraManager_AvailabilityCallbacks* callback) {
    mGlobalManager->unregisterAvailabilityCallback(mDeviceContext, callback);
}

void ACameraManager::registerExtendedAvailabilityCallback(
        const ACameraManager_ExtendedAvailabilityCallbacks* callback) {
    mGlobalManager->registerExtendedAvailabilityCallback(mDeviceContext, callback);
}

void ACameraManager::unregisterExtendedAvailabilityCallback(
        const ACameraManager_ExtendedAvailabilityCallbacks* callback) {
    mGlobalManager->unregisterExtendedAvailabilityCallback(mDeviceContext, callback);
}
