/** This method starts the camera preview and recording */
 private void startPreviewAndRecording() {
   try {
     mCameraPreview.setVisibility(View.VISIBLE);
     if (mTargetHeight != -1) {
       resizeCameraPreview(mTargetHeight);
     }
     mVideoCallManager.startCameraPreview(mCameraSurface);
     mVideoCallManager.startCameraRecording();
   } catch (IOException ioe) {
     closeCamera();
     loge("Exception startPreviewAndRecording, " + ioe.toString());
   }
 }
 public boolean isCameraInitNeeded() {
   if (DBG) {
     log(
         "isCameraInitNeeded mCameraNeeded="
             + mCameraNeeded
             + " mCameraSurface= "
             + mCameraSurface
             + " camera state = "
             + mVideoCallManager.getCameraState());
   }
   return mCameraNeeded
       && mCameraSurface != null
       && mVideoCallManager.getCameraState() == CameraState.CAMERA_CLOSED;
 }
  /** This method is called when the visibility of the VideoCallPanel is changed */
  @Override
  protected void onVisibilityChanged(View changedView, int visibility) {
    if (changedView != this || mVideoCallManager == null) {
      return;
    }

    switch (visibility) {
      case View.INVISIBLE:
      case View.GONE:
        if (DBG) log("VideoCallPanel View is GONE or INVISIBLE");
        // Stop the preview and close the camera now because other
        // activities may need to use it
        if (mVideoCallManager.getCameraState() != CameraState.CAMERA_CLOSED) {
          stopRecordingAndPreview();
          closeCamera();
        }
        break;
      case View.VISIBLE:
        if (DBG) log("VideoCallPanel View is VISIBLE");
        if (isCameraInitNeeded()) {
          initializeCamera();
        }
        break;
    }
  }
 /**
  * This method gets called when the zoom control reports that the zoom value has changed. This
  * method sets the camera zoom value accordingly.
  *
  * @param index
  */
 private void onZoomValueChanged(int index) {
   mZoomValue = index;
   ImsCamera imsCamera = mVideoCallManager.getImsCameraInstance();
   // Set zoom
   if (imsCamera.isZoomSupported()) {
     imsCamera.setZoom(mZoomValue);
   }
 }
  /**
   * This method crates the camera object if camera is not disabled
   *
   * @param cameraId ID of the front or the back camera
   * @return Camera instance on success, null otherwise
   */
  private boolean openCamera(int cameraId) {
    boolean result = false;

    try {
      return mVideoCallManager.openCamera(cameraId);
    } catch (Exception e) {
      loge("Failed to open camera device, error " + e.toString());
      return result;
    }
  }
 @Override
 public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
   if (surface.equals(mCameraPreview.getSurfaceTexture())) {
     if (DBG) log("CameraPreview surface texture destroyed");
     stopRecordingAndPreview();
     closeCamera();
     mCameraSurface = null;
   } else if (surface.equals(mFarEndView.getSurfaceTexture())) {
     if (DBG) log("FarEndView surface texture destroyed");
     mFarEndSurface = null;
     mVideoCallManager.setFarEndSurface(null);
   }
   return true;
 }
 @Override
 public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
   if (surface.equals(mCameraPreview.getSurfaceTexture())) {
     if (DBG) log("Camera surface texture created");
     mCameraSurface = surface;
     if (isCameraInitNeeded()) {
       initializeCamera();
     }
   } else if (surface.equals(mFarEndView.getSurfaceTexture())) {
     if (DBG) log("Video surface texture created");
     mFarEndSurface = surface;
     mVideoCallManager.setFarEndSurface(mFarEndSurface);
   }
 }
  /**
   * This method switches the camera to front/back or off
   *
   * @param cameraId
   */
  private void switchCamera(int cameraId) {
    // Change the camera Id
    mCameraId = cameraId;

    // Stop camera preview if already running
    if (mVideoCallManager.getCameraState() != CameraState.CAMERA_CLOSED) {
      stopRecordingAndPreview();
      closeCamera();
    }

    // Restart camera if camera doesn't need to stay off
    if (isCameraInitNeeded()) {
      initializeCamera();
    }
  }
  /**
   * This method get the zoom related parameters from the camera and initialized the zoom control
   */
  private void initializeZoom() {
    ImsCamera imsCamera = mVideoCallManager.getImsCameraInstance();
    if (imsCamera == null) {
      return;
    }
    if (!imsCamera.isZoomSupported()) {
      mZoomControl.setVisibility(View.GONE); // Disable ZoomControl
      return;
    }

    mZoomControl.setVisibility(View.VISIBLE); // Enable ZoomControl
    mZoomMax = imsCamera.getMaxZoom();
    // Currently we use immediate zoom for fast zooming to get better UX and
    // there is no plan to take advantage of the smooth zoom.
    mZoomControl.setZoomMax(mZoomMax);
    mZoomControl.setZoomIndex(DEFAULT_CAMERA_ZOOM_VALUE);
    mZoomControl.setOnZoomChangeListener(new ZoomChangeListener());
  }
  @Override
  public void onClick(View v) {
    int direction = mVideoCallManager.getCameraDirection();

    // Switch the camera front/back/off
    // The state machine is as follows
    // front --> back --> stop preview --> front...
    switch (direction) {
      case CAMERA_UNKNOWN:
        switchCamera(mFrontCameraId);
        break;
      case Camera.CameraInfo.CAMERA_FACING_FRONT:
        switchCamera(mBackCameraId);
        break;
      case Camera.CameraInfo.CAMERA_FACING_BACK:
        switchCamera(CAMERA_UNKNOWN);
        break;
    }
  }
 public void setPanelElementsVisibility(int callType) {
   switch (callType) {
     case Phone.CALL_TYPE_VT:
       if (isCameraInitNeeded()) {
         initializeCamera();
       }
       break;
     case Phone.CALL_TYPE_VT_TX:
       if (isCameraInitNeeded()) {
         initializeCamera();
       }
       break;
     case Phone.CALL_TYPE_VT_RX:
       // Stop the preview and close the camera now because other
       // activities may need to use it
       if (mVideoCallManager.getCameraState() != CameraState.CAMERA_CLOSED) {
         stopRecordingAndPreview();
         closeCamera();
       }
       break;
     default:
       log("setPanelElementsVisibility: callType=" + callType);
       break;
   }
   log(
       "setPanelElementsVisibility: callType= "
           + callType
           + " VideoCallPanel is "
           + mVideoCallPanel.getVisibility()
           + " mCameraPreview is "
           + mCameraPreview.getVisibility()
           + " available="
           + mCameraPreview.isAvailable()
           + " activated= "
           + mCameraPreview.isActivated()
           + " mFarEndView is "
           + mFarEndView.getVisibility()
           + " available="
           + mFarEndView.isAvailable()
           + " activated= "
           + mFarEndView.isActivated());
 }
  /** Finalize view from inflation. */
  @Override
  protected void onFinishInflate() {
    super.onFinishInflate();

    if (DBG) log("onFinishInflate(this = " + this + ")...");

    // Check the Media loopback property
    int property = SystemProperties.getInt("net.lte.VT_LOOPBACK_ENABLE", 0);
    mIsMediaLoopback = (property == 1) ? true : false;
    if (DBG) log("Is Media running in loopback mode: " + mIsMediaLoopback);

    // Get UI widgets
    mVideoCallPanel = (ViewGroup) findViewById(R.id.videoCallPanel);
    mZoomControl = (ZoomControlBar) findViewById(R.id.zoom_control);
    mFarEndView = (TextureView) findViewById(R.id.video_view);
    mCameraPreview = (TextureView) findViewById(R.id.camera_view);
    mCameraPicker = (ImageView) findViewById(R.id.camera_picker);

    // Set listeners
    mCameraPreview.setSurfaceTextureListener(this);
    mFarEndView.setSurfaceTextureListener(this);
    mCameraPicker.setOnClickListener(this);

    // Get the camera IDs for front and back cameras
    mVideoCallManager = VideoCallManager.getInstance(mContext);
    mBackCameraId = mVideoCallManager.getBackCameraId();
    mFrontCameraId = mVideoCallManager.getFrontCameraId();
    chooseCamera(true);

    // Check if camera supports dual cameras
    mNumberOfCameras = mVideoCallManager.getNumberOfCameras();
    if (mNumberOfCameras > 1) {
      mCameraPicker.setVisibility(View.VISIBLE);
    } else {
      mCameraPicker.setVisibility(View.GONE);
    }

    // Set media event listener
    mVideoCallManager.setOnParamReadyListener(new ParamReadyListener());
    mVideoCallManager.setCvoEventListener(new CvoListener());
  }
 /** Initialize camera parameters based on negotiated height, width */
 private void initializeCameraParams() {
   try {
     // Get the parameter to make sure we have the up-to-date value.
     ImsCamera imsCamera = mVideoCallManager.getImsCameraInstance();
     // Set the camera preview size
     if (mIsMediaLoopback) {
       // In loopback mode the IMS is hard coded to render the
       // camera frames of only the size 176x144 on the far end surface
       imsCamera.setPreviewSize(LOOPBACK_MODE_WIDTH, LOOPBACK_MODE_HEIGHT);
     } else {
       log(
           "Set Preview Size directly with negotiated Height = "
               + mVideoCallManager.getNegotiatedHeight()
               + " negotiated width= "
               + mVideoCallManager.getNegotiatedWidth());
       imsCamera.setPreviewSize(
           mVideoCallManager.getNegotiatedWidth(), mVideoCallManager.getNegotiatedHeight());
       imsCamera.setPreviewFpsRange(mVideoCallManager.getNegotiatedFps());
     }
   } catch (RuntimeException e) {
     loge("Error setting Camera preview size/fps exception=" + e);
   }
 }
 public void startOrientationListener(boolean start) {
   mVideoCallManager.startOrientationListener(start);
 }
 /** This method stops the camera recording and preview */
 private void stopRecordingAndPreview() {
   mCameraPreview.setVisibility(View.INVISIBLE);
   mVideoCallManager.stopCameraRecording();
   mVideoCallManager.stopCameraPreview();
 }
 /** This method disconnect and releases the camera */
 private void closeCamera() {
   mVideoCallManager.closeCamera();
 }