title: Rotating the Camera Activity 180 degrees when in landscape causes inverted camera preview
body: <h1>EDIT</h1>
  <p>Also an issue when rotating from upside down portrait to one of the landscape orientations and back from there to the upside down portrait orientation.I have tested these cases on the default Camera application and it does not seem to have any of these problems.</p>
  <h1>END EDIT</h1>
  <p>I have a custom camera which when rotated by 180 degrees say from one landscape to another shows an inverted preview.I have used an OrientationEventListener in my code like this.
  <code>mCamera.setDisplayOrientation</code> is called in <code>setDisplayOrientation</code>,I am rounding the orientation to 0,90,180,270 using <code>roundOrientation(orientation,orientationHistory)</code> and I get the natural display rotation using <code>getDisplayRotation</code>.I instantiate the listener in <code>initializeFirstTime</code> and enable it <code>initializeFirstTime</code> and if resuming from a paused state from <code>initializeSecondTime</code>.I disable the listener in <code>onPause</code>.I call <code>initializeFirstTime</code> or <code>initializeSecondTime</code> in <code>onResume</code>.
  :</p>
  <pre><code>    class MyOrientationEventListener extends OrientationEventListener
  {
      
      @Override
      public void onOrientationChanged(int orientation)
      {
          if(orientation==ORIENTATION_UNKNOWN)
              return;
          mOrientation=roundOrientation(orientation,0);
          int orientationCompensation=getDisplayRotation(CameraActivity.this);
          if(mOrientationCompensation!=orientationCompensation)
              mOrientationCompensation=orientationCompensation;
      }
  
      public MyOrientationEventListener(Context context) {
          super(context);
      }
      
      private int roundOrientation(int orientation, int orientationHistory) {
          boolean changeOrientation = false;
          final int ORIENTATION_HYSTERESIS=5;//a tolerance value above the limit
          if (orientationHistory == OrientationEventListener.ORIENTATION_UNKNOWN) {
              changeOrientation = true;
          } else {
              int dist = Math.abs(orientation - orientationHistory);
              dist = Math.min(dist, 360 - dist);
              changeOrientation = (dist &gt;= 45 +ORIENTATION_HYSTERESIS );
          }
          if (changeOrientation) {
                  return ((orientation + 45) / 90 * 90) % 360;
          }
          return orientationHistory;
      }   
  }
  
  private void setDisplayOrientation()
  {
      mDisplayRotation=getDisplayRotation(this);
      mDisplayOrientation=getDisplayOrientation(mDisplayRotation, CameraInfo.CAMERA_FACING_BACK);
      mCamera.setDisplayOrientation(mDisplayOrientation);
  }
  
  private int getDisplayOrientation(int degrees, int cameraId) {
      // See android.hardware.Camera.setDisplayOrientation for
      // documentation.
      Camera.CameraInfo info = new Camera.CameraInfo();
      Camera.getCameraInfo(cameraId, info);
      int result;
      if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
          result = (info.orientation + degrees) % 360;
          result = (360 - result) % 360;  // compensate the mirror
      } else {  // back-facing
          result = (info.orientation - degrees + 360) % 360;
      }
      return result;
  }
  
   private int getDisplayRotation(Activity activity) {
          int rotation = activity.getWindowManager().getDefaultDisplay()
                  .getRotation();
          switch (rotation) {
              case Surface.ROTATION_0: return 0;
              case Surface.ROTATION_90: return 90;
              case Surface.ROTATION_180: return 180;
              case Surface.ROTATION_270: return 270;
          }
          return 0;
      } 
  
  private MyOrientationEventListener mOrientationListener;
  private int mOrientation=OrientationEventListener.ORIENTATION_UNKNOWN;
  private int mOrientationCompensation=0;
  private int mDisplayRotation;
  private int mDisplayOrientation;
  </code></pre>
  <p>These two methods are used to activate the OrientationEventListener:</p>
  <pre><code>private void initializeFirstTime()
  {
      //checking if previously initialized and setting camera parameters
      mOrientationListener=new MyOrientationEventListener(CameraActivity.this);
      mOrientationListener.enable();
      mFirstTimeInitialized=true;
  }
  
  private void initializeSecondTime()
  {
      mOrientationListener.enable();
  }
  </code></pre>
  <p>The Camera Preview is started,stopeed and restarted like this:</p>
  <pre><code>  private void startPreview() throws CameraHardwareException
  {
      //check if called before onPause or after onResume,
      //open the Camera if null,stop the preview,set the parameters
      setDisplayOrientation();
      try
      {
          Log.d(TAG, &quot;Trying to start the preview&quot;);
          mCamera.startPreview();
      }
      catch(Throwable ex)
      {
          closeCamera();
          throw new RuntimeException(&quot;Could not start camera preview&quot;);
      }
      mPreviewing=true;
  }
  </code></pre>
  <p>The Activity lifecycle methods have been implemented like this:</p>
  <pre><code>@Override
  public void onResume()
  {
      super.onResume();
      mPausing=false;
      //check condition for SurfaceHolder
      //probsbly happens if camera has paused and is resuming
      if(mStatus==PREVIEW_STOPPED)
      {
          try {
              startPreview();
          } catch (CameraHardwareException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
      }
      if(surfaceHolder!=null)
      {
          if(!mFirstTimeInitialized)
              initializeFirstTime();
          else
              initializeSecondTime();
      }
      keepScreenOnAwhile();
      if(mStatus==CAMERA_IDLE)
      {
          mResumeTime=SystemClock.uptimeMillis();
          handler.sendEmptyMessageDelayed(CHECK_DISPLAY_ROTATION, 100);
      }
  }
  
  @Override
  public void onPause()
  {
      mPausing=true;
      stopPreview();
      closeCamera();
      resetScreenOn();
      if(mFirstTimeInitialized)
          mOrientationListener.disable();
      handler.removeMessages(FIRST_TIME_INIT);
      handler.removeMessages(CLEAR_SCREEN_DELAY);
      super.onPause();
  }
  </code></pre>
  <p>The SurfaceHolder.Callbacks methods have been implemented here:</p>
  <pre><code>@Override
  public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
      if(holder.getSurface()==null)
      {   
          Log.d(TAG, &quot;holder.getSurface()=null&quot;);
          return;
      }
      //stash the holder here for later use,useful if onResume needs to be invoked after this.
      surfaceHolder=holder;
      if(mCamera==null)
          return;
      //sometimes surfaceChanged is called after onPause or before onResume,ignore it
      if(mPausing || isFinishing())
          return;
      if(mStatus==PREVIEW_STOPPED)
          try {
              startPreview();
          } catch (CameraHardwareException e1) {
              Log.e(TAG, &quot;Error starting the preview&quot;);
          }
      if(!mPreviewing)
          try {
              startPreview();
          } catch (CameraHardwareException e) {
              Log.e(TAG,&quot;Could not get the camera&quot;);
          }
      
      if(!mFirstTimeInitialized)
          if(getDisplayRotation(this)!=mDisplayOrientation)
              setDisplayOrientation();
      if(mPreviewing &amp;&amp; holder.isCreating())
      {
          setPreviewDisplay(holder);
      }
      if(!mFirstTimeInitialized)
          handler.sendEmptyMessage(FIRST_TIME_INIT);
      else
          initializeSecondTime();
  }
  
  @Override
  public void surfaceCreated(SurfaceHolder holder) {
      //nothing here
  }
  
  @Override
  public void surfaceDestroyed(SurfaceHolder holder) {
      // TODO Auto-generated method stub
      stopPreview();
      surfaceHolder=null;
  }
  </code></pre>
  <p>The orientation event listener is enabled in onResume and surfaceChanged whichever gets called fastest I guess and is then disabled in onPause.The OrientationEventListener is only instantiated in initializeFirstTime.</p>
  <h1>EDIT:</h1>
  <p>Is this happening because I did not enable the <code>OrientationEventListener</code> correctly.Also did I set the rotation for parameters which affects image rotation correctly:</p>
  <pre><code>  mParameters.setRotation(rotation);
  </code></pre>