Initial commit of new camera API, mostly just the interface.

- New core API classes in android.hardware.photography
- android.media.Image and android.media.ImageReader classes for
  application access to direct hardware image buffers.
- Additions to android.graphics.ImageFormat to describe new image
  types needed by new camera API.
- Some documentation included; very little implementation.

Bug: 9111736
Change-Id: I0680f35944d1cb8845b7dc0c67edc8c0f0864573
diff --git a/api/current.txt b/api/current.txt
index 87891b51..3337837 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5735,6 +5735,7 @@
     field public static final int BIND_NOT_FOREGROUND = 4; // 0x4
     field public static final int BIND_WAIVE_PRIORITY = 32; // 0x20
     field public static final java.lang.String BLUETOOTH_SERVICE = "bluetooth";
+    field public static final java.lang.String CAMERA_SERVICE = "camera";
     field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
     field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
     field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2
@@ -9002,8 +9003,10 @@
     field public static final int JPEG = 256; // 0x100
     field public static final int NV16 = 16; // 0x10
     field public static final int NV21 = 17; // 0x11
+    field public static final int RAW_SENSOR = 513; // 0x201
     field public static final int RGB_565 = 4; // 0x4
     field public static final int UNKNOWN = 0; // 0x0
+    field public static final int YUV_420_888 = 35; // 0x23
     field public static final int YUY2 = 20; // 0x14
     field public static final int YV12 = 842094169; // 0x32315659
   }
@@ -10626,6 +10629,133 @@
 
 }
 
