/*
 * 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.
 */

#ifndef ANDROID_HARDWARE_RADIO_SERVICE_H
#define ANDROID_HARDWARE_RADIO_SERVICE_H

#include <utils/Vector.h>
//#include <binder/AppOpsManager.h>
#include <binder/MemoryDealer.h>
#include <binder/BinderService.h>
#include <binder/IAppOpsCallback.h>
#include <radio/IRadioService.h>
#include <radio/IRadio.h>
#include <radio/IRadioClient.h>
#include <system/radio.h>
#include <hardware/radio.h>
#include "RadioInterface.h"
#include "TunerInterface.h"
#include "TunerCallbackInterface.h"

namespace android {

class MemoryHeapBase;

class RadioService :
    public BinderService<RadioService>,
    public BnRadioService
{
    friend class BinderService<RadioService>;

public:
    class ModuleClient;
    class Module;

    static char const* getServiceName() { return "media.radio"; }

                        RadioService();
    virtual             ~RadioService();

    // IRadioService
    virtual status_t listModules(struct radio_properties *properties,
                                 uint32_t *numModules);

    virtual status_t attach(radio_handle_t handle,
                            const sp<IRadioClient>& client,
                            const struct radio_band_config *config,
                            bool withAudio,
                            sp<IRadio>& radio);

    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);


    class Module : public virtual RefBase {
    public:

       Module(sp<RadioInterface> hwDevice,
              struct radio_properties properties);

       virtual ~Module();

               sp<ModuleClient> addClient(const sp<IRadioClient>& client,
                                  const struct radio_band_config *config,
                                  bool audio);

               void removeClient(const sp<ModuleClient>& moduleClient);

               status_t setMute(bool mute);

               status_t getMute(bool *mute);

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

       sp<RadioInterface> hwDevice() const { return mHwDevice; }
       const struct radio_properties properties() const { return mProperties; }
       const struct radio_band_config *getDefaultConfig() const ;

    private:

       void notifyDeviceConnection(bool connected, const char *address);

        Mutex                         mLock;          // protects  mModuleClients
        sp<RadioInterface>            mHwDevice;      // HAL hardware device
        const struct radio_properties mProperties;    // cached hardware module properties
        Vector< sp<ModuleClient> >    mModuleClients; // list of attached clients
        bool                          mMute;          // radio audio source state
                                                      // when unmuted, audio is routed to the
                                                      // output device selected for media use case.
    }; // class Module

    class CallbackThread : public Thread {
    public:

        explicit CallbackThread(const wp<ModuleClient>& moduleClient);

        virtual ~CallbackThread();


        // Thread virtuals
        virtual bool threadLoop();

        // RefBase
        virtual void onFirstRef();

                void exit();

                void sendEvent(radio_hal_event_t *halEvent);
                sp<IMemory> prepareEvent(radio_hal_event_t *halEvent);

    private:
        wp<ModuleClient>      mModuleClient;    // client module the thread belongs to
        Condition             mCallbackCond;    // condition signaled when a new event is posted
        Mutex                 mCallbackLock;    // protects mEventQueue
        Vector< sp<IMemory> > mEventQueue;      // pending callback events
        sp<MemoryDealer>      mMemoryDealer;    // shared memory for callback event
    }; // class CallbackThread

    class ModuleClient : public BnRadio,
                   public IBinder::DeathRecipient,
                   public TunerCallbackInterface {
    public:

       ModuleClient(const sp<Module>& module,
              const sp<IRadioClient>& client,
              const struct radio_band_config *config,
              bool audio);

       virtual ~ModuleClient();

       // IRadio
       virtual void detach();

       virtual status_t setConfiguration(const struct radio_band_config *config);

       virtual status_t getConfiguration(struct radio_band_config *config);

       virtual status_t setMute(bool mute);

       virtual status_t getMute(bool *mute);

       virtual status_t scan(radio_direction_t direction, bool skipSubChannel);

       virtual status_t step(radio_direction_t direction, bool skipSubChannel);

       virtual status_t tune(unsigned int channel, unsigned int subChannel);

       virtual status_t cancel();

       virtual status_t getProgramInformation(struct radio_program_info *info);

       virtual status_t hasControl(bool *hasControl);

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

               sp<IRadioClient> client() const { return mClient; }
               wp<Module> module() const { return mModule; }
               radio_hal_band_config_t halConfig() const;
               sp<CallbackThread> callbackThread() const { return mCallbackThread; }
               void setTuner(sp<TunerInterface>& tuner);
               sp<TunerInterface>& getTuner();
               bool audio() const { return mAudio; }

               void onCallbackEvent(const sp<IMemory>& event);

       virtual void onFirstRef();


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

       // TunerCallbackInterface
       virtual void onEvent(radio_hal_event_t *event);

    private:

        mutable Mutex               mLock;           // protects mClient, mConfig and mTuner
        wp<Module>                  mModule;         // The module this client is attached to
        sp<IRadioClient>            mClient;         // event callback binder interface
        radio_band_config_t         mConfig;         // current band configuration
        sp<CallbackThread>          mCallbackThread; // event callback thread
        const bool                  mAudio;
        sp<TunerInterface>          mTuner;        // HAL tuner interface. NULL indicates that
                                                    // this client does not have control on any
                                                    // tuner
    }; // class ModuleClient


    static void callback(radio_hal_event_t *halEvent, void *cookie);

private:

    virtual void onFirstRef();

    static void convertProperties(radio_properties_t *properties,
                                  const radio_hal_properties_t *halProperties);
    Mutex               mServiceLock;   // protects mModules
    volatile int32_t    mNextUniqueId;  // for module ID allocation
    DefaultKeyedVector< radio_handle_t, sp<Module> > mModules;
};

} // namespace android

#endif // ANDROID_HARDWARE_RADIO_SERVICE_H
