/*
 * Copyright (C) 2013 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_TAG "ProCamera2Client"
#define ATRACE_TAG ATRACE_TAG_CAMERA
//#define LOG_NDEBUG 0

#include <utils/Log.h>
#include <utils/Trace.h>

#include <cutils/properties.h>
#include <gui/Surface.h>
#include <gui/Surface.h>
#include "camera2/Parameters.h"
#include "ProCamera2Client.h"
#include "camera2/ProFrameProcessor.h"
#include "CameraDeviceBase.h"

namespace android {
using namespace camera2;

// Interface used by CameraService

ProCamera2Client::ProCamera2Client(const sp<CameraService>& cameraService,
                                   const sp<IProCameraCallbacks>& remoteCallback,
                                   const String16& clientPackageName,
                                   int cameraId,
                                   int cameraFacing,
                                   int clientPid,
                                   uid_t clientUid,
                                   int servicePid) :
    Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
                cameraId, cameraFacing, clientPid, clientUid, servicePid)
{
    ATRACE_CALL();
    ALOGI("ProCamera %d: Opened", cameraId);

    mExclusiveLock = false;
}

status_t ProCamera2Client::initialize(camera_module_t *module)
{
    ATRACE_CALL();
    status_t res;

    res = Camera2ClientBase::initialize(module);
    if (res != OK) {
        return res;
    }

    String8 threadName;
    mFrameProcessor = new ProFrameProcessor(mDevice);
    threadName = String8::format("PC2-%d-FrameProc", mCameraId);
    mFrameProcessor->run(threadName.string());

    mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
                                      FRAME_PROCESSOR_LISTENER_MAX_ID,
                                      /*listener*/this);

    return OK;
}

ProCamera2Client::~ProCamera2Client() {
}

status_t ProCamera2Client::exclusiveTryLock() {
    ATRACE_CALL();
    ALOGV("%s", __FUNCTION__);

    Mutex::Autolock icl(mBinderSerializationLock);
    SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);

    if (!mDevice.get()) return PERMISSION_DENIED;

    if (!mExclusiveLock) {
        mExclusiveLock = true;

        if (mRemoteCallback != NULL) {
            mRemoteCallback->onLockStatusChanged(
                              IProCameraCallbacks::LOCK_ACQUIRED);
        }

        ALOGV("%s: exclusive lock acquired", __FUNCTION__);

        return OK;
    }

    // TODO: have a PERMISSION_DENIED case for when someone else owns the lock

    // don't allow recursive locking
    ALOGW("%s: exclusive lock already exists - recursive locking is not"
          "allowed", __FUNCTION__);

    return ALREADY_EXISTS;
}

status_t ProCamera2Client::exclusiveLock() {
    ATRACE_CALL();
    ALOGV("%s", __FUNCTION__);

    Mutex::Autolock icl(mBinderSerializationLock);
    SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);

    if (!mDevice.get()) return PERMISSION_DENIED;

    /**
     * TODO: this should asynchronously 'wait' until the lock becomes available
     * if another client already has an exclusive lock.
     *
     * once we have proper sharing support this will need to do
     * more than just return immediately
     */
    if (!mExclusiveLock) {
        mExclusiveLock = true;

        if (mRemoteCallback != NULL) {
            mRemoteCallback->onLockStatusChanged(IProCameraCallbacks::LOCK_ACQUIRED);
        }

        ALOGV("%s: exclusive lock acquired", __FUNCTION__);

        return OK;
    }

    // don't allow recursive locking
    ALOGW("%s: exclusive lock already exists - recursive locking is not allowed"
                                                                , __FUNCTION__);
    return ALREADY_EXISTS;
}

status_t ProCamera2Client::exclusiveUnlock() {
    ATRACE_CALL();
    ALOGV("%s", __FUNCTION__);

    Mutex::Autolock icl(mBinderSerializationLock);
    SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);

    // don't allow unlocking if we have no lock
    if (!mExclusiveLock) {
        ALOGW("%s: cannot unlock, no lock was held in the first place",
              __FUNCTION__);
        return BAD_VALUE;
    }

    mExclusiveLock = false;
    if (mRemoteCallback != NULL ) {
        mRemoteCallback->onLockStatusChanged(
                                       IProCameraCallbacks::LOCK_RELEASED);
    }
    ALOGV("%s: exclusive lock released", __FUNCTION__);

    return OK;
}

