text: /*
  // Copyright (c) 2014 Intel Corporation 
  //
  // 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 __MULTIDISPLAY_OBSERVER_H
  #define __MULTIDISPLAY_OBSERVER_H
  
  #ifdef TARGET_HAS_MULTIPLE_DISPLAY
  #include <display/MultiDisplayService.h>
  #include <SimpleThread.h>
  #else
  #include <utils/Errors.h>
  #endif
  #include <string.h>
  
  namespace android {
  namespace intel {
  
  struct VideoSourceInfo {
      VideoSourceInfo() {
          memset(this, 0, sizeof(VideoSourceInfo));
      }
      int width;
      int height;
      int frameRate;
      bool isProtected;
  };
  
  
  #ifdef TARGET_HAS_MULTIPLE_DISPLAY
  
  class MultiDisplayObserver;
  
  class MultiDisplayCallback : public BnMultiDisplayCallback {
  public:
      MultiDisplayCallback(MultiDisplayObserver *observer);
      virtual ~MultiDisplayCallback();
  
      status_t blankSecondaryDisplay(bool blank);
      status_t updateVideoState(int sessionId, MDS_VIDEO_STATE state);
      status_t setHdmiTiming(const MDSHdmiTiming& timing);
      status_t setHdmiScalingType(MDS_SCALING_TYPE type);
      status_t setHdmiOverscan(int hValue, int vValue);
      status_t updateInputState(bool state);
  
  private:
      MultiDisplayObserver *mDispObserver;
      MDS_VIDEO_STATE mVideoState;
  };
  
  class MultiDisplayObserver {
  public:
      MultiDisplayObserver();
      virtual ~MultiDisplayObserver();
  
  public:
      bool initialize();
      void deinitialize();
      status_t notifyHotPlug(bool connected);
      status_t getVideoSourceInfo(int sessionID, VideoSourceInfo* info);
      int  getVideoSessionNumber();
      bool isExternalDeviceTimingFixed() const;
      status_t notifyWidiConnectionStatus(bool connected);
      status_t setDecoderOutputResolution(int sessionID,
              int32_t width, int32_t height,
              int32_t offX,  int32_t offY,
              int32_t bufWidth, int32_t bufHeight);
  
  private:
      bool isMDSRunning();
      bool initMDSClient();
      bool initMDSClientAsync();
      void deinitMDSClient();
      status_t blankSecondaryDisplay(bool blank);
      status_t updateVideoState(int sessionId, MDS_VIDEO_STATE state);
      status_t setHdmiTiming(const MDSHdmiTiming& timing);
      status_t updateInputState(bool active);
      friend class MultiDisplayCallback;
  
  private:
      enum {
          THREAD_LOOP_DELAY = 10, // 10 ms
          THREAD_LOOP_BOUND = 2000, // 20s
      };
  
  private:
      sp<IMultiDisplayCallbackRegistrar> mMDSCbRegistrar;
      sp<IMultiDisplayInfoProvider> mMDSInfoProvider;
      sp<IMultiDisplayConnectionObserver> mMDSConnObserver;
      sp<IMultiDisplayDecoderConfig> mMDSDecoderConfig;
      sp<MultiDisplayCallback> mMDSCallback;
      mutable Mutex mLock;
      Condition mCondition;
      int mThreadLoopCount;
      bool mDeviceConnected;
      // indicate external devices's timing is set
      bool mExternalHdmiTiming;
      bool mInitialized;
  
  private:
      DECLARE_THREAD(MDSClientInitThread, MultiDisplayObserver);
  };
  
  #else
  
  // dummy declaration and implementation of MultiDisplayObserver
  class MultiDisplayObserver {
  public:
      MultiDisplayObserver() {}
      virtual ~MultiDisplayObserver() {}
  
      bool initialize() { return true; }
      void deinitialize() {}
      status_t notifyHotPlug(bool connected) { return NO_ERROR; }
      status_t getVideoSourceInfo(int sessionID, VideoSourceInfo* info) { return INVALID_OPERATION; }
      int  getVideoSessionNumber() { return 0; }
      bool isExternalDeviceTimingFixed() const { return false; }
      status_t notifyWidiConnectionStatus(bool connected) { return NO_ERROR; }
      status_t setDecoderOutputResolution(
              int sessionID,
              int32_t width, int32_t height,
              int32_t, int32_t, int32_t, int32_t) { return NO_ERROR; }
  };
  
  #endif //TARGET_HAS_MULTIPLE_DISPLAY
  
  } // namespace intel
  } // namespace android
  
  #endif /* __MULTIMultiDisplayObserver_H_ */
  