/*
**
** Copyright (C) 2008, 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.
*/

#ifndef ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
#define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H

#include <utils/Vector.h>
#include <binder/AppOpsManager.h>
#include <binder/BinderService.h>
#include <binder/IAppOpsCallback.h>
#include <camera/ICameraService.h>
#include <hardware/camera.h>

#include <camera/ICamera.h>
#include <camera/ICameraClient.h>
#include <camera/IProCameraUser.h>
#include <camera/IProCameraCallbacks.h>

#include <camera/ICameraServiceListener.h>

/* This needs to be increased if we can have more cameras */
#define MAX_CAMERAS 2

namespace android {

extern volatile int32_t gLogLevel;

class MemoryHeapBase;
class MediaPlayer;

class CameraService :
    public BinderService<CameraService>,
    public BnCameraService,
    public IBinder::DeathRecipient,
    public camera_module_callbacks_t
{
    friend class BinderService<CameraService>;
public:
    class Client;
    class BasicClient;

    // Implementation of BinderService<T>
    static char const* getServiceName() { return "media.camera"; }

                        CameraService();
    virtual             ~CameraService();

    /////////////////////////////////////////////////////////////////////
    // HAL Callbacks
    virtual void        onDeviceStatusChanged(int cameraId,
                                              int newStatus);

    /////////////////////////////////////////////////////////////////////
    // ICameraService
    virtual int32_t     getNumberOfCameras();
    virtual status_t    getCameraInfo(int cameraId,
                                      struct CameraInfo* cameraInfo);

    virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId,
            const String16& clientPackageName, int clientUid);
    virtual sp<IProCameraUser> connect(const sp<IProCameraCallbacks>& cameraCb,
            int cameraId, const String16& clientPackageName, int clientUid);

    virtual status_t    addListener(const sp<ICameraServiceListener>& listener);
    virtual status_t    removeListener(
                                    const sp<ICameraServiceListener>& listener);

    // Extra permissions checks
    virtual status_t    onTransact(uint32_t code, const Parcel& data,
                                   Parcel* reply, uint32_t flags);

    virtual status_t    dump(int fd, const Vector<String16>& args);

    /////////////////////////////////////////////////////////////////////
    // Client functionality
    virtual void        removeClientByRemote(const wp<IBinder>& remoteBinder);

    enum sound_kind {
        SOUND_SHUTTER = 0,
        SOUND_RECORDING = 1,
        NUM_SOUNDS
    };

    void                loadSound();
    void                playSound(sound_kind kind);
    void                releaseSound();


    /////////////////////////////////////////////////////////////////////
    // CameraClient functionality

    // returns plain pointer of client. Note that mClientLock should be acquired to
    // prevent the client from destruction. The result can be NULL.
    virtual Client*     getClientByIdUnsafe(int cameraId);
    virtual Mutex*      getClientLockById(int cameraId);

    class BasicClient : public virtual RefBase {
    public:
        virtual status_t initialize(camera_module_t *module) = 0;

        virtual void          disconnect() = 0;

        // Return the remote callback binder object (e.g. IProCameraCallbacks)
        wp<IBinder>     getRemote() {
            return mRemoteBinder;
        }

    protected:
        BasicClient(const sp<CameraService>& cameraService,
                const sp<IBinder>& remoteCallback,
                const String16& clientPackageName,
                int cameraId,
                int cameraFacing,
                int clientPid,
                uid_t clientUid,
                int servicePid);

        virtual ~BasicClient();

        // the instance is in the middle of destruction. When this is set,
        // the instance should not be accessed from callback.
        // CameraService's mClientLock should be acquired to access this.
        // - subclasses should set this to true in their destructors.
        bool                            mDestructionStarted;

        // these are initialized in the constructor.
        sp<CameraService>               mCameraService;  // immutable after constructor
        int                             mCameraId;       // immutable after constructor
        int                             mCameraFacing;   // immutable after constructor
        const String16                  mClientPackageName;
        pid_t                           mClientPid;
        uid_t                           mClientUid;      // immutable after constructor
        pid_t                           mServicePid;     // immutable after constructor

        // - The app-side Binder interface to receive callbacks from us
        wp<IBinder>                     mRemoteBinder;   // immutable after constructor

        // permissions management
        status_t                        startCameraOps();
        status_t                        finishCameraOps();

        // Notify client about a fatal error
        virtual void                    notifyError() = 0;
    private:
        AppOpsManager                   mAppOpsManager;

        class OpsCallback : public BnAppOpsCallback {
        public:
            OpsCallback(wp<BasicClient> client);
            virtual void opChanged(int32_t op, const String16& packageName);

        private:
            wp<BasicClient> mClient;

        }; // class OpsCallback

        sp<OpsCallback> mOpsCallback;
        // Track whether startCameraOps was called successfully, to avoid
        // finishing what we didn't start.
        bool            mOpsActive;

        // IAppOpsCallback interface, indirected through opListener
        virtual void opChanged(int32_t op, const String16& packageName);
    }; // class BasicClient

    class Client : public BnCamera, public BasicClient
    {
    public:
        typedef ICameraClient TCamCallbacks;