bool ProCamera2Client::hasExclusiveLock() {
    Mutex::Autolock icl(mBinderSerializationLock);
    return mExclusiveLock;
}

void ProCamera2Client::onExclusiveLockStolen() {
    ALOGV("%s: ProClient lost exclusivity (id %d)",
          __FUNCTION__, mCameraId);

    Mutex::Autolock icl(mBinderSerializationLock);
    SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);

    if (mExclusiveLock && mRemoteCallback.get() != NULL) {
        mRemoteCallback->onLockStatusChanged(
                                       IProCameraCallbacks::LOCK_STOLEN);
    }

    mExclusiveLock = false;

    //TODO: we should not need to detach the device, merely reset it.
    detachDevice();
}

status_t ProCamera2Client::submitRequest(camera_metadata_t* request,
                                         bool streaming) {
    ATRACE_CALL();
    ALOGV("%s", __FUNCTION__);

    Mutex::Autolock icl(mBinderSerializationLock);

    if (!mDevice.get()) return DEAD_OBJECT;

    if (!mExclusiveLock) {
        return PERMISSION_DENIED;
    }

    CameraMetadata metadata(request);

    if (!enforceRequestPermissions(metadata)) {
        return PERMISSION_DENIED;
    }

    if (streaming) {
        return mDevice->setStreamingRequest(metadata);
    } else {
        return mDevice->capture(metadata);
    }

    // unreachable. thx gcc for a useless warning
    return OK;
}

status_t ProCamera2Client::cancelRequest(int requestId) {
    ATRACE_CALL();
    ALOGV("%s", __FUNCTION__);

    Mutex::Autolock icl(mBinderSerializationLock);

    if (!mDevice.get()) return DEAD_OBJECT;

    if (!mExclusiveLock) {
        return PERMISSION_DENIED;
    }

    // TODO: implement
    ALOGE("%s: not fully implemented yet", __FUNCTION__);
    return INVALID_OPERATION;
}

status_t ProCamera2Client::deleteStream(int streamId) {
    ATRACE_CALL();
    ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);

    status_t res;
    if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

    Mutex::Autolock icl(mBinderSerializationLock);

    if (!mDevice.get()) return DEAD_OBJECT;
    mDevice->clearStreamingRequest();

    status_t code;
    if ((code = mDevice->waitUntilDrained()) != OK) {
        ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__, code);
    }

    return mDevice->deleteStream(streamId);
}

status_t ProCamera2Client::createStream(int width, int height, int format,
                      const sp<IGraphicBufferProducer>& bufferProducer,
                      /*out*/
                      int* streamId)
{
    if (streamId) {
        *streamId = -1;
    }

    ATRACE_CALL();
    ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);

    status_t res;
    if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

    Mutex::Autolock icl(mBinderSerializationLock);

    if (!mDevice.get()) return DEAD_OBJECT;

    sp<IBinder> binder;
    sp<ANativeWindow> window;
    if (bufferProducer != 0) {
        binder = bufferProducer->asBinder();
        window = new Surface(bufferProducer);
    }

    return mDevice->createStream(window, width, height, format, /*size*/1,
                                 streamId);
}

// Create a request object from a template.
// -- Caller owns the newly allocated metadata
status_t ProCamera2Client::createDefaultRequest(int templateId,
                             /*out*/
                              camera_metadata** request)
{
    ATRACE_CALL();
    ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);

    if (request) {
        *request = NULL;
    }

    status_t res;
    if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

    Mutex::Autolock icl(mBinderSerializationLock);

    if (!mDevice.get()) return DEAD_OBJECT;

    CameraMetadata metadata;
    if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK) {
        *request = metadata.release();
    }

    return res;
}

