Extended camera preview to switch between multiple available device cameras

Change-Id: I8e97d6182bf02cba29ae3bc9f1a7ef21a277117e
diff --git a/samples/ApiDemos/res/menu/camera_menu.xml b/samples/ApiDemos/res/menu/camera_menu.xml
new file mode 100644
index 0000000..16504b7
--- /dev/null
+++ b/samples/ApiDemos/res/menu/camera_menu.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/switch_cam"
+          android:title="@string/switch_cam" />
+</menu>
diff --git a/samples/ApiDemos/res/values/strings.xml b/samples/ApiDemos/res/values/strings.xml
index 4e61b8f..7adf48d 100644
--- a/samples/ApiDemos/res/values/strings.xml
+++ b/samples/ApiDemos/res/values/strings.xml
@@ -498,6 +498,8 @@
     <string name="hide_me">Hide Me!</string>
 
     <string name="density_title">Density: Unknown Screen</string>
+    <string name="camera_alert">Device has only one camera!</string>
+    <string name="switch_cam">Switch Camera</string>
 
     <!-- ============================ -->
     <!--  media examples strings  -->
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java b/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java
index 22dc297..73d50cb 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java
@@ -17,11 +17,16 @@
 package com.example.android.apis.graphics;
 
 import android.app.Activity;
+import android.app.AlertDialog;
 import android.content.Context;
 import android.hardware.Camera;
+import android.hardware.Camera.CameraInfo;
 import android.hardware.Camera.Size;
 import android.os.Bundle;
 import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 import android.view.View;
@@ -32,11 +37,20 @@
 import java.io.IOException;
 import java.util.List;
 
+// Need the following import to get access to the app resources, since this
+// class is in a sub-package.
+import com.example.android.apis.R;
+
 // ----------------------------------------------------------------------
 
 public class CameraPreview extends Activity {
     private Preview mPreview;
     Camera mCamera;
+    int numberOfCameras;
+    int cameraCurrentlyLocked;
+
+    // The first rear facing camera
+    int defaultCameraId;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -50,13 +64,27 @@
         // and set it as the content of our activity.
         mPreview = new Preview(this);
         setContentView(mPreview);
+
+        // Find the total number of cameras available
+        numberOfCameras = Camera.getNumberOfCameras();
+
+        // Find the ID of the default camera
+        CameraInfo cameraInfo = new CameraInfo();
+            for (int i = 0; i < numberOfCameras; i++) {
+                Camera.getCameraInfo(i, cameraInfo);
+                if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
+                    defaultCameraId = i;
+                }
+            }
     }
 
     @Override
     protected void onResume() {
         super.onResume();
 
+        // Open the default i.e. the first rear facing camera.
         mCamera = Camera.open();
+        cameraCurrentlyLocked = defaultCameraId;
         mPreview.setCamera(mCamera);
     }
 
@@ -72,6 +100,55 @@
             mCamera = null;
         }
     }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+
+        // Inflate our menu which can gather user input for switching camera
+        MenuInflater inflater = getMenuInflater();
+        inflater.inflate(R.menu.camera_menu, menu);
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        // Handle item selection
+        switch (item.getItemId()) {
+        case R.id.switch_cam:
+            // check for availability of multiple cameras
+            if (numberOfCameras == 1) {
+                AlertDialog.Builder builder = new AlertDialog.Builder(this);
+                builder.setMessage(this.getString(R.string.camera_alert))
+                       .setNeutralButton("Close", null);
+                AlertDialog alert = builder.create();
+                alert.show();
+                return true;
+            }
+
+            // OK, we have multiple cameras.
+            // Release this camera -> cameraCurrentlyLocked
+            if (mCamera != null) {
+                mCamera.stopPreview();
+                mPreview.setCamera(null);
+                mCamera.release();
+                mCamera = null;
+            }
+
+            // Acquire the next camera and request Preview to reconfigure
+            // parameters.
+            mCamera = Camera
+                    .open((cameraCurrentlyLocked + 1) % numberOfCameras);
+            cameraCurrentlyLocked = (cameraCurrentlyLocked + 1)
+                    % numberOfCameras;
+            mPreview.switchCamera(mCamera);
+
+            // Start the preview
+            mCamera.startPreview();
+            return true;
+        default:
+            return super.onOptionsItemSelected(item);
+        }
+    }
 }
 
 // ----------------------------------------------------------------------
@@ -111,6 +188,20 @@
         }
     }
 
+    public void switchCamera(Camera camera) {
+       setCamera(camera);
+       try {
+           camera.setPreviewDisplay(mHolder);
+       } catch (IOException exception) {
+           Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
+       }
+       Camera.Parameters parameters = camera.getParameters();
+       parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
+       requestLayout();
+
+       camera.setParameters(parameters);
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         // We purposely disregard child measurements because act as a