        // ICamera interface (see ICamera for details)
        virtual void          disconnect();
        virtual status_t      connect(const sp<ICameraClient>& client) = 0;
        virtual status_t      lock() = 0;
        virtual status_t      unlock() = 0;
        virtual status_t      setPreviewDisplay(const sp<Surface>& surface) = 0;
        virtual status_t      setPreviewTexture(const sp<IGraphicBufferProducer>& bufferProducer)=0;
        virtual void          setPreviewCallbackFlag(int flag) = 0;
        virtual status_t      startPreview() = 0;
        virtual void          stopPreview() = 0;
        virtual bool          previewEnabled() = 0;
        virtual status_t      storeMetaDataInBuffers(bool enabled) = 0;
        virtual status_t      startRecording() = 0;
        virtual void          stopRecording() = 0;
        virtual bool          recordingEnabled() = 0;
        virtual void          releaseRecordingFrame(const sp<IMemory>& mem) = 0;
        virtual status_t      autoFocus() = 0;
        virtual status_t      cancelAutoFocus() = 0;
        virtual status_t      takePicture(int msgType) = 0;
        virtual status_t      setParameters(const String8& params) = 0;
        virtual String8       getParameters() const = 0;
        virtual status_t      sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0;

        // Interface used by CameraService
        Client(const sp<CameraService>& cameraService,
                const sp<ICameraClient>& cameraClient,
                const String16& clientPackageName,
                int cameraId,
                int cameraFacing,
                int clientPid,
                uid_t clientUid,
                int servicePid);
        ~Client();

        // return our camera client
        const sp<ICameraClient>&    getRemoteCallback() {
            return mRemoteCallback;
        }

    protected:
        static Mutex*        getClientLockFromCookie(void* user);
        // convert client from cookie. Client lock should be acquired before getting Client.
        static Client*       getClientFromCookie(void* user);

        virtual void         notifyError();

        // Initialized in constructor

        // - The app-side Binder interface to receive callbacks from us
        sp<ICameraClient>               mRemoteCallback;

    }; // class Client

    class ProClient : public BnProCameraUser, public BasicClient {
    public:
        typedef IProCameraCallbacks TCamCallbacks;

        ProClient(const sp<CameraService>& cameraService,
                const sp<IProCameraCallbacks>& remoteCallback,
                const String16& clientPackageName,
                int cameraId,
                int cameraFacing,
                int clientPid,
                uid_t clientUid,
                int servicePid);

        virtual ~ProClient();

        const sp<IProCameraCallbacks>& getRemoteCallback() {
            return mRemoteCallback;
        }

        /***
            IProCamera implementation
         ***/
        virtual status_t      connect(const sp<IProCameraCallbacks>& callbacks)
                                                                            = 0;
        virtual status_t      exclusiveTryLock() = 0;
        virtual status_t      exclusiveLock() = 0;
        virtual status_t      exclusiveUnlock() = 0;

        virtual bool          hasExclusiveLock() = 0;

        // Note that the callee gets a copy of the metadata.
        virtual int           submitRequest(camera_metadata_t* metadata,
                                            bool streaming = false) = 0;
        virtual status_t      cancelRequest(int requestId) = 0;

        // Callbacks from camera service
        virtual void          onExclusiveLockStolen() = 0;

    protected:
        virtual void          notifyError();

        sp<IProCameraCallbacks> mRemoteCallback;
    }; // class ProClient

private:

    // Delay-load the Camera HAL module
    virtual void onFirstRef();

    // Step 1. Check if we can connect, before we acquire the service lock.
    bool                validateConnect(int cameraId,
                                        /*inout*/
                                        int& clientUid) const;

    // Step 2. Check if we can connect, after we acquire the service lock.
    bool                canConnectUnsafe(int cameraId,
                                         const String16& clientPackageName,
                                         const sp<IBinder>& remoteCallback,
                                         /*out*/
                                         sp<Client> &client);

    // When connection is successful, initialize client and track its death
    bool                connectFinishUnsafe(const sp<BasicClient>& client,
                                            const sp<IBinder>& clientBinder);

    virtual sp<BasicClient>  getClientByRemote(const wp<IBinder>& cameraClient);

    Mutex               mServiceLock;
    wp<Client>          mClient[MAX_CAMERAS];  // protected by mServiceLock
    Mutex               mClientLock[MAX_CAMERAS]; // prevent Client destruction inside callbacks
    int                 mNumberOfCameras;

    typedef wp<ProClient> weak_pro_client_ptr;
    Vector<weak_pro_client_ptr> mProClientList[MAX_CAMERAS];

    // needs to be called with mServiceLock held
    sp<Client>          findClientUnsafe(const wp<IBinder>& cameraClient, int& outIndex);
    sp<ProClient>       findProClientUnsafe(
                                     const wp<IBinder>& cameraCallbacksRemote);

    // atomics to record whether the hardware is allocated to some client.
    volatile int32_t    mBusy[MAX_CAMERAS];
    void                setCameraBusy(int cameraId);
    void                setCameraFree(int cameraId);

    // sounds
    MediaPlayer*        newMediaPlayer(const char *file);

    Mutex               mSoundLock;
    sp<MediaPlayer>     mSoundPlayer[NUM_SOUNDS];
    int                 mSoundRef;  // reference count (release all MediaPlayer when 0)

    camera_module_t *mModule;

    Vector<sp<ICameraServiceListener> >
                        mListenerList;

    // guard only mStatusList and the broadcasting of ICameraServiceListener
    mutable Mutex       mStatusMutex;
    ICameraServiceListener::Status
                        mStatusList[MAX_CAMERAS];

    // Read the current status (locks mStatusMutex)
    ICameraServiceListener::Status
                        getStatus(int cameraId) const;

    // Broadcast the new status if it changed (locks the service mutex)
    void                updateStatus(
                            ICameraServiceListener::Status status,
                            int32_t cameraId);
    // Call this one when the service mutex is already held (idempotent)
    void                updateStatusUnsafe(
                            ICameraServiceListener::Status status,
                            int32_t cameraId);

    // IBinder::DeathRecipient implementation
    virtual void        binderDied(const wp<IBinder> &who);

    // Helpers
    int                 getDeviceVersion(int cameraId, int* facing);

    bool                isValidCameraId(int cameraId);
};

} // namespace android

#endif