status_t ProCamera2Client::getCameraInfo(int cameraId,
                                         /*out*/
                                         camera_metadata** info)
{
    if (cameraId != mCameraId) {
        return INVALID_OPERATION;
    }

    Mutex::Autolock icl(mBinderSerializationLock);

    if (!mDevice.get()) return DEAD_OBJECT;

    CameraMetadata deviceInfo = mDevice->info();
    *info = deviceInfo.release();

    return OK;
}

status_t ProCamera2Client::dump(int fd, const Vector<String16>& args) {
    String8 result;
    result.appendFormat("ProCamera2Client[%d] (%p) PID: %d, dump:\n",
            mCameraId,
            getRemoteCallback()->asBinder().get(),
            mClientPid);
    result.append("  State: ");

    // TODO: print dynamic/request section from most recent requests
    mFrameProcessor->dump(fd, args);

    return dumpDevice(fd, args);
}

// IProCameraUser interface

void ProCamera2Client::detachDevice() {
    if (mDevice == 0) return;

    ALOGV("Camera %d: Stopping processors", mCameraId);

    mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
                                    FRAME_PROCESSOR_LISTENER_MAX_ID,
                                    /*listener*/this);
    mFrameProcessor->requestExit();
    ALOGV("Camera %d: Waiting for threads", mCameraId);
    mFrameProcessor->join();
    ALOGV("Camera %d: Disconnecting device", mCameraId);

    // WORKAROUND: HAL refuses to disconnect while there's streams in flight
    {
        mDevice->clearStreamingRequest();

        status_t code;
        if ((code = mDevice->waitUntilDrained()) != OK) {
            ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
                  code);
        }
    }

    Camera2ClientBase::detachDevice();
}

/** Device-related methods */
void ProCamera2Client::onFrameAvailable(int32_t frameId,
                                        const CameraMetadata& frame) {
    ATRACE_CALL();
    ALOGV("%s", __FUNCTION__);

    Mutex::Autolock icl(mBinderSerializationLock);
    SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);

    if (mRemoteCallback != NULL) {
        CameraMetadata tmp(frame);
        camera_metadata_t* meta = tmp.release();
        ALOGV("%s: meta = %p ", __FUNCTION__, meta);
        mRemoteCallback->onResultReceived(frameId, meta);
        tmp.acquire(meta);
    }

}

bool ProCamera2Client::enforceRequestPermissions(CameraMetadata& metadata) {

    const int pid = IPCThreadState::self()->getCallingPid();
    const int selfPid = getpid();
    camera_metadata_entry_t entry;

    /**
     * Mixin default important security values
     * - android.led.transmit = defaulted ON
     */
    CameraMetadata staticInfo = mDevice->info();
    entry = staticInfo.find(ANDROID_LED_AVAILABLE_LEDS);
    for(size_t i = 0; i < entry.count; ++i) {
        uint8_t led = entry.data.u8[i];

        switch(led) {
            case ANDROID_LED_AVAILABLE_LEDS_TRANSMIT: {
                uint8_t transmitDefault = ANDROID_LED_TRANSMIT_ON;
                if (!metadata.exists(ANDROID_LED_TRANSMIT)) {
                    metadata.update(ANDROID_LED_TRANSMIT,
                                    &transmitDefault, 1);
                }
                break;
            }
        }
    }

    // We can do anything!
    if (pid == selfPid) {
        return true;
    }

    /**
     * Permission check special fields in the request
     * - android.led.transmit = android.permission.CAMERA_DISABLE_TRANSMIT
     */
    entry = metadata.find(ANDROID_LED_TRANSMIT);
    if (entry.count > 0 && entry.data.u8[0] != ANDROID_LED_TRANSMIT_ON) {
        String16 permissionString =
            String16("android.permission.CAMERA_DISABLE_TRANSMIT_LED");
        if (!checkCallingPermission(permissionString)) {
            const int uid = IPCThreadState::self()->getCallingUid();
            ALOGE("Permission Denial: "
                  "can't disable transmit LED pid=%d, uid=%d", pid, uid);
            return false;
        }
    }

    return true;
}

} // namespace android