+package android.hardware.photography {
+
+  public class CameraAccessException extends java.lang.Exception {
+    ctor public CameraAccessException(int);
+    ctor public CameraAccessException(int, java.lang.String);
+    ctor public CameraAccessException(int, java.lang.String, java.lang.Throwable);
+    ctor public CameraAccessException(int, java.lang.Throwable);
+    method public final int getReason();
+    field public static final int CAMERA_DISABLED = 3; // 0x3
+    field public static final int CAMERA_DISCONNECTED = 4; // 0x4
+    field public static final int CAMERA_IN_USE = 1; // 0x1
+    field public static final int MAX_CAMERAS_IN_USE = 2; // 0x2
+  }
+
+  public final class CameraDevice implements java.lang.AutoCloseable {
+    ctor public CameraDevice();
+    method public void capture(android.hardware.photography.CaptureRequest, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
+    method public void captureBurst(java.util.List<android.hardware.photography.CaptureRequest>, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
+    method public void close();
+    method public void configureOutputs(java.util.List<android.view.Surface>);
+    method public android.hardware.photography.CaptureRequest createCaptureRequest(int) throws android.hardware.photography.CameraAccessException;
+    method public android.hardware.photography.CameraProperties getProperties() throws android.hardware.photography.CameraAccessException;
+    method public void setErrorListener(android.hardware.photography.CameraDevice.ErrorListener);
+    method public void setRepeatingBurst(java.util.List<android.hardware.photography.CaptureRequest>, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
+    method public void setRepeatingRequest(android.hardware.photography.CaptureRequest, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
+    method public void stopRepeating() throws android.hardware.photography.CameraAccessException;
+    method public void waitUntilIdle() throws android.hardware.photography.CameraAccessException;
+    field public static final int TEMPLATE_MANUAL = 5; // 0x5
+    field public static final int TEMPLATE_PREVIEW = 1; // 0x1
+    field public static final int TEMPLATE_RECORD = 2; // 0x2
+    field public static final int TEMPLATE_STILL_CAPTURE = 3; // 0x3
+    field public static final int TEMPLATE_VIDEO_SNAPSHOT = 4; // 0x4
+  }
+
+  public static abstract interface CameraDevice.CaptureListener {
+    method public abstract void onCaptureComplete(android.hardware.photography.CameraDevice, android.hardware.photography.CaptureRequest, android.hardware.photography.CaptureResult);
+    method public abstract void onCaptureFailed(android.hardware.photography.CameraDevice, android.hardware.photography.CaptureRequest);
+  }
+
+  public static abstract interface CameraDevice.ErrorListener {
+    method public abstract void onCameraDeviceError(android.hardware.photography.CameraDevice, int);
+    field public static final int DEVICE_DISCONNECTED = 1; // 0x1
+    field public static final int DEVICE_ERROR = 2; // 0x2
+    field public static final int SERVICE_ERROR = 3; // 0x3
+  }
+
+  public final class CameraManager {
+    method public android.hardware.photography.CameraProperties getCameraProperties(java.lang.String) throws android.hardware.photography.CameraAccessException;
+    method public java.lang.String[] getDeviceIdList();
+    method public android.hardware.photography.CameraDevice openCamera(java.lang.String) throws android.hardware.photography.CameraAccessException;
+    method public void registerCameraListener(android.hardware.photography.CameraManager.CameraListener);
+    method public void unregisterCameraListener(android.hardware.photography.CameraManager.CameraListener);
+  }
+
+  public static abstract interface CameraManager.CameraListener {
+    method public abstract void onCameraAvailable(java.lang.String);
+    method public abstract void onCameraUnavailable(java.lang.String);
+  }
+
+  public class CameraMetadata implements android.os.Parcelable {
+    ctor public CameraMetadata();
+    method public int describeContents();
+    method public T get(android.hardware.photography.CameraMetadata.Key<T>);
+    method public void set(android.hardware.photography.CameraMetadata.Key<T>, T);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public static class CameraMetadata.Key {
+    ctor public CameraMetadata.Key(java.lang.String);
+    method public final boolean equals(java.lang.Object);
+    method public final java.lang.String getName();
+    method public final int hashCode();
+  }
+
+  public final class CameraProperties extends android.hardware.photography.CameraMetadata {
+    ctor public CameraProperties();
+    field public static final android.hardware.photography.CameraMetadata.Key INFO_IDENTIFIER;
+    field public static final android.hardware.photography.CameraMetadata.Key INFO_MODEL;
+    field public static final android.hardware.photography.CameraMetadata.Key INFO_REMOVABLE;
+    field public static final android.hardware.photography.CameraMetadata.Key INFO_SUPPORTED_HARDWARE_LEVEL;
+    field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1; // 0x1
+    field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0; // 0x0
+    field public static final android.hardware.photography.CameraMetadata.Key SCALER_AVAILABLE_FORMATS;
+    field public static final android.hardware.photography.CameraMetadata.Key SCALER_AVAILABLE_JPEG_SIZES;
+    field public static final android.hardware.photography.CameraMetadata.Key SCALER_AVAILABLE_PROCESSED_SIZES;
+    field public static final android.hardware.photography.CameraMetadata.Key SCALER_AVAILABLE_RAW_SIZES;
+    field public static final android.hardware.photography.CameraMetadata.Key SENSOR_ACTIVE_ARRAY_SIZE;
+    field public static final android.hardware.photography.CameraMetadata.Key SENSOR_PIXEL_ARRAY_SIZE;
+  }
+
+  public final class CaptureRequest extends android.hardware.photography.CameraMetadata {
+    method public void addTarget(android.view.Surface);
+    method public void removeTarget(android.view.Surface);
+    field public static final android.hardware.photography.CameraMetadata.Key SENSOR_EXPOSURE_TIME;
+    field public static final android.hardware.photography.CameraMetadata.Key SENSOR_SENSITIVITY;
+  }
+
+  public final class CaptureResult extends android.hardware.photography.CameraMetadata {
+    field public static final android.hardware.photography.CameraMetadata.Key CONTROL_AE_STATE;
+    field public static final int CONTROL_AE_STATE_CONVERGED = 2; // 0x2
+    field public static final int CONTROL_AE_STATE_FLASH_REQUIRED = 4; // 0x4
+    field public static final int CONTROL_AE_STATE_INACTIVE = 0; // 0x0
+    field public static final int CONTROL_AE_STATE_LOCKED = 3; // 0x3
+    field public static final int CONTROL_AE_STATE_PRECAPTURE = 5; // 0x5
+    field public static final int CONTROL_AE_STATE_SEARCHING = 1; // 0x1
+    field public static final android.hardware.photography.CameraMetadata.Key SENSOR_TIMESTAMP;
+    field public static final android.hardware.photography.CameraMetadata.Key STATISTICS_DETECTED_FACES;
+  }
+
+  public static class CaptureResult.Face {
+    ctor public CaptureResult.Face();
+    method public android.graphics.Rect getBounds();
+    method public int getId();
+    method public android.graphics.Point getLeftEye();
+    method public android.graphics.Point getMouth();
+    method public android.graphics.Point getRightEye();
+    method public int getScore();
+  }
+
+  public final class Size {
+    method public final int getHeight();
+    method public final int getWidth();
+  }
+
+}
+
 package android.hardware.usb {
 
   public class UsbAccessory implements android.os.Parcelable {
@@ -11662,6 +11792,40 @@
     field public static final int EULER_Z = 2; // 0x2
   }
 
+  public abstract class Image implements java.lang.AutoCloseable {
+    ctor public Image();
+    method public abstract void close();
+    method protected final void finalize();
+    method public int getFormat();
+    method public int getHeight();
+    method public android.media.Image.Plane[] getPlanes();
+    method public long getTimestamp();
+    method public int getWidth();
+  }
+
+  public static final class Image.Plane {
+    ctor public Image.Plane();
+    method public java.nio.ByteBuffer getBuffer();
+    method public int getPixelStride();
+    method public int getRowStride();
+  }
+
+  public final class ImageReader {
+    ctor public ImageReader(int, int, int, int);
+    method public int getHeight();
+    method public int getImageFormat();
+    method public int getMaxImages();
+    method public android.media.Image getNextImage();
+    method public android.view.Surface getSurface();
+    method public int getWidth();
+    method public void releaseImage(android.media.Image);
+    method public void setOnImageAvailableListener(android.media.ImageReader.OnImageAvailableListener);
+  }
+
+  public static abstract interface ImageReader.OnImageAvailableListener {
+    method public abstract void onImageAvailable(android.media.ImageReader);
+  }
+
   public class JetPlayer {
     method public boolean clearQueue();
     method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 459139f..7968431 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -49,6 +49,7 @@
 import android.hardware.ISerialManager;
 import android.hardware.SerialManager;
 import android.hardware.SystemSensorManager;
+import android.hardware.photography.CameraManager;
 import android.hardware.display.DisplayManager;
 import android.hardware.input.InputManager;
 import android.hardware.usb.IUsbManager;
@@ -540,6 +541,11 @@
                 IAppOpsService service = IAppOpsService.Stub.asInterface(b);
                 return new AppOpsManager(ctx, service);
             }});
+
+        registerService(CAMERA_SERVICE, new StaticServiceFetcher() {
+            public Object createStaticService() {
+                return new CameraManager();
+            }});
     }
 
     static ContextImpl getImpl(Context context) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 81d6f0b..35e51a6 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2284,6 +2284,16 @@
     public static final String APP_OPS_SERVICE = "appops";
 
     /**
+     * Use with {@link #getSystemService} to retrieve a
+     * {@link android.hardware.photography.CameraManager} for interacting with
+     * camera devices.
+     *
+     * @see #getSystemService
+     * @see android.hardware.camera.CameraManager
+     */
+    public static final String CAMERA_SERVICE = "camera";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/hardware/photography/CameraAccessException.java b/core/java/android/hardware/photography/CameraAccessException.java
new file mode 100644
index 0000000..01114df
--- /dev/null
+++ b/core/java/android/hardware/photography/CameraAccessException.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+package android.hardware.photography;
+
+/**
+ * <p><code>CameraAccessException</code> is thrown if a camera device could not
+ * be queried or opened by the {@link CameraManager}, or if the connection to an
+ * opened {@link CameraDevice} is no longer valid.</p>
+ *
+ * @see CameraManager
+ * @see CameraDevice
+ */
+public class CameraAccessException extends Exception {
+    /**
+     * The camera device is in use already
+     */
+    public static final int CAMERA_IN_USE = 1;
+
+    /**
+     * The system-wide limit for number of open cameras has been reached,
+     * and more camera devices cannot be opened until previous instances are
+     * closed.
+     */
+    public static final int MAX_CAMERAS_IN_USE = 2;
+
+    /**
+     * The camera is disabled due to a device policy, and cannot be opened.
+     *
+     * @see android.app.admin.DevicePolicyManager#setCameraDisabled(android.content.ComponentName, boolean)
+     */
+    public static final int CAMERA_DISABLED = 3;
+
+    /**
+     * The camera device is removable and has been disconnected from the Android
+     * device, or the camera service has shut down the connection due to a
+     * higher-priority access request for the camera device.
+     */
+    public static final int CAMERA_DISCONNECTED = 4;
+
+    private int mReason;
+
+    /**
+     * The reason for the failure to access the camera.
+     *
+     * @see #CAMERA_IN_USE
+     * @see #MAX_CAMERAS_IN_USE
+     * @see #CAMERA_DISABLED
+     * @see #CAMERA_DISCONNECTED
+     */
+    public final int getReason() {
+        return mReason;
+    }
+
+    public CameraAccessException(int problem) {
+        mReason = problem;
+    }
+
+    public CameraAccessException(int problem, String message) {
+        super(message);
+        mReason = problem;
+    }
+
+    public CameraAccessException(int problem, String message, Throwable cause) {
+        super(message, cause);
+        mReason = problem;
+    }
+
+    public CameraAccessException(int problem, Throwable cause) {
+        super(cause);
+        mReason = problem;
+    }
+}
diff --git a/core/java/android/hardware/photography/CameraDevice.java b/core/java/android/hardware/photography/CameraDevice.java
new file mode 100644
index 0000000..2062db2
--- /dev/null
+++ b/core/java/android/hardware/photography/CameraDevice.java
@@ -0,0 +1,555 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+package android.hardware.photography;
+
+import android.graphics.ImageFormat;
+import android.renderscript.Allocation;
+import android.renderscript.RenderScript;
+import android.view.Surface;
+
+import java.lang.AutoCloseable;
+import java.util.List;
+
+/**
+ * <p>The CameraDevice class is an interface to a single camera connected to an
+ * Android device, allowing for fine-grain control of image capture and
+ * post-processing at high frame rates.</p>
+ *
+ * <p>Your application must declare the
+ * {@link android.Manifest.permission#CAMERA Camera} permission in its manifest
+ * in order to access camera devices.</p>
+ *
+ * <p>A given camera device may provide support at one of two levels: limited or
+ * full. If a device only supports the limited level, then Camera2 exposes a
+ * feature set that is roughly equivalent to the older
+ * {@link android.hardware.Camera Camera} API, although with a cleaner and more
+ * efficient interface.  Devices that implement the full level of support
+ * provide substantially improved capabilities over the older camera
+ * API. Applications that target the limited level devices will run unchanged on
+ * the full-level devices; if your application requires a full-level device for
+ * proper operation, declare the "android.hardware.camera2.full" feature in your
+ * manifest.</p>
+ *
+ * @see CameraManager#openCamera
+ * @see android.Manifest.permission#CAMERA
+ */
+public final class CameraDevice implements AutoCloseable {
+
+    /**
+     * Create a request suitable for a camera preview window. Specifically, this
+     * means that high frame rate is given priority over the highest-quality
+     * post-processing. These requests would normally be used with the
+     * {@link #setRepeatingRequest} method.
+     *
+     * @see #createCaptureRequest
+     */
+    public static final int TEMPLATE_PREVIEW = 1;
+
+    /**
+     * Create a request suitable for video recording. Specifically, this means
+     * that a stable frame rate is used, and post-processing is set for
+     * recording quality. These requests would commonly be used with the
+     * {@link #setRepeatingRequest} method.
+     *
+     * @see #createCaptureRequest
+     */
+    public static final int TEMPLATE_RECORD  = 2;
+
+    /**
+     * Create a request suitable for still image capture. Specifically, this
+     * means prioritizing image quality over frame rate. These requests would
+     * commonly be used with the {@link #capture} method.
+     *
+     * @see #createCaptureRequest
+     */
+    public static final int TEMPLATE_STILL_CAPTURE = 3;
+
+    /**
+     * Create a request suitable for still image capture while recording
+     * video. Specifically, this means maximizing image quality without
+     * disrupting the ongoing recording. These requests would commonly be used
+     * with the {@link #capture} method while a request based on
+     * {@link #TEMPLATE_RECORD} is is in use with {@link #setRepeatingRequest}.
+     *
+     * @see #createCaptureRequest
+     */
+    public static final int TEMPLATE_VIDEO_SNAPSHOT = 4;
+
+    /**
+     * A basic template for direct application control of capture
+     * parameters. All automatic control is disabled (auto-exposure, auto-white
+     * balance, auto-focus), and post-processing parameters are set to preview
+     * quality. The manual capture parameters (exposure, sensitivity, and so on)
+     * are set to reasonable defaults, but should be overriden by the
+     * application depending on the intended use case.
+     *
+     * @see #createCaptureRequest
+     */
+    public static final int TEMPLATE_MANUAL = 5;
+
+    /**
+     * Get the static properties for this camera. These are identical to the
+     * properties returned by {@link CameraManager#getCameraProperties}.
+     *
+     * @return the static properties of the camera.
+     *
+     * @throws CameraAccessException if the camera device is no longer connected
+     *
+     * @see CameraManager#getCameraProperties
+     */
+    public CameraProperties getProperties() throws CameraAccessException {
+        return null;
+    }
+
+    /**
+     * <p>Set up a new output set of Surfaces for the camera device.</p>
+     *
+     * <p>The configuration determines the set of potential output Surfaces for
+     * the camera device for each capture request. A given request may use all
+     * or a only some of the outputs. This method must be called before requests
+     * can be submitted to the camera with {@link #capture capture},
+     * {@link #captureBurst captureBurst},
+     * {@link #setRepeatingRequest setRepeatingRequest}, or
+     * {@link #setRepeatingBurst setRepeatingBurst}.</p>
+     *
+     * <p>Surfaces suitable for inclusion as a camera output can be created for
+     * various use cases and targets:</p>
+     *
+     * <ul>
+     *
+     * <li>For drawing to a {@link android.view.SurfaceView SurfaceView}: Set
+     *   the size of the Surface with
+     *   {@link android.view.SurfaceHolder#setFixedSize} to be one of the
+     *   supported
+     *   {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes}
+     *   before calling {@link android.view.SurfaceHolder#getSurface}.</li>
+     *
+     * <li>For accessing through an OpenGL texture via a
+     *   {@link android.graphics.SurfaceTexture SurfaceTexture}: Set the size of
+     *   the SurfaceTexture with
+     *   {@link android.graphics.SurfaceTexture#setDefaultBufferSize} to be one
+     *   of the supported
+     *   {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes}
+     *   before creating a Surface from the SurfaceTexture with
+     *   {@link Surface#Surface}.</li>
+     *
+     * <li>For recording with {@link android.media.MediaCodec}: Call
+     *   {@link android.media.MediaCodec#createInputSurface} after configuring
+     *   the media codec to use one of the
+     *   {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes}
+     *   </li>
+     *
+     * <li>For recording with {@link android.media.MediaRecorder}: TODO</li>
+     *
+     * <li>For efficient YUV processing with {@link android.renderscript}:
+     *   Create a RenderScript
+     *   {@link android.renderscript.Allocation Allocation} with a supported YUV
+     *   type, the IO_INPUT flag, and one of the supported
+     *   {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes}. Then
+     *   obtain the Surface with
+     *   {@link android.renderscript.Allocation#getSurface}.</li>
+     *
+     * <li>For access to uncompressed, JPEG, or raw sensor data in the
+     *   application: Create a {@link android.media.ImageReader} object with the
+     *   desired {@link CameraProperties#SCALER_AVAILABLE_FORMATS image format},
+     *   and a size from the matching
+     *   {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed},
+     *   {@link CameraProperties#SCALER_AVAILABLE_JPEG_SIZES jpeg}, or
+     *   {@link CameraProperties#SCALER_AVAILABLE_RAW_SIZES raw} sizes. Then
+     *   obtain a Surface from it.</li>
+     *
+     * </ul>
+     *
+     * </p>
+     *
+     * <p>This function can take several hundred milliseconds to execute, since
+     * camera hardware may need to be powered on or reconfigured.</p>
+     *
+     * <p>To change the configuration after requests have been submitted to the
+     * device, the camera device must be idle. To idle the device, stop any
+     * repeating requests with {@link #stopRepeating stopRepeating}, and then
+     * call {@link #waitUntilIdle waitUntilIdle}.</p>
+     *
+     * <p>Using larger resolution outputs, or more outputs, can result in slower
+     * output rate from the device.</p>
+     *
+     * @param outputs the new set of Surfaces that should be made available as
+     * targets for captured image data.
+     *
+     * @throws IllegalArgumentException if the set of output Surfaces do not
+     * meet the requirements
+     * @throws CameraAccessException if the camera device is no longer connected
+     * @throws IllegalStateException if the camera device is not idle, or has
+     * encountered a fatal error
+     */
+    public void configureOutputs(List<Surface> outputs) {
+    }
+
+    /**
+     * <p>Create a {@link CaptureRequest} initialized with template for a target
+     * use case. The settings are chosen to be the best options for the specific
+     * camera device, so it is not recommended to reuse the same request for a
+     * different camera device; create a request for that device and override
+     * the settings as desired, instead.</p>
+     *
+     * @param templateType An enumeration selecting the use case for this
+     * request; one of the CameraDevice.TEMPLATE_ values.
+     * @return a filled-in CaptureRequest, except for output streams.
+     *
+     * @throws IllegalArgumentException if the templateType is not in the list
+     * of supported templates.
+     * @throws CameraAccessException if the camera device is no longer connected
+     * @throws IllegalStateException if the camera device has been closed or the
+     * device has encountered a fatal error.
+     *
+     * @see #TEMPLATE_PREVIEW
+     * @see #TEMPLATE_RECORD
+     * @see #TEMPLATE_STILL_CAPTURE
+     * @see #TEMPLATE_VIDEO_SNAPSHOT
+     * @see #TEMPLATE_MANUAL
+     */
+    public CaptureRequest createCaptureRequest(int templateType)
+            throws CameraAccessException {
+        return null;
+    }
+
+    /**
+     * <p>Submit a request for an image to be captured by this CameraDevice.</p>
+     *
+     * <p>The request defines all the parameters for capturing the single image,
+     * including sensor, lens, flash, and post-processing settings.</p>
+     *
+     * <p>Each request will produce one {@link CaptureResult} and produce new
+     * frames for one or more target Surfaces, as defined by the request's .</p>
+     *
+     * <p>Multiple requests can be in progress at once. They are processed in
+     * first-in, first-out order, with minimal delays between each
+     * capture. Requests submitted through this method have higher priority than
+     * those submitted through {@link #setRepeatingRequest} or
+     * {@link #setRepeatingBurst}, and will be processed as soon as the current
+     * repeat/repeatBurst processing completes.</p>
+     *
+     * @param request the settings for this capture.
+     * @param listener the callback object to notify once this request has been
+     * processed. If null, no metadata will be produced for this capture,
+     * although image data will still be produced.
+     *
+     * @throws CameraAccessException if the camera device is no longer connected
+     * @throws IllegalStateException if the camera device has been closed or the
+     * device has encountered a fatal error.
+     *
+     * @see #captureBurst
+     * @see #setRepeatingRequest
+     * @see #setRepeatingBurst
+     */
+    public void capture(CaptureRequest request, CaptureListener listener)
+            throws CameraAccessException {
+    }
+
+    /**
+     * <p>Submit a list of requests to be captured in sequence as a burst. The
+     * burst will be captured in the minimum amount of time possible, and will
+     * not be interleaved with requests submitted by other capture or repeat
+     * calls.</p>
+     *
+     * <p>The requests will be captured in order, each capture producing one
+     * {@link CaptureResult} and frames for one or more
+     * target {@link android.view.Surface surfaces}.</p>
+     *
+     * <p>The main difference between this method and simply calling
+     * {@link #capture} repeatedly is that this method guarantees that no
+     * other requests will be interspersed with the burst.</p>
+     *
+     * @param requests the list of settings for this burst capture.
+     * @param listener the callback object to notify each time one of the
+     * requests in the burst has been processed. If null, no metadata will be
+     * produced for any requests in this burst, although image data will still
+     * be produced.
+     *
+     * @throws CameraAccessException if the camera device is no longer connected
+     * @throws IllegalStateException if the camera device has been closed or the
+     * device has encountered a fatal error.
+     *
+     * @see #capture
+     * @see #setRepeatingRequest
+     * @see #setRepeatingBurst
+     */
+    public void captureBurst(List<CaptureRequest> requests,
+            CaptureListener listener) throws CameraAccessException {
+    }
+
+    /**
+     * <p>Request endlessly repeating capture of images by this
+     * CameraDevice.</p>
+     *
+     * <p>With this method, the CameraDevice will continually capture
+     * images using the settings in the provided {@link
+     * CaptureRequest}, at the maximum rate possible.</p>
+     *
+     * <p>Repeat requests have lower priority than those submitted
+     * through {@link #capture} or {@link #captureBurst}, so if
+     * capture() is called when a repeating request is active, the
+     * capture request will be processed before any further repeating
+     * requests are processed.<p>
+     *
+     * <p>Repeating requests are a simple way for an application to maintain a
+     * preview or other continuous stream of frames, without having to submit
+     * requests through {@link #capture} at video rates.</p>
+     *
+     * <p>To stop the repeating capture, call {@link #stopRepeating}</p>
+     *
+     * <p>Calling repeat will replace a burst set up by {@link
+     * #setRepeatingBurst}, although any in-progress burst will be
+     * completed before the new repeat request will be used.</p>
+     *
+     * @param request the request to repeat indefinitely
+     * @param listener the callback object to notify every time the
+     * request finishes processing. If null, no metadata will be
+     * produced for this stream of requests, although image data will
+     * still be produced.
+     *
+     * @throws CameraAccessException if the camera device is no longer
+     * connected
+     * @throws IllegalStateException if the camera device has been closed or the
+     * device has encountered a fatal error.
+     *
+     * @see #capture
+     * @see #captureBurst
+     * @see #setRepeatingBurst
+     */
+    public void setRepeatingRequest(CaptureRequest request, CaptureListener listener)
+            throws CameraAccessException {
+    }
+
+    /**
+     * <p>Request endlessly repeating capture of a sequence of images by this
+     * CameraDevice.</p>
+     *
+     * <p>With this method, the CameraDevice will continually capture images,
+     * cycling through the settings in the provided list of
+     * {@link CaptureRequest CaptureRequests}, at the maximum rate possible.</p>
+     *
+     * <p>If a request is submitted through {@link #capture} or
+     * {@link #captureBurst}, the current repetition of the request list will be
+     * completed before the higher-priority request is handled. This guarantees
+     * that the application always receives a complete repeat burst captured in
+     * minimal time, instead of bursts interleaved with higher-priority
+     * captures, or incomplete captures.</p>
+     *
+     * <p>Repeating burst requests are a simple way for an application to
+     * maintain a preview or other continuous stream of frames where each
+     * request is different in a predicatable way, without having to submit
+     * requests through {@link #capture} at video rates.</p>
+     *
+     * <p>To stop the repeating capture, call {@link #stopRepeating}. Any
+     * ongoing burst will still be completed, however.</p>
+     *
+     * <p>Calling repeatBurst will replace a repeating request set up by
+     * {@link #setRepeatingRequest}, although any in-progress capture will be completed
+     * before the new repeat burst will be used.</p>
+     *
+     * @param requests the list of requests to cycle through indefinitely.
+     * @param listener the callback object to notify each time one of the
+     * requests in the repeating bursts has finished processing. If null, no
+     * metadata will be produced for this stream of requests, although image
+     * data will still be produced.
+     *
+     * @throws CameraAccessException if the camera device is no longer connected
+     * @throws IllegalStateException if the camera device has been closed or the
+     * device has encountered a fatal error.
+     *
+     * @see #capture
+     * @see #captureBurst
+     * @see #setRepeatingRequest
+     */
+    public void setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener)
+            throws CameraAccessException {
+    }
+
+    /**
+     * <p>Cancel any ongoing repeating capture set by either
+     * {@link #setRepeatingRequest setRepeatingRequest} or
+     * {@link #setRepeatingBurst}. Has no effect on requests submitted through
+     * {@link #capture capture} or {@link #captureBurst captureBurst}.</p>
+     *
+     * <p>Any currently in-flight captures will still complete, as will any
+     * burst that is mid-capture. To ensure that the device has finished
+     * processing all of its capture requests and is in idle state, use the
+     * {@link #waitUntilIdle waitUntilIdle} method.</p>
+     *
+     * @throws CameraAccessException if the camera device is no longer connected
+     * @throws IllegalStateException if the camera device has been closed or the
+     * device has encountered a fatal error.
+     *
+     * @see #setRepeatingRequest
+     * @see #setRepeatingBurst
+     * @see #waitUntilIdle
+     *
+     * @throws CameraAccessException if the camera device is no longer connected
+     * @throws IllegalStateException if the camera device has been closed, the
+     * device has encountered a fatal error, or if there is an active repeating
+     * request or burst.
+     */
+    public void stopRepeating() throws CameraAccessException {
+    }
+
+    /**
+     * <p>Wait until all the submitted requests have finished processing</p>
+     *
+     * <p>This method blocks until all the requests that have been submitted to
+     * the camera device, either through {@link #capture capture},
+     * {@link #captureBurst captureBurst},
+     * {@link #setRepeatingRequest setRepeatingRequest}, or
+     * {@link #setRepeatingBurst setRepeatingBurst}, have completed their
+     * processing.</p>
+     *
+     * <p>Once this call returns successfully, the device is in an idle state,
+     * and can be reconfigured with {@link #configureOutputs configureOutputs}.</p>
+     *
+     * <p>This method cannot be used if there is an active repeating request or
+     * burst, set with {@link #setRepeatingRequest setRepeatingRequest} or
+     * {@link #setRepeatingBurst setRepeatingBurst}. Call
+     * {@link #stopRepeating stopRepeating} before calling this method.</p>
+     *
+     * @throws CameraAccessException if the camera device is no longer connected
+     * @throws IllegalStateException if the camera device has been closed, the
+     * device has encountered a fatal error, or if there is an active repeating
+     * request or burst.
+     */
+    public void waitUntilIdle() throws CameraAccessException {
+    }
+
+    /**
+     * Set the error listener object to call when an asynchronous error
+     * occurs. The errors reported here are only device-wide errors; errors
+     * about individual requests or frames are reported through
+     * {@link CaptureListener#onCaptureFailed}.
+     *
+     * @param listener the ErrorListener to send asynchronous error
+     * notifications to. Setting this to null will stop notifications about
+     * asynchronous errors.
+     */
+    public void setErrorListener(ErrorListener listener) {
+    }
+
+    /**
+     * Close the connection to this camera device. After this call, all calls to
+     * the camera device interface will throw a {@link IllegalStateException},
+     * except for calls to close().
+     */
+    public void close() {
+    }
+
+    /**
+     * A listener for receiving metadata about completed image captures. The
+     * metadata includes, among other things, the final capture settings and the
+     * state of the control algorithms.
+     */
+    public interface CaptureListener {
+        /**
+         * <p>Called when a capture request has been processed by a
+         * {@link CameraDevice}.</p>
+         *
+         * @param camera The CameraDevice sending the callback.
+         * @param request The request that was given to the CameraDevice
+         * @param result The output metadata from the capture, including the
+         * final capture parameters and the state of the camera system during
+         * capture.
+         *
+         * @see #capture
+         * @see #captureBurst
+         * @see #setRepeatingRequest
+         * @see #setRepeatingBurst
+         */
+        public void onCaptureComplete(CameraDevice camera,
+                CaptureRequest request, CaptureResult result);
+
+        /**
+         * <p>Called instead of onCaptureComplete when the camera device failed
+         * to produce a CaptureResult for the request. Other requests are
+         * unaffected, and some or all image buffers from the capture may have
+         * been pushed to their respective output streams.</p>
+         *
+         * @param camera The CameraDevice sending the callback.
+         * @param request The request that was given to the CameraDevice
+         *
+         * @see #capture
+         * @see #captureBurst
+         * @see #setRepeatingRequest
+         * @see #setRepeatingBurst
+         */
+        public void onCaptureFailed(CameraDevice camera,
+                CaptureRequest request);
+    }
+
+    /**
+     * <p>A listener for asynchronous errors from the camera device. Errors
+     * about specific {@link CaptureRequest CaptureRequests} are sent through
+     * the capture {@link CaptureListener#onCaptureFailed listener}
+     * interface. Errors reported through this listener affect the device as a
+     * whole.</p>
+     */
+    public interface ErrorListener {
+        /**
+         * <p>This camera device has been disconnected by the camera
+         * service. Any attempt to call methods on this CameraDevice will throw
+         * a {@link CameraAccessException}. The disconnection could be due to a
+         * change in security policy or permissions; the physical disconnection
+         * of a removable camera device; or the camera being needed for a
+         * higher-priority use case.</p>
+         *
+         * <p>There may still be capture completion or camera stream listeners
+         * that will be called after this error is received.</p>
+         */
+        public static final int DEVICE_DISCONNECTED = 1;
+
+        /**
+         * <p>The camera device has encountered a fatal error. Any attempt to
+         * call methods on this CameraDevice will throw a
+         * {@link java.lang.IllegalStateException}.</p>
+         *
+         * <p>There may still be capture completion or camera stream listeners
+         * that will be called after this error is received.</p>
+         *
+         * <p>The application needs to re-open the camera device to use it
+         * again.</p>
+         */
+        public static final int DEVICE_ERROR = 2;
+
+        /**
+         * <p>The camera service has encountered a fatal error. Any attempt to
+         * call methods on this CameraDevice in the future will throw a
+         * {@link java.lang.IllegalStateException}.</p>
+         *
+         * <p>There may still be capture completion or camera stream listeners
+         * that will be called after this error is received.</p>
+         *
+         * <p>The device may need to be shut down and restarted to restore
+         * camera function, or there may be a persistent hardware problem.</p>
+         */
+        public static final int SERVICE_ERROR = 3;
+
+        /**
+         * The method to call when a camera device has encountered an error.
+         *
+         * @param camera The device reporting the error
+         * @param error The error code, one of the ErrorListener.ERROR_ values.
+         */
+        public void onCameraDeviceError(CameraDevice camera, int error);
+    }
+
+}
diff --git a/core/java/android/hardware/photography/CameraManager.java b/core/java/android/hardware/photography/CameraManager.java
new file mode 100644
index 0000000..328ba4b
--- /dev/null
+++ b/core/java/android/hardware/photography/CameraManager.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+package android.hardware.photography;
+
+/**
+ * <p>An interface for iterating, listing, and connecting to
+ * {@link CameraDevice CameraDevices}.</p>
+ *
+ * <p>You can get an instance of this class by calling
+ * {@link android.content.Context#getSystemService(String) Context.getSystemService()}.</p>
+ *
+ * <pre>CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);</pre>
+ *
+ * <p>For more details about communicating with camera devices, read the Camera
+ * developer guide or the {@link android.hardware.photography photography}
+ * package documentation.</p>
+ */
+public final class CameraManager {
+
+    /**
+     * @hide
+     */
+    public CameraManager() {
+    }
+
+    /**
+     * <p>Return the list of currently connected camera devices by
+     * identifier. Non-removable cameras use integers starting at 0 for their
+     * identifiers, while removable cameras have a unique identifier for each
+     * individual device, even if they are the same model.</p>
+     *
+     * @return The list of currently connected camera devices.
+     */
+    public String[] getDeviceIdList() {
+        return null;
+    }
+
+    /**
+     * Register a listener to be notified about camera device availability.
+     *
+     * @param listener the new listener to send camera availablity notices to.
+     */
+    public void registerCameraListener(CameraListener listener) {
+    }
+
+    /**
+     * Remove a previously-added listener; the listener will no longer receive
+     * connection and disconnection callbacks.
+     *
+     * @param listener the listener to remove from the notification list
+     */
+    public void unregisterCameraListener(CameraListener listener) {
+    }
+
+    /**
+     * <p>Query the capabilities of a camera device. These capabilities are
+     * immutable for a given camera.</p>
+     *
+     * @param cameraId The id of the camera device to query
+     * @return The properties of the given camera
+     *
+     * @throws IllegalArgumentException if the cameraId does not match any
+     * currently connected camera device.
+     * @throws CameraAccessException if the camera is disabled by device policy.
+     * @throws SecurityException if the application does not have permission to
+     * access the camera
+     *
+     * @see #getDeviceIdList
+     * @see android.app.admin.DevicePolicyManager#setCameraDisabled
+     */
+    public CameraProperties getCameraProperties(String cameraId)
+            throws CameraAccessException {
+        throw new IllegalArgumentException();
+    }
+
+    /**
+     * Open a connection to a camera with the given ID. Use
+     * {@link #getDeviceIdList} to get the list of available camera
+     * devices. Note that even if an id is listed, open may fail if the device
+     * is disconnected between the calls to {@link #getDeviceIdList} and
+     * {@link #openCamera}.
+     *
+     * @param cameraId The unique identifier of the camera device to open
+     *
+     * @throws IllegalArgumentException if the cameraId does not match any
+     * currently connected camera device.
+     * @throws CameraAccessException if the camera is disabled by device policy,
+     * or too many camera devices are already open.
+     * @throws SecurityException if the application does not have permission to
+     * access the camera
+     *
+     * @see #getDeviceIdList
+     * @see android.app.admin.DevicePolicyManager#setCameraDisabled
+     */
+    public CameraDevice openCamera(String cameraId) throws CameraAccessException {
+        throw new IllegalArgumentException();
+    }
+
+    /**
+     * Interface for listening to cameras becoming available or unavailable.
+     * Cameras become available when they are no longer in use, or when a new
+     * removable camera is connected. They become unavailable when some
+     * application or service starts using a camera, or when a removable camera
+     * is disconnected.
+     */
+    public interface CameraListener {
+        /**
+         * A new camera has become available to use.
+         *
+         * @param cameraId The unique identifier of the new camera.
+         */
+        public void onCameraAvailable(String cameraId);
+
+        /**
+         * A previously-available camera has become unavailable for use. If an
+         * application had an active CameraDevice instance for the
+         * now-disconnected camera, that application will receive a {@link
+         * CameraDevice.ErrorListener#DEVICE_DISCONNECTED disconnection error}.
+         *
+         * @param cameraId The unique identifier of the disconnected camera.
+         */
+        public void onCameraUnavailable(String cameraId);
+    }
+}
diff --git a/core/java/android/hardware/photography/CameraMetadata.java b/core/java/android/hardware/photography/CameraMetadata.java
new file mode 100644
index 0000000..385a1b9
--- /dev/null
+++ b/core/java/android/hardware/photography/CameraMetadata.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+package android.hardware.photography;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The base class for camera controls and information.
+ *
+ * This class defines the basic key/value map used for querying for camera
+ * characteristics or capture results, and for setting camera request
+ * parameters.
+ *
+ * @see CameraDevice
+ * @see CameraManager
+ * @see CameraProperties
+ **/
+public class CameraMetadata implements Parcelable {
+
+    public CameraMetadata() {
+        mMetadataMap = new HashMap<Key<?>, Object>();
+    }
+
+    private CameraMetadata(Parcel in) {
+
+    }
+
+    public static final Parcelable.Creator<CameraMetadata> CREATOR =
+            new Parcelable.Creator<CameraMetadata>() {
+        public CameraMetadata createFromParcel(Parcel in) {
+            return new CameraMetadata(in);
+        }
+
+        public CameraMetadata[] newArray(int size) {
+            return new CameraMetadata[size];
+        }
+    };
+
+    /**
+     * Set a camera metadata field to a value. The field definitions can be
+     * found in {@link CameraProperties}, {@link CaptureResult}, and
+     * {@link CaptureRequest}.
+     *
+     * @param key the metadata field to write.
+     * @param value the value to set the field to, which must be of a matching
+     * type to the key.
+     */
+    public <T> void set(Key<T> key, T value) {
+        mMetadataMap.put(key, value);
+    }
+
+    /**
+     * Get a camera metadata field value. The field definitions can be
+     * found in {@link CameraProperties}, {@link CaptureResult}, and
+     * {@link CaptureRequest}.
+     *
+     * @param key the metadata field to read.
+     * @return the value of that key, or {@code null} if the field is not set.
+     */
+    @SuppressWarnings("unchecked")
+    public <T> T get(Key<T> key) {
+        return (T) mMetadataMap.get(key);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+
+    }
+
+    public static class Key<T> {
+        public Key(String name) {
+            if (name == null) {
+                throw new NullPointerException("Key needs a valid name");
+            }
+            mName = name;
+        }
+
+        public final String getName() {
+            return mName;
+        }
+
+        @Override
+        public final int hashCode() {
+            return mName.hashCode();
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public final boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+
+            if (!(o instanceof Key)) {
+                return false;
+            }
+
+            Key lhs = (Key) o;
+
+            return mName.equals(lhs.mName);
+        }
+
+        private final String mName;
+    }
+
+    private Map<Key<?>, Object> mMetadataMap;
+}
\ No newline at end of file
diff --git a/core/java/android/hardware/photography/CameraProperties.java b/core/java/android/hardware/photography/CameraProperties.java
new file mode 100644
index 0000000..1bfd712
--- /dev/null
+++ b/core/java/android/hardware/photography/CameraProperties.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+package android.hardware.photography;
+
+import android.graphics.Rect;
+
+import java.util.List;
+
+/**
+ * <p>The properties describing a
+ * {@link CameraDevice CameraDevice}.</p>
+ *
+ * <p>These properties are fixed for a given CameraDevice, and can be queried
+ * through the {@link CameraManager CameraManager}
+ * interface in addition to through the CameraDevice interface.</p>
+ *
+ * @see CameraDevice
+ * @see CameraManager
+ */
+public final class CameraProperties extends CameraMetadata {
+    /**
+     * The model name of the camera. For fixed (non-removable) cameras, this is
+     * the manufacturer's name. For removable cameras, this is a string that
+     * uniquely identifies the camera model and manufacturer. The
+     * {@link #INFO_IDENTIFIER} can be used to distinguish between multiple
+     * removable cameras of the same model.
+     */
+    public static final Key INFO_MODEL =
+            new Key<String>("android.info.model");
+
+    /**
+     * A unique identifier for this camera. For removable cameras, every
+     * camera will have a unique identifier, including two cameras of the
+     * same model and manufacturer. For non-removable cameras, the
+     * identifier is equal to the the device's id.
+     */
+    public static final Key INFO_IDENTIFIER =
+            new Key<String>("android.info.identifier");
+
+    /**
+     * <p>Whether this camera is removable or not.</p>
+     *
+     * <p>Applications using a removable camera must be prepared for the camera
+     * to be disconnected during use. Use the {@link #INFO_IDENTIFIER} field to
+     * determine if this camera is a match for a camera device seen earlier.</p>
+     */
+    public static final Key INFO_REMOVABLE =
+            new Key<Boolean>("android.info.isRemovable");
+
+    /**
+     * <p>The hardware operational model of this device. One of the
+     * INFO_SUPPORTED_HARDWARE_LEVEL_* constants.</p>
+     *
+     * <p>Limited-capability devices have a number of limitations relative to
+     * full-capability cameras. Roughly, they have capabilities comparable to
+     * those provided by the deprecated {@link android.hardware.Camera}
+     * class.</p>
+     *
+     * <p>Specifically, limited-mode devices:</p>
+     *
+     * <ol>
+     *
+     *  <li>Do not provide per-frame result metadata for repeating
+     *  captures. This means that a CaptureListener will not be called for
+     *  captures done through {@link CameraDevice#setRepeatingRequest
+     *  setRepeatingRequest} or {@link CameraDevice#setRepeatingBurst
+     *  setRepeatingBurst}.</li>
+     *
+     *  <li>Do not support complete result metadata. Only a few fields are
+     *  provided, such as the timestamp (TODO).</li>
+     *
+     *  <li>Do not support manual capture controls. Only the (TODO)
+     *  ANDROID_CONTROL_* fields and TODO controls are used, and the various
+     *  AE/AF/AWB_OFF control values cannot be used.</li>
+     *
+     *  <li>Do not support high frame rate captures. To obtain high frame rate,
+     *  the {@link CameraDevice#setRepeatingRequest setRepeatingRequest} method
+     *  must be used. The {@link CameraDevice#capture capture},
+     *  {@link CameraDevice#captureBurst captureBurst}, and
+     *  {@link CameraDevice#setRepeatingBurst setRepeatingBurst} methods will
+     *  result in slow frame captures.</li>
+     *
+     * </ol>
+     *
+     * @see #INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED
+     * @see #INFO_SUPPORTED_HARDWARE_LEVEL_FULL
+     */
+    public static final Key INFO_SUPPORTED_HARDWARE_LEVEL =
+            new Key<Integer>("android.info.supportedHardwareLevel");
+
+    /**
+     * <p>The type reported by limited-capability camera devices.</p>
+     *
+     * <p>Limited-capability devices have a number of limitations relative to
+     * full-capability cameras. Roughly, they have capabilities comparable to
+     * those provided by the deprecated {@link android.hardware.Camera}
+     * class.</p>
+     *
+     * <p>Specifically, limited-mode devices:</p>
+     *
+     * <ol>
+     *
+     *  <li>Do not provide per-frame result metadata for repeating
+     *  captures. This means that a CaptureListener will not be called for
+     *  captures done through {@link CameraDevice#setRepeatingRequest
+     *  setRepeatingRequest} or {@link CameraDevice#setRepeatingBurst
+     *  setRepeatingBurst}.</li>
+     *
+     *  <li>Do not support complete result metadata. Only a few fields are
+     *  provided, such as the timestamp (TODO).</li>
+     *
+     *  <li>Do not support manual capture controls. Only the (TODO)
+     *  ANDROID_CONTROL_* fields and TODO controls are used, and the various
+     *  AE/AF/AWB_OFF control values cannot be used.</li>
+     *
+     *  <li>Do not support high frame rate captures. To obtain high frame rate,
+     *  the {@link CameraDevice#setRepeatingRequest setRepeatingRequest} method
+     *  must be used. The {@link CameraDevice#capture capture},
+     *  {@link CameraDevice#captureBurst captureBurst}, and
+     *  {@link CameraDevice#setRepeatingBurst setRepeatingBurst} methods will
+     *  result in slow frame captures.</li>
+     *
+     * </ol>
+     *
+     * @see #INFO_SUPPORTED_HARDWARE_LEVEL
+     */
+    public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0;
+
+    /**
+     * <p>The type reported by full-capability camera devices</p>
+     *
+     * <p>Full-capability devices allow for per-frame control of capture
+     * hardware and post-processing parameters at high frame rates. They also
+     * provide output data at high resolution in uncompressed formats, in
+     * addition to compressed JPEG output.</p>
+     *
+     * @see #INFO_SUPPORTED_HARDWARE_LEVEL
+     */
+    public static final int INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1;
+
+    /**
+     * <p>The available output formats from this camera device. When using a
+     * {@link android.media.ImageReader} as an output target, the
+     * ImageReader must be configured to use one of these formats.</p>
+     *
+     * <p>The list is a subset of the formats defined in
+     * {@link android.graphics.ImageFormat}.</p>
+     *
+     * <p>The image formats {@link android.graphics.ImageFormat#JPEG},
+     * {@link android.graphics.ImageFormat#YUV_420_888} are guaranteed to be
+     * supported.</p>
+     */
+    public static final Key SCALER_AVAILABLE_FORMATS =
+            new Key<Integer[]>("android.scaler.availableFormats");
+
+    /**
+     * <p>The available output sizes for JPEG buffers from this camera
+     * device. When using a {@link android.media.ImageReader} as an output
+     * target, the ImageReader must be configured to use one of these sizes
+     * when using format {@link android.graphics.ImageFormat#JPEG}.</p>
+     */
+    public static final Key SCALER_AVAILABLE_JPEG_SIZES =
+            new Key<Size[]>("android.scaler.availableJpegSizes");
+
+    /**
+     * <p>The available sizes for output buffers from this camera device, when
+     * the buffers are neither of the {@link android.graphics.ImageFormat#JPEG}
+     * or of the {@link android.graphics.ImageFormat#RAW_SENSOR} type.</p>
+     *
+     * <p>When using a {@link android.view.SurfaceView},
+     * {@link android.graphics.SurfaceTexture},
+     * {@link android.media.MediaRecorder}, {@link android.media.MediaCodec}, or
+     * {@link android.renderscript.Allocation} as an output target, that target
+     * must be configured to one of these sizes. See
+     * {@link CameraDevice#configureOutputs} for details.
+     *
+     * <p>When using a {@link android.media.ImageReader} as an output
+     * target, the ImageReader must be configured to use one of these sizes
+     * when using format {@link android.graphics.ImageFormat#YUV_420_888}.</p>
+     *
+     */
+    public static final Key SCALER_AVAILABLE_PROCESSED_SIZES =
+            new Key<Size[]>("android.scaler.availableProcessedSizes");
+
+    /**
+     * <p>The available sizes for output buffers from this camera device, when
+     * the buffers are of the {@link android.graphics.ImageFormat#RAW_SENSOR} type. This type of output may not be
+     * supported by the device; check {@link #SCALER_AVAILABLE_FORMATS} to
+     * check. In that case, this list will not exist.</p>
+     *
+     * <p>When using a {@link android.media.ImageReader} as an output
+     * target, the ImageReader must be configured to use one of these sizes
+     * when using image format {@link android.graphics.ImageFormat#RAW_SENSOR}.</p>
+     */
+    public static final Key SCALER_AVAILABLE_RAW_SIZES =
+            new Key<Size[]>("android.scaler.availableRawSizes");
+
+    /**
+     * <p>The coordinates of the sensor's active pixel array, relative to its
+     * total pixel array. These are the pixels that are actually used for image
+     * capture. The active pixel region may be smaller than the total number of
+     * pixels, if some pixels are used for other tasks such as calibrating the
+     * sensor's black level. If all pixels available for readout are used for
+     * imaging, then this rectangle will be
+     * {@code (0,0) - (SENSOR_PIXEL_ARRAY_SIZE.width,
+     * SENSOR_PIXEL_ARRAY_SIZE.height)}.</p>
+     *
+     * <p>If raw sensor capture is supported by this device, the width and
+     * height of the active pixel array match up to one of the supported raw
+     * capture sizes, and using that size will capture just the active pixel
+     * array region.</p>
+     *
+     * <p>Most other coordinates used by the camera device (for example, for
+     * metering and crop region selection, or for reporting detected faces) use
+     * a coordinate system based on the active array dimensions, with (0,0)
+     * being the top-left corner of the active array.</p>
+     */
+    public static final Key SENSOR_ACTIVE_ARRAY_SIZE =
+            new Key<Rect>("android.sensor.activeArraySize");
+
+    /**
+     * <p>The size of the sensor's total pixel array available for readout. Some
+     * of these pixels may not be used for image capture, in which case
+     * {@link #SENSOR_ACTIVE_ARRAY_SIZE} will describe a rectangle smaller than
+     * this. If raw sensor capture is supported by this device, this is one of
+     * the supported capture sizes.</p>
+     */
+    public static final Key SENSOR_PIXEL_ARRAY_SIZE =
+            new Key<Size>("android.sensor.activeArraySize");
+
+    // TODO: Many more of these.
+
+}
diff --git a/core/java/android/hardware/photography/CaptureRequest.java b/core/java/android/hardware/photography/CaptureRequest.java
new file mode 100644
index 0000000..a54c743
--- /dev/null
+++ b/core/java/android/hardware/photography/CaptureRequest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+package android.hardware.photography;
+
+import android.view.Surface;
+
+import java.util.List;
+
+
+/**
+ * <p>All the settings required to capture a single image from the image sensor.</p>
+ *
+ * <p>Contains the configuration for the capture hardware (sensor, lens, flash),
+ * the processing pipeline, the control algorithms, and the output buffers.</p>
+ *
+ * <p>CaptureRequests can be created by calling
+ * {@link CameraDevice#createCaptureRequest}</p>
+ *
+ * <p>CaptureRequests are given to {@link CameraDevice#capture} or
+ * {@link CameraDevice#setRepeatingRequest} to capture images from a camera.</p>
+ *
+ * <p>Each request can specify a different subset of target Surfaces for the
+ * camera to send the captured data to. All the surfaces used in a request must
+ * be part of the surface list given to the last call to
+ * {@link CameraDevice#configureOutputs}.</p>
+ *
+ * <p>For example, a request meant for repeating preview might only include the
+ * Surface for the preview SurfaceView or SurfaceTexture, while a
+ * high-resolution still capture would also include a Surface from a ImageReader
+ * configured for high-resolution JPEG images.</p>
+ *
+ * @see CameraDevice#capture
+ * @see CameraDevice#setRepeatingRequest
+ * @see CameraDevice#createRequest
+ */
+public final class CaptureRequest extends CameraMetadata {
+
+    /**
+     * The exposure time for this capture, in nanoseconds.
+     */
+    public static final Key SENSOR_EXPOSURE_TIME =
+            new Key<Long>("android.sensor.exposureTime");
+
+    /**
+     * The sensor sensitivity (gain) setting for this camera.
+     * This is represented as an ISO sensitivity value
+     */
+    public static final Key SENSOR_SENSITIVITY =
+            new Key<Integer>("android.sensor.sensitivity");
+
+    // Many more settings
+
+    CaptureRequest() {
+    }
+
+    /**
+     * <p>Add a surface to the list of targets for this request</p>
+     *
+     * <p>The Surface added must be one of the surfaces included in the last
+     * call to {@link CameraDevice#configureOutputs}.</p>
+     */
+    public void addTarget(Surface outputTarget) {
+    }
+
+    /**
+     * <p>Remove a surface from the list of targets for this request.</p>
+     */
+    public void removeTarget(Surface outputTarget) {
+    }
+
+}
\ No newline at end of file
diff --git a/core/java/android/hardware/photography/CaptureResult.java b/core/java/android/hardware/photography/CaptureResult.java
new file mode 100644
index 0000000..dd36f1d
--- /dev/null
+++ b/core/java/android/hardware/photography/CaptureResult.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+package android.hardware.photography;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+
+/**
+ * <p>The results of a single image capture from the image sensor.</p>
+ *
+ * <p>Contains the final configuration for the capture hardware (sensor, lens,
+ * flash), the processing pipeline, the control algorithms, and the output
+ * buffers.</p>
+ *
+ * <p>CaptureResults are produced by a {@link CameraDevice} after processing a
+ * {@link CaptureRequest}. All properties listed for capture requests can also
+ * be queried on the capture result, to determine the final values used for
+ * capture. The result also includes additional metadata about the state of the
+ * camera device during the capture.</p>
+ *
+ */
+public final class CaptureResult extends CameraMetadata {
+
+    /**
+     * The timestamp representing the start of image capture, in nanoseconds.
+     * This corresponds to the timestamp available through
+     * {@link android.graphics.SurfaceTexture#getTimestamp SurfaceTexture.getTimestamp()}
+     * or {@link android.media.Image#getTimestamp Image.getTimestamp()} for this
+     * capture's image data.
+     */
+    public static final Key SENSOR_TIMESTAMP =
+            new Key<Long>("android.sensor.timestamp");
+
+    /**
+     * The state of the camera device's auto-exposure algorithm. One of the
+     * CONTROL_AE_STATE_* enumerations.
+     */
+    public static final Key CONTROL_AE_STATE =
+            new Key<Integer>("android.control.aeState");
+
+    /**
+     * The auto-exposure algorithm is inactive.
+     * @see CONTROL_AE_STATE
+     */
+    public static final int CONTROL_AE_STATE_INACTIVE = 0;
+
+    /**
+     * The auto-exposure algorithm is currently searching for proper exposure.
+     * @see CONTROL_AE_STATE
+     */
+    public static final int CONTROL_AE_STATE_SEARCHING = 1;
+
+    /**
+     * The auto-exposure algorithm has reached proper exposure values for the
+     * current scene.
+     * @see CONTROL_AE_STATE
+     */
+    public static final int CONTROL_AE_STATE_CONVERGED = 2;
+
+    /**
+     * The auto-exposure algorithm has been locked to its current values.
+     * @see CONTROL_AE_STATE
+     */
+    public static final int CONTROL_AE_STATE_LOCKED = 3;
+
+    /**
+     * The auto-exposure algorithm has reached proper exposure values as with
+     * CONTROL_AE_STATE_CONVERGED, but the scene is too dark to take a good
+     * quality image without firing the camera flash.
+     * @see CONTROL_AE_STATE
+     */
+    public static final int CONTROL_AE_STATE_FLASH_REQUIRED = 4;
+
+    /**
+     * The precapture sequence of the auto-exposure algorithm has been triggered,
+     * and is underway.
+     * @see CONTROL_AE_STATE
+     */
+    public static final int CONTROL_AE_STATE_PRECAPTURE =5;
+
+    /**
+     * The list of faces detected in this capture. Available if face detection
+     * was enabled for this capture
+     */
+    public static final Key STATISTICS_DETECTED_FACES =
+            new Key<Face[]>("android.statistics.faces");
+
+    // TODO: Many many more
+
+    CaptureResult() {
+    }
+
+    /**
+     * Describes a face detected in an image.
+     */
+    public static class Face {
+
+        /**
+         * <p>Bounds of the face. A rectangle relative to the sensor's
+         * {@link CameraProperties#SENSOR_ACTIVE_ARRAY_SIZE}, with (0,0)
+         * representing the top-left corner of the active array rectangle.</p>
+         */
+        public Rect getBounds() {
+            return mBounds;
+        }
+
+        /* <p>The confidence level for the detection of the face. The range is 1 to
+         * 100. 100 is the highest confidence.</p>
+         *
+         * <p>Depending on the device, even very low-confidence faces may be
+         * listed, so applications should filter out faces with low confidence,
+         * depending on the use case. For a typical point-and-shoot camera
+         * application that wishes to display rectangles around detected faces,
+         * filtering out faces with confidence less than 50 is recommended.</p>
+         *
+         */
+        public int getScore() {
+            return mScore;
+        }
+
+        /**
+         * An unique id per face while the face is visible to the tracker. If
+         * the face leaves the field-of-view and comes back, it will get a new
+         * id. This is an optional field, may not be supported on all devices.
+         * If not supported, id will always be set to -1. The optional fields
+         * are supported as a set. Either they are all valid, or none of them
+         * are.
+         */
+        public int getId() {
+            return mId;
+        }
+
+        /**
+         * The coordinates of the center of the left eye. The coordinates are in
+         * the same space as the ones for {@link #getBounds}. This is an
+         * optional field, may not be supported on all devices. If not
+         * supported, the value will always be set to null. The optional fields
+         * are supported as a set. Either they are all valid, or none of them
+         * are.
+         */
+        public Point getLeftEye() {
+            return mLeftEye;
+        }
+
+        /**
+         * The coordinates of the center of the right eye. The coordinates are
+         * in the same space as the ones for {@link #getBounds}.This is an
+         * optional field, may not be supported on all devices. If not
+         * supported, the value will always be set to null. The optional fields
+         * are supported as a set. Either they are all valid, or none of them
+         * are.
+         */
+        public Point getRightEye() {
+            return mRightEye;
+        }
+
+        /**
+         * The coordinates of the center of the mouth.  The coordinates are in
+         * the same space as the ones for {@link #getBounds}. This is an optional
+         * field, may not be supported on all devices. If not supported, the
+         * value will always be set to null. The optional fields are supported
+         * as a set. Either they are all valid, or none of them are.
+         */
+        public Point getMouth() {
+            return mMouth;
+        }
+
+        private Rect mBounds;
+        private int mScore;
+        private int mId;
+        private Point mLeftEye;
+        private Point mRightEye;
+        private Point mMouth;
+    }
+}
diff --git a/core/java/android/hardware/photography/Size.java b/core/java/android/hardware/photography/Size.java
new file mode 100644
index 0000000..e1115d3
--- /dev/null
+++ b/core/java/android/hardware/photography/Size.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+package android.hardware.photography;
+
+/**
+ * A simple immutable class for describing the dimensions of camera image
+ * buffers.
+ */
+public final class Size {
+    /**
+     * Create a new immutable Size instance
+     *
+     * @param w The width to store in the Size instance
+     * @param h The height to store in the Size instance
+     */
+    Size(int w, int h) {
+        mWidth = w;
+        mHeight = h;
+    }
+
+    public final int getWidth() {
+        return mWidth;
+    }
+
+    public final int getHeight() {
+        return mHeight;
+    }
+
+    private final int mWidth;
+    private final int mHeight;
+};
diff --git a/core/java/android/hardware/photography/package.html b/core/java/android/hardware/photography/package.html
new file mode 100644
index 0000000..578bdf5
--- /dev/null
+++ b/core/java/android/hardware/photography/package.html
@@ -0,0 +1,84 @@
+<!-- Copyright (C) 2013 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.
+-->
+<HTML>
+<BODY>
+<p>The android.hardware.photography package provides an interface to
+individual camera devices connected to an Android device. It replaces
+the deprecated {@link android.hardware.Camera} class.</p>
+
+<p>This package models a camera device as a pipeline, which takes in
+input requests for capturing a single frame, captures the single image
+per the request, and then outputs one capture result metadata packet,
+plus a set of output image buffers for the request. The requests are
+processed in-order, and multiple requests can be in flight at
+once. Since the camera device is a pipeline with multiple stages,
+having multiple requests in flight is required to maintain full
+framerate on most Android devices.</p>
+
+<p>To enumerate, query, and open available camera devices, obtain a
+{@link android.hardware.photography.CameraManager} instance.</p>
+
+<p>Individual {@link android.hardware.photography.CameraDevice
+CameraDevices} provide a set of static property information that
+describes the hardware device and the available settings and output
+parameters for the device. This information is provided through the
+{@link android.hardware.photography.CameraProperties} object.</p>
+
+<p>To capture or stream images from a camera device, the application
+must first configure a set of output Surfaces for use with the camera
+device, with {@link
+android.hardware.photography.CameraDevice#configureOutputs}. Each
+Surface has to be pre-configured with an appropriate size and format
+(if applicable) to match the sizes and formats available from the
+camera device. A target Surface can be obtained from a variety of
+classes, including {@link android.view.SurfaceView}, {@link
+android.graphics.SurfaceTexture} via {@link
+android.view.Surface#Surface(SurfaceTexture), {@link
+android.media.MediaCodec}, and {@link android.media.ImageReader}.
+</p>
+
+<p>The application then needs to construct a {@link
+android.hardware.photography.CaptureRequest}, which defines all the
+capture parameters needed by a camera device to capture a single
+image. The request also lists which of the configured output Surfaces
+should be used as targets for this capture. The CameraDevice has a
+{@link android.hardware.photography.CameraDevice#createCaptureRequest
+convenience factory method} for creating a request for a given use
+case which is optimized for the Android device the application is
+running on.</p>
+
+<p>Once the request has been set up, it can be handed to the
+CameraDevice either for a one-shot {@link
+android.hardware.photography.CameraDevice#capture} or for an endlessly
+{@link android.hardware.photography.CameraDevice#setRepeatingRequest
+repeating} use. Both methods also accept a list of requests to use as
+a burst capture / repeating burst. Repeating requests have a lower
+priority than captures, so a request submitted
+through <code>capture()</code> while there's a repeating request
+configured will be captured as soon as the current repeat (burst)
+capture completes.</p>
+
+<p>After processing a request, the camera device will produce a {@link
+android.hardware.photography.CaptureResult} object, which contains
+information about the state of the camera device at time of capture,
+and the final settings used. These may vary somewhat from the request,
+if rounding or resolving contradictory parameters was necessary. The
+camera device will also send a frame of image data into each of the
+output streams included in the request. These are produced
+asynchronously relative to the output CaptureResult, sometimes
+substantially later.</p>
+
+</BODY>
+</HTML>
diff --git a/core/java/android/view/SurfaceHolder.java b/core/java/android/view/SurfaceHolder.java
index 015a78e..99fa2a4 100644
--- a/core/java/android/view/SurfaceHolder.java
+++ b/core/java/android/view/SurfaceHolder.java
@@ -277,9 +277,6 @@
      * 
      * <p>This method is intended to be used by frameworks which often need
      * direct access to the Surface object (usually to pass it to native code).
-     * When designing APIs always use SurfaceHolder to pass surfaces around
-     * as opposed to the Surface object itself. A rule of thumb is that
-     * application code should never have to call this method.
      * 
      * @return Surface The surface.
      */
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index f6b747a..972ce47 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -100,6 +100,41 @@
     public static final int JPEG = 0x100;
 
     /**
+     * <p>Multi-plane Android YUV format</p>
+     *
+     * <p>This format is a generic YCbCr format, capable of describing any 4:2:0
+     * chroma-subsampled planar or semiplanar buffer, with 8 bits per color
+     * sample.</p>
+     *
+     * <p>Images in this format are always represented by three separate buffers
+     * of data, one for each color plane. Additional information always
+     * accompanies the buffers, describing the row stride and the pixel stride
+     * for each plane.</p>
+     *
+     * <p>For example, the {@link android.media.Image} object can provide data
+     * in this format from a {@link android.hardware.photography.CameraDevice}
+     * through a {@link android.media.ImageReader} object.</p>
+     *
+     * @see android.media.Image
+     * @see android.media.ImageReader
+     * @see android.hardware.camera.CameraDevice
+     */
+    public static final int YUV_420_888 = 0x23;
+
+    /**
+     * <p>General raw camera sensor image format, usually representing a
+     * single-channel Bayer-mosaic image. Each pixel color sample is stored with
+     * 16 bits of precision.</p>
+     *
+     * <p>The layout of the color mosaic, the maximum and minimum encoding
+     * values of the raw pixel data, the color space of the image, and all other
+     * needed information to interpret a raw sensor image must be queried from
+     * the {@link android.hardware.photography.CameraDevice} which produced the
+     * image.</p>
+     */
+    public static final int RAW_SENSOR = 0x201;
+
+    /**
      * Raw bayer format used for images, which is 10 bit precision samples
      * stored in 16 bit words. The filter pattern is RGGB. Whether this format
      * is supported by the camera hardware can be determined by
@@ -129,6 +164,10 @@
                 return 12;
             case NV21:
                 return 12;
+            case YUV_420_888:
+                return 12;
+            case RAW_SENSOR:
+                return 16;
             case BAYER_RGGB:
                 return 16;
         }
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
new file mode 100644
index 0000000..eb94346
--- /dev/null
+++ b/media/java/android/media/Image.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+package android.media;
+
+import android.graphics.ImageFormat;
+import java.nio.ByteBuffer;
+import java.lang.AutoCloseable;
+
+/**
+ * <p>A single complete image buffer to use with a media source such as a
+ * {@link MediaCodec} or a
+ * {@link android.hardware.photography.CameraDevice}.</p>
+ *
+ * <p>This class allows for efficient direct application access to the pixel
+ * data of the Image through one or more
+ * {@link java.nio.ByteBuffer ByteBuffers}. Each buffer is encapsulated in a
+ * {@link Plane} that describes the layout of the pixel data in that plane. Due
+ * to this direct access, and unlike the {@link android.graphics.Bitmap} class,
+ * Images are not directly usable as as UI resources.</p>
+ *
+ * <p>Since Images are often directly produced or consumed by hardware
+ * components, they are a limited resource shared across the system, and should
+ * be closed as soon as they are no longer needed.</p>
+ *
+ * <p>For example, when using the {@link ImageReader} class to read out Images
+ * from various media sources, not closing old Image objects will prevent the
+ * availability of new Images once
+ * {@link ImageReader#getMaxImages the maximum outstanding image count} is
+ * reached.</p>
+ *
+ * @see ImageReader
+ */
+public abstract class Image implements AutoCloseable {
+    /**
+     * Get the format for this image. This format determines the number of
+     * ByteBuffers needed to represent the image, and the general layout of the
+     * pixel data in each in ByteBuffer.
+     *
+     * The format is one of the values from
+     * {@link android.graphics.ImageFormat}. The mapping between the formats and
+     * the planes is as follows:
+     *
+     * <table>
+     * <th>
+     *   <td>Format</td>
+     *   <td>Plane count</td>
+     *   <td>Layout details</td>
+     * </th>
+     * <tr>
+     *   <td>{@link android.graphics.ImageFormat#JPEG}</td>
+     *   <td>1</td>
+     *   <td>Compressed data, so row and pixel strides are 0. To uncompress, use
+     *      {@link android.graphics.BitmapFactory#decodeByteArray}.</td>
+     * </tr>
+     * <tr>
+     *   <td>{@link android.graphics.ImageFormat#YUV_420_888}</td>
+     *   <td>3</td>
+     *   <td>A luminance plane followed by the Cb and Cr chroma planes.
+     *     The chroma planes have half the width and height of the luminance
+     *     plane (4:2:0 subsampling). Each pixel sample in each plane has 8 bits.
+     *     Each plane has its own row stride and pixel stride.</td>
+     * </tr>
+     * <tr>
+     *   <td>{@link android.graphics.ImageFormat#RAW_SENSOR}</td>
+     *   <td>1</td>
+     *   <td>A single plane of raw sensor image data, with 16 bits per color
+     *     sample. The details of the layout need to be queried from the source of
+     *     the raw sensor data, such as
+     *     {@link android.hardware.photography.CameraDevice}.
+     *   </td>
+     * </tr>
+     * </table>
+     *
+     * @see android.graphics.ImageFormat
+     */
+    public int getFormat() {
+        return ImageFormat.UNKNOWN;
+    }
+
+    /**
+     * The width of the image in pixels. For formats where some color channels
+     * are subsampled, this is the width of the largest-resolution plane.
+     */
+    public int getWidth() {
+        return 0;
+    }
+
+    /**
+     * The height of the image in pixels. For formats where some color channels
+     * are subsampled, this is the height of the largest-resolution plane.
+     */
+    public int getHeight() {
+        return 0;
+    }
+
+    /**
+     * Get the timestamp associated with this frame. The timestamp is measured
+     * in nanoseconds, and is monotonically increasing. However, the zero point
+     * and whether the timestamp can be compared against other sources of time
+     * or images depend on the source of this image.
+     */
+    public long getTimestamp() {
+        return 0;
+    }
+
+    /**
+     * Get the array of pixel planes for this Image. The number of planes is
+     * determined by the format of the Image.
+     */
+    public Plane[] getPlanes() {
+        return null;
+    }
+
+    /**
+     * Free up this frame for reuse. After calling this method, calling any
+     * methods on this Image will result in an IllegalStateException, and
+     * attempting to read from ByteBuffers returned by an earlier
+     * {@code Plane#getBuffer} call will have undefined behavior.
+     */
+    public abstract void close();
+
+    protected final void finalize() {
+        close();
+    }
+
+    /**
+     * <p>A single color plane of image data.</p>
+     *
+     * <p>The number and meaning of the planes in an Image are determined by the
+     * format of the Image.</p>
+     *
+     * <p>Once the Image has been closed, any access to the the plane's
+     * ByteBuffer will fail.</p>
+     *
+     * @see #getFormat
+     */
+    public static final class Plane {
+        /**
+         * <p>The row stride for this color plane, in bytes.
+         *
+         * <p>This is the distance between the start of two consecutive rows of
+         * pixels in the image.</p>
+         */
+        public int getRowStride() {
+            return 0;
+        }
+
+        /**
+         * <p>The distance between adjacent pixel samples, in bytes.</p>
+         *
+         * <p>This is the distance between two consecutive pixel values in a row
+         * of pixels. It may be larger than the size of a single pixel to
+         * account for interleaved image data or padded formats.</p>
+         */
+        public int getPixelStride() {
+            return 0;
+        }
+
+        /**
+         * <p>Get a set of direct {@link java.nio.ByteBuffer byte buffers}
+         * containing the frame data.</p>
+         *
+         * @return the byte buffer containing the image data for this plane.
+         */
+        public ByteBuffer getBuffer() {
+            return null;
+        }
+    }
+
+}
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
new file mode 100644
index 0000000..9384c14
--- /dev/null
+++ b/media/java/android/media/ImageReader.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+package android.media;
+
+import android.view.Surface;
+import java.lang.AutoCloseable;
+
+/**
+ * <p>The ImageReader class allows direct application access to image data
+ * rendered into a {@link android.view.Surface}</p>
+ *
+ * <p>Several Android media API classes accept Surface objects as targets to
+ * render to, including {@link MediaPlayer}, {@link MediaCodec},
+ * {@link android.hardware.photography.CameraDevice}, and
+ * {@link android.renderscript.Allocation RenderScript Allocations}. The image
+ * sizes and formats that can be used with each source vary, and should be
+ * checked in the documentation for the specific API.</p>
+ *
+ * <p>The image data is encapsulated in {@link Image} objects, and multiple such
+ * objects can be accessed at the same time, up to the number specified by the
+ * {@code maxImages} constructor parameter. New images sent to an ImageReader
+ * through its Surface are queued until accessed through the
+ * {@link #getNextImage} call. Due to memory limits, an image source will
+ * eventually stall or drop Images in trying to render to the Surface if the
+ * ImageReader does not obtain and release Images at a rate equal to the
+ * production rate.</p>
+ */
+public final class ImageReader {
+
+    /**
+     * <p>Create a new reader for images of the desired size and format.</p>
+     *
+     * <p>The maxImages parameter determines the maximum number of {@link Image}
+     * objects that can be be acquired from the ImageReader
+     * simultaneously. Requesting more buffers will use up more memory, so it is
+     * important to use only the minimum number necessary for the use case.</p>
+     *
+     * <p>The valid sizes and formats depend on the source of the image
+     * data.</p>
+     *
+     * @param width the width in pixels of the Images that this reader will
+     * produce.
+     * @param height the height in pixels of the Images that this reader will
+     * produce.
+     * @param format the format of the Image that this reader will produce. This
+     * must be one of the {@link android.graphics.ImageFormat} constants.
+     * @param maxImages the maximum number of images the user will want to
+     * access simultaneously. This should be as small as possible to limit
+     * memory use. Once maxImages Images are obtained by the user, one of them
+     * has to be released before a new Image will become available for access
+     * through getImage(). Must be greater than 0.
+     *
+     * @see Image
+     */
+    public ImageReader(int width, int height, int format, int maxImages) {
+        mWidth = width;
+        mHeight = height;
+        mFormat = format;
+        mMaxImages = maxImages;
+
+        if (width < 1 || height < 1) {
+            throw new IllegalArgumentException(
+                "The image dimensions must be positive");
+        }
+        if (mMaxImages < 1) {
+            throw new IllegalArgumentException(
+                "Maximum outstanding image count must be at least 1");
+        }
+    }
+
+    public int getWidth() {
+        return mWidth;
+    }
+
+    public int getHeight() {
+        return mHeight;
+    }
+
+    public int getImageFormat() {
+        return mFormat;
+    }
+
+    public int getMaxImages() {
+        return mMaxImages;
+    }
+
+    /**
+     * <p>Get a Surface that can be used to produce Images for this
+     * ImageReader.</p>
+     *
+     * <p>Until valid image data is rendered into this Surface, the
+     * {@link #getNextImage} method will return {@code null}. Only one source
+     * can be producing data into this Surface at the same time, although the
+     * same Surface can be reused with a different API once the first source is
+     * disconnected from the Surface.</p>
+     *
+     * @return A Surface to use for a drawing target for various APIs.
+     */
+    public Surface getSurface() {
+        return null;
+    }
+
+    /**
+     * <p>Get the next Image from the ImageReader's queue. Returns {@code null}
+     * if no new image is available.</p>
+     *
+     * @return a new frame of image data, or {@code null} if no image data is
+     * available.
+     */
+    public Image getNextImage() {
+        return null;
+    }
+
+    /**
+     * <p>Return the frame to the ImageReader for reuse.</p>
+     */
+    public void releaseImage(Image i) {
+        if (! (i instanceof SurfaceImage) ) {
+            throw new IllegalArgumentException(
+                "This image was not produced by an ImageReader");
+        }
+        SurfaceImage si = (SurfaceImage) i;
+        if (si.getReader() != this) {
+            throw new IllegalArgumentException(
+                "This image was not produced by this ImageReader");
+        }
+    }
+
+    public void setOnImageAvailableListener(OnImageAvailableListener l) {
+        mImageListener = l;
+    }
+
+    public interface OnImageAvailableListener {
+        void onImageAvailable(ImageReader reader);
+    }
+
+    private final int mWidth;
+    private final int mHeight;
+    private final int mFormat;
+    private final int mMaxImages;
+
+    private OnImageAvailableListener mImageListener;
+
+    private class SurfaceImage extends android.media.Image {
+        public SurfaceImage() {
+        }
+
+        @Override
+        public void close() {
+            ImageReader.this.releaseImage(this);
+        }
+
+        public ImageReader getReader() {
+            return ImageReader.this;
+        }
+    }
+}