Merge "QS: Cellular usage warning marker + policy cycle." into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index c319ce8..d283360 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11857,7 +11857,7 @@
 
 package android.hardware {
 
-  public class Camera {
+  public deprecated class Camera {
     method public final void addCallbackBuffer(byte[]);
     method public final void autoFocus(android.hardware.Camera.AutoFocusCallback);
     method public final void cancelAutoFocus();
@@ -11896,21 +11896,21 @@
     field public static final int CAMERA_ERROR_UNKNOWN = 1; // 0x1
   }
 
-  public static class Camera.Area {
+  public static deprecated class Camera.Area {
     ctor public Camera.Area(android.graphics.Rect, int);
     field public android.graphics.Rect rect;
     field public int weight;
   }
 
-  public static abstract interface Camera.AutoFocusCallback {
+  public static abstract deprecated interface Camera.AutoFocusCallback {
     method public abstract void onAutoFocus(boolean, android.hardware.Camera);
   }
 
-  public static abstract interface Camera.AutoFocusMoveCallback {
+  public static abstract deprecated interface Camera.AutoFocusMoveCallback {
     method public abstract void onAutoFocusMoving(boolean, android.hardware.Camera);
   }
 
-  public static class Camera.CameraInfo {
+  public static deprecated class Camera.CameraInfo {
     ctor public Camera.CameraInfo();
     field public static final int CAMERA_FACING_BACK = 0; // 0x0
     field public static final int CAMERA_FACING_FRONT = 1; // 0x1
@@ -11919,11 +11919,11 @@
     field public int orientation;
   }
 
-  public static abstract interface Camera.ErrorCallback {
+  public static abstract deprecated interface Camera.ErrorCallback {
     method public abstract void onError(int, android.hardware.Camera);
   }
 
-  public static class Camera.Face {
+  public static deprecated class Camera.Face {
     ctor public Camera.Face();
     field public int id;
     field public android.graphics.Point leftEye;
@@ -11933,15 +11933,15 @@
     field public int score;
   }
 
-  public static abstract interface Camera.FaceDetectionListener {
+  public static abstract deprecated interface Camera.FaceDetectionListener {
     method public abstract void onFaceDetection(android.hardware.Camera.Face[], android.hardware.Camera);
   }
 
-  public static abstract interface Camera.OnZoomChangeListener {
+  public static abstract deprecated interface Camera.OnZoomChangeListener {
     method public abstract void onZoomChange(int, boolean, android.hardware.Camera);
   }
 
-  public class Camera.Parameters {
+  public deprecated class Camera.Parameters {
     method public java.lang.String flatten();
     method public java.lang.String get(java.lang.String);
     method public java.lang.String getAntibanding();
@@ -12091,19 +12091,19 @@
     field public static final java.lang.String WHITE_BALANCE_WARM_FLUORESCENT = "warm-fluorescent";
   }
 
-  public static abstract interface Camera.PictureCallback {
+  public static abstract deprecated interface Camera.PictureCallback {
     method public abstract void onPictureTaken(byte[], android.hardware.Camera);
   }
 
-  public static abstract interface Camera.PreviewCallback {
+  public static abstract deprecated interface Camera.PreviewCallback {
     method public abstract void onPreviewFrame(byte[], android.hardware.Camera);
   }
 
-  public static abstract interface Camera.ShutterCallback {
+  public static abstract deprecated interface Camera.ShutterCallback {
     method public abstract void onShutter();
   }
 
-  public class Camera.Size {
+  public deprecated class Camera.Size {
     ctor public Camera.Size(int, int);
     field public int height;
     field public int width;
@@ -14970,7 +14970,7 @@
     method public void setAudioEncodingBitRate(int);
     method public void setAudioSamplingRate(int);
     method public void setAudioSource(int) throws java.lang.IllegalStateException;
-    method public void setCamera(android.hardware.Camera);
+    method public deprecated void setCamera(android.hardware.Camera);
     method public void setCaptureRate(double);
     method public void setLocation(float, float);
     method public void setMaxDuration(int) throws java.lang.IllegalArgumentException;
@@ -16166,6 +16166,10 @@
   public final class TvInputManager {
     method public boolean getAvailability(java.lang.String);
     method public java.util.List<android.media.tv.TvInputInfo> getTvInputList();
+    field public static final int VIDEO_UNAVAILABLE_REASON_BUFFERING = 3; // 0x3
+    field public static final int VIDEO_UNAVAILABLE_REASON_TUNE = 1; // 0x1
+    field public static final int VIDEO_UNAVAILABLE_REASON_UNKNOWN = 0; // 0x0
+    field public static final int VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL = 2; // 0x2
   }
 
   public static abstract class TvInputManager.TvInputListener {
@@ -16185,6 +16189,8 @@
     ctor public TvInputService.Session();
     method public void dispatchChannelRetuned(android.net.Uri);
     method public void dispatchTrackInfoChanged(java.util.List<android.media.tv.TvTrackInfo>);
+    method public void dispatchVideoAvailable();
+    method public void dispatchVideoUnavailable(int);
     method public android.view.View onCreateOverlayView();
     method public boolean onGenericMotionEvent(android.view.MotionEvent);
     method public boolean onKeyDown(int, android.view.KeyEvent);
@@ -16263,6 +16269,8 @@
     method public void onError(java.lang.String, int);
     method public void onTrackInfoChanged(java.lang.String, java.util.List<android.media.tv.TvTrackInfo>);
     method public void onVideoSizeChanged(java.lang.String, int, int);
+    method public void onVideoAvailable(java.lang.String);
+    method public void onVideoUnavailable(java.lang.String, int);
   }
 
 }
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index cf462cd..4c73e6a 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -133,7 +133,11 @@
  * <p>For more information about using cameras, read the
  * <a href="{@docRoot}guide/topics/media/camera.html">Camera</a> developer guide.</p>
  * </div>
+ *
+ * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+ *             applications.
  */
+@Deprecated
 public class Camera {
     private static final String TAG = "Camera";
 
@@ -247,7 +251,11 @@
 
     /**
      * Information about a camera
+     *
+     * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+     *             applications.
      */
+    @Deprecated
     public static class CameraInfo {
         /**
          * The facing of the camera is opposite to that of the screen.
@@ -675,7 +683,11 @@
      * @see #setOneShotPreviewCallback(Camera.PreviewCallback)
      * @see #setPreviewCallbackWithBuffer(Camera.PreviewCallback)
      * @see #startPreview()
+     *
+     * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+     *             applications.
      */
+    @Deprecated
     public interface PreviewCallback
     {
         /**
@@ -1175,7 +1187,10 @@
      * manifest element.</p>
      *
      * @see #autoFocus(AutoFocusCallback)
+     * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+     *             applications.
      */
+    @Deprecated
     public interface AutoFocusCallback
     {
         /**
@@ -1286,7 +1301,11 @@
      * Parameters#FOCUS_MODE_CONTINUOUS_VIDEO} and {@link
      * Parameters#FOCUS_MODE_CONTINUOUS_PICTURE}. Applications can show
      * autofocus animation based on this.</p>
+     *
+     * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+     *             applications.
      */
+    @Deprecated
     public interface AutoFocusMoveCallback
     {
         /**
@@ -1314,7 +1333,11 @@
      * Callback interface used to signal the moment of actual image capture.
      *
      * @see #takePicture(ShutterCallback, PictureCallback, PictureCallback, PictureCallback)
+     *
+     * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+     *             applications.
      */
+    @Deprecated
     public interface ShutterCallback
     {
         /**
@@ -1331,7 +1354,11 @@
      * Callback interface used to supply image data from a photo capture.
      *
      * @see #takePicture(ShutterCallback, PictureCallback, PictureCallback, PictureCallback)
+     *
+     * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+     *             applications.
      */
+    @Deprecated
     public interface PictureCallback {
         /**
          * Called when image data is available after a picture is taken.
@@ -1538,7 +1565,11 @@
      *
      * @see #setZoomChangeListener(OnZoomChangeListener)
      * @see #startSmoothZoom(int)
+     *
+     * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+     *             applications.
      */
+    @Deprecated
     public interface OnZoomChangeListener
     {
         /**
@@ -1568,7 +1599,10 @@
     /**
      * Callback interface for face detected in the preview frame.
      *
+     * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+     *             applications.
      */
+    @Deprecated
     public interface FaceDetectionListener
     {
         /**
@@ -1652,7 +1686,10 @@
      * list of face objects for use in focusing and metering.</p>
      *
      * @see FaceDetectionListener
+     * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+     *             applications.
      */
+    @Deprecated
     public static class Face {
         /**
          * Create an empty face.
@@ -1766,7 +1803,11 @@
      * Callback interface for camera error notification.
      *
      * @see #setErrorCallback(ErrorCallback)
+     *
+     * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+     *             applications.
      */
+    @Deprecated
     public interface ErrorCallback
     {
         /**
@@ -1864,7 +1905,10 @@
 
     /**
      * Image size (width and height dimensions).
+     * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+     *             applications.
      */
+    @Deprecated
     public class Size {
         /**
          * Sets the dimensions for pictures.
@@ -1931,7 +1975,11 @@
      * @see Parameters#setMeteringAreas(List)
      * @see Parameters#getMeteringAreas()
      * @see Parameters#getMaxNumMeteringAreas()
+     *
+     * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+     *             applications.
      */
+    @Deprecated
     public static class Area {
         /**
          * Create an area with specified rectangle and weight.
@@ -2005,7 +2053,11 @@
      * calling {@link Camera.Parameters#setColorEffect(String)}. If the
      * camera does not support color effects,
      * {@link Camera.Parameters#getSupportedColorEffects()} will return null.
+     *
+     * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+     *             applications.
      */
+    @Deprecated
     public class Parameters {
         // Parameter keys to communicate with the camera driver.
         private static final String KEY_PREVIEW_SIZE = "preview-size";
@@ -2960,7 +3012,6 @@
             case ImageFormat.YV12:      return PIXEL_FORMAT_YUV420P;
             case ImageFormat.RGB_565:   return PIXEL_FORMAT_RGB565;
             case ImageFormat.JPEG:      return PIXEL_FORMAT_JPEG;
-            case ImageFormat.BAYER_RGGB: return PIXEL_FORMAT_BAYER_RGGB;
             default:                    return null;
             }
         }
diff --git a/core/java/android/hardware/camera2/package.html b/core/java/android/hardware/camera2/package.html
index ef0d7bd..719c2f6 100644
--- a/core/java/android/hardware/camera2/package.html
+++ b/core/java/android/hardware/camera2/package.html
@@ -58,16 +58,16 @@
 <p>Generally, camera preview images are sent to {@link
 android.view.SurfaceView} or {@link android.view.TextureView} (via its
 {@link android.graphics.SurfaceTexture}). Capture of JPEG images or
-RAW buffers for {@link android.hardware.camera2.DngCreator} can be done
-with {@link android.media.ImageReader} with the
-{android.graphics.ImageFormat#JPEG} and
-{android.graphics.ImageFormat#RAW_SENSOR} formats.  Application-driven
+RAW buffers for {@link android.hardware.camera2.DngCreator} can be
+done with {@link android.media.ImageReader} with the {@link
+android.graphics.ImageFormat#JPEG} and {@link
+android.graphics.ImageFormat#RAW_SENSOR} formats.  Application-driven
 processing of camera data in RenderScript, OpenGL ES, or directly in
 managed or native code is best done through {@link
 android.renderscript.Allocation} with a YUV {@link
 android.renderscript.Type}, {@link android.graphics.SurfaceTexture},
-and {@link android.media.ImageReader} with a
-{android.graphics.ImageFormat#YUV_420_888} format, respectively.</p>
+and {@link android.media.ImageReader} with a {@link
+android.graphics.ImageFormat#YUV_420_888} format, respectively.</p>
 
 <p>The application then needs to construct a {@link
 android.hardware.camera2.CaptureRequest}, which defines all the
diff --git a/docs/html/guide/topics/media/camera.jd b/docs/html/guide/topics/media/camera.jd
index 56ef624..8b79b23 100644
--- a/docs/html/guide/topics/media/camera.jd
+++ b/docs/html/guide/topics/media/camera.jd
@@ -86,14 +86,17 @@
 
 <h2 id="basics">The Basics</h2>
 <p>The Android framework supports capturing images and video through the
-{@link android.hardware.Camera} API or camera {@link android.content.Intent}. Here are the relevant
+{@link android.hardware.camera2} API or camera {@link android.content.Intent}. Here are the relevant
 classes:</p>
 
 <dl>
-  <dt>{@link android.hardware.Camera}</dt>
-  <dd>This class is the primary API for controlling device cameras. This class is used to take
+  <dt>{@link android.hardware.camera2}</dt>
+  <dd>This package is the primary API for controlling device cameras. It can be used to take
 pictures or videos when you are building a camera application.</dd>
 
+  <dt>{@link android.hardware.Camera}</dt>
+  <dd>This class is the older deprecated API for controlling device cameras.</dd>
+
   <dt>{@link android.view.SurfaceView}</dt>
   <dd>This class is used to present a live camera preview to the user.</dd>
 
@@ -354,6 +357,10 @@
 code than <a href="#intents">using an intent</a>, but it can provide a more compelling experience
 for your users.</p>
 
+<p><strong> Note: The following guide is for the older, deprecated {@link android.hardware.Camera}
+API. For new or advanced camera applications, the newer {@link android.hardware.camera2} API is
+recommended.</strong></p>
+
 <p>The general steps for creating a custom camera interface for your application are as follows:</p>
 
 <ul>
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index 28fd7ba..ab4258d 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -54,9 +54,12 @@
      * cr_offset = y_size
      * cb_offset = y_size + c_size</pre>
      *
-     * <p>This format is guaranteed to be supported for camera preview images since
-     * API level 12; for earlier API versions, check
-     * {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.
+     * <p>For the {@link android.hardware.camera2} API, the {@link #YUV_420_888} format is
+     * recommended for YUV output instead.</p>
+     *
+     * <p>For the older camera API, this format is guaranteed to be supported for
+     * {@link android.hardware.Camera} preview images since API level 12; for earlier API versions,
+     * check {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.
      *
      * <p>Note that for camera preview callback use (see
      * {@link android.hardware.Camera#setPreviewCallback}), the
@@ -133,29 +136,47 @@
     public static final int Y16 = 0x20363159;
 
     /**
-     * YCbCr format, used for video. Whether this format is supported by the
-     * camera hardware can be determined by
-     * {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.
+     * YCbCr format, used for video.
+     *
+     * <p>For the {@link android.hardware.camera2} API, the {@link #YUV_420_888} format is
+     * recommended for YUV output instead.</p>
+     *
+     * <p>Whether this format is supported by the old camera API can be determined by
+     * {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.</p>
+     *
      */
     public static final int NV16 = 0x10;
 
     /**
-     * YCrCb format used for images, which uses the NV21 encoding format. This
-     * is the default format for camera preview images, when not otherwise set
-     * with {@link android.hardware.Camera.Parameters#setPreviewFormat(int)}.
+     * YCrCb format used for images, which uses the NV21 encoding format.
+     *
+     * <p>This is the default format
+     * for {@link android.hardware.Camera} preview images, when not otherwise set with
+     * {@link android.hardware.Camera.Parameters#setPreviewFormat(int)}.</p>
+     *
+     * <p>For the {@link android.hardware.camera2} API, the {@link #YUV_420_888} format is
+     * recommended for YUV output instead.</p>
      */
     public static final int NV21 = 0x11;
 
     /**
      * YCbCr format used for images, which uses YUYV (YUY2) encoding format.
-     * This is an alternative format for camera preview images. Whether this
-     * format is supported by the camera hardware can be determined by
-     * {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.
+     *
+     * <p>For the {@link android.hardware.camera2} API, the {@link #YUV_420_888} format is
+     * recommended for YUV output instead.</p>
+     *
+     * <p>This is an alternative format for {@link android.hardware.Camera} preview images. Whether
+     * this format is supported by the camera hardware can be determined by
+     * {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.</p>
      */
     public static final int YUY2 = 0x14;
 
     /**
-     * Encoded formats. These are not necessarily supported by the hardware.
+     * Compressed JPEG format.
+     *
+     * <p>This format is always supported as an output format for the
+     * {@link android.hardware.camera2} API, and as a picture format for the older
+     * {@link android.hardware.Camera} API</p>
      */
     public static final int JPEG = 0x100;
 
@@ -332,16 +353,6 @@
     public static final int RAW10 = 0x25;
 
     /**
-     * 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
-     * {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.
-     *
-     * @hide
-     */
-    public static final int BAYER_RGGB = 0x200;
-
-    /**
      * Use this function to retrieve the number of bits per pixel of an
      * ImageFormat.
      *
@@ -369,8 +380,6 @@
                 return 12;
             case RAW_SENSOR:
                 return 16;
-            case BAYER_RGGB:
-                return 16;
             case RAW10:
                 return 10;
         }
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 17795f3..f52c661 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -27,14 +27,18 @@
 /**
  * Captures frames from an image stream as an OpenGL ES texture.
  *
- * <p>The image stream may come from either camera preview or video decode.  A SurfaceTexture
- * may be used in place of a SurfaceHolder when specifying the output destination of a
- * {@link android.hardware.Camera} or {@link android.media.MediaPlayer}
- * object.  Doing so will cause all the frames from the image stream to be sent to the
- * SurfaceTexture object rather than to the device's display.  When {@link #updateTexImage} is
- * called, the contents of the texture object specified when the SurfaceTexture was created are
- * updated to contain the most recent image from the image stream.  This may cause some frames of
- * the stream to be skipped.
+ * <p>The image stream may come from either camera preview or video decode. A
+ * {@link android.view.Surface} created from a SurfaceTexture can be used as an output
+ * destination for the {@link android.hardware.camera2}, {@link android.media.MediaCodec},
+ * {@link android.media.MediaPlayer}, and {@link android.renderscript.Allocation} APIs.
+ * When {@link #updateTexImage} is called, the contents of the texture object specified
+ * when the SurfaceTexture was created are updated to contain the most recent image from the image
+ * stream.  This may cause some frames of the stream to be skipped.
+ *
+ * <p>A SurfaceTexture may also be used in place of a SurfaceHolder when specifying the output
+ * destination of the older {@link android.hardware.Camera} API. Doing so will cause all the
+ * frames from the image stream to be sent to the SurfaceTexture object rather than to the device's
+ * display.
  *
  * <p>When sampling from the texture one should first transform the texture coordinates using the
  * matrix queried via {@link #getTransformMatrix(float[])}.  The transform matrix may change each
diff --git a/media/java/android/media/MediaActionSound.java b/media/java/android/media/MediaActionSound.java
index 7a520fe..2f4d136 100644
--- a/media/java/android/media/MediaActionSound.java
+++ b/media/java/android/media/MediaActionSound.java
@@ -24,13 +24,15 @@
  * <p>A class for producing sounds that match those produced by various actions
  * taken by the media and camera APIs.  </p>
  *
- * <p>Use this class to play an appropriate camera operation sound when
- * implementing a custom still or video recording mechanism (through the Camera
- * preview callbacks with {@link android.hardware.Camera#setPreviewCallback
- * Camera.setPreviewCallback}, or through GPU processing with {@link
- * android.hardware.Camera#setPreviewTexture Camera.setPreviewTexture}, for
- * example), or when implementing some other camera-like function in your
- * application.</p>
+ * <p>This class is recommended for use with the {@link android.hardware.camera2} API, since the
+ * camera2 API does not play any sounds on its own for any capture or video recording actions.</p>
+ *
+ * <p>With the older {@link android.hardware.Camera} API, use this class to play an appropriate
+ * camera operation sound when implementing a custom still or video recording mechanism (through the
+ * Camera preview callbacks with
+ * {@link android.hardware.Camera#setPreviewCallback Camera.setPreviewCallback}, or through GPU
+ * processing with {@link android.hardware.Camera#setPreviewTexture Camera.setPreviewTexture}, for
+ * example), or when implementing some other camera-like function in your application.</p>
  *
  * <p>There is no need to play sounds when using
  * {@link android.hardware.Camera#takePicture Camera.takePicture} or
@@ -136,10 +138,12 @@
      * {@link android.media.MediaRecorder#start MediaRecorder.start}, and
      * {@link android.media.MediaRecorder#stop MediaRecorder.stop}.</p>
      *
-     * <p>Using this method makes it easy to match the default device sounds
-     * when recording or capturing data through the preview callbacks, or when
-     * implementing custom camera-like features in your
-     * application.</p>
+     * <p>With the {@link android.hardware.camera2 camera2} API, this method can be used to play
+     * standard camera operation sounds with the appropriate system behavior for such sounds.</p>
+
+     * <p>With the older {@link android.hardware.Camera} API, using this method makes it easy to
+     * match the default device sounds when recording or capturing data through the preview
+     * callbacks, or when implementing custom camera-like features in your application.</p>
      *
      * <p>If the sound has not been loaded by {@link #load} before calling play,
      * play will load the sound at the cost of some additional latency before
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index f8c0494..3917bf1 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -114,23 +114,26 @@
     }
 
     /**
-     * Sets a Camera to use for recording. Use this function to switch
-     * quickly between preview and capture mode without a teardown of
-     * the camera object. {@link android.hardware.Camera#unlock()} should be
-     * called before this. Must call before prepare().
+     * Sets a {@link android.hardware.Camera} to use for recording.
+     *
+     * <p>Use this function to switch quickly between preview and capture mode without a teardown of
+     * the camera object. {@link android.hardware.Camera#unlock()} should be called before
+     * this. Must call before {@link #prepare}.</p>
      *
      * @param c the Camera to use for recording
+     * @deprecated Use {@link #getSurface} and the {@link android.hardware.camera2} API instead.
      */
+    @Deprecated
     public native void setCamera(Camera c);
 
     /**
      * Gets the surface to record from when using SURFACE video source.
-     * <p>
-     * Should only be called after prepare(). Frames rendered before start()
-     * will be discarded.
-     * </p>
-     * @throws IllegalStateException if it is called before prepare(), after
-     * stop() or is called when VideoSource is not set to SURFACE.
+     *
+     * <p> May only be called after {@link #prepare}. Frames rendered to the Surface before
+     * {@link #start} will be discarded.</p>
+     *
+     * @throws IllegalStateException if it is called before {@link #prepare}, after
+     * {@link #stop}, or is called when VideoSource is not set to SURFACE.
      * @see android.media.MediaRecorder.VideoSource
      */
     public native Surface getSurface();
@@ -239,7 +242,7 @@
         public static final int DEFAULT = 0;
         /** Camera video source
          * <p>
-         * Using android.hardware.Camera as video source.
+         * Using the {@link android.hardware.Camera} API as video source.
          * </p>
          */
         public static final int CAMERA = 1;
@@ -248,7 +251,7 @@
          * Using a Surface as video source.
          * </p><p>
          * This flag must be used when recording from an
-         * android.hardware.camera2.CameraDevice source.
+         * {@link android.hardware.camera2} API source.
          * </p><p>
          * When using this video source type, use {@link MediaRecorder#getSurface()}
          * to retrieve the surface created by MediaRecorder.
diff --git a/media/java/android/media/tv/ITvInputClient.aidl b/media/java/android/media/tv/ITvInputClient.aidl
index 27360ed..cac8a14 100644
--- a/media/java/android/media/tv/ITvInputClient.aidl
+++ b/media/java/android/media/tv/ITvInputClient.aidl
@@ -35,4 +35,6 @@
     void onSessionEvent(in String name, in Bundle args, int seq);
     void onChannelRetuned(in Uri channelUri, int seq);
     void onTrackInfoChanged(in List<TvTrackInfo> tracks, int seq);
+    void onVideoAvailable(int seq);
+    void onVideoUnavailable(int reason, int seq);
 }
diff --git a/media/java/android/media/tv/ITvInputSessionCallback.aidl b/media/java/android/media/tv/ITvInputSessionCallback.aidl
index 4d72059..e0036e1 100644
--- a/media/java/android/media/tv/ITvInputSessionCallback.aidl
+++ b/media/java/android/media/tv/ITvInputSessionCallback.aidl
@@ -31,4 +31,6 @@
     void onSessionEvent(in String name, in Bundle args);
     void onChannelRetuned(in Uri channelUri);
     void onTrackInfoChanged(in List<TvTrackInfo> tracks);
+    void onVideoAvailable();
+    void onVideoUnavailable(int reason);
 }
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index f1a63ad..867b0db 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -47,6 +47,24 @@
 public final class TvInputManager {
     private static final String TAG = "TvInputManager";
 
+    /**
+     * A generic reason. Video is not available due to an unspecified error.
+     */
+    public static final int VIDEO_UNAVAILABLE_REASON_UNKNOWN = 0;
+    /**
+     * Video is not available because the TV input is tuning to another channel.
+     */
+    public static final int VIDEO_UNAVAILABLE_REASON_TUNE = 1;
+    /**
+     * Video is not available due to the weak TV signal.
+     */
+    public static final int VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL = 2;
+    /**
+     * Video is not available because the TV input stopped the playback temporarily to buffer more
+     * data.
+     */
+    public static final int VIDEO_UNAVAILABLE_REASON_BUFFERING = 3;
+
     private final ITvInputManager mService;
 
     // A mapping from an input to the list of its TvInputListenerRecords.
@@ -108,6 +126,29 @@
         }
 
         /**
+         * This is called when the video is available, so the TV input starts the playback.
+         *
+         * @param session A {@link TvInputManager.Session} associated with this callback
+         */
+        public void onVideoAvailable(Session session) {
+        }
+
+        /**
+         * This is called when the video is not available, so the TV input stops the playback.
+         *
+         * @param session A {@link TvInputManager.Session} associated with this callback
+         * @param reason The reason why the TV input stopped the playback:
+         * <ul>
+         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_UNKNOWN}
+         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_TUNE}
+         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL}
+         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_BUFFERING}
+         * </ul>
+         */
+        public void onVideoUnavailable(Session session, int reason) {
+        }
+
+        /**
          * This is called when a custom event has been sent from this session.
          *
          * @param session A {@link TvInputManager.Session} associated with this callback
@@ -168,6 +209,24 @@
             });
         }
 
+        public void postVideoAvailable() {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mSessionCallback.onVideoAvailable(mSession);
+                }
+            });
+        }
+
+        public void postVideoUnavailable(final int reason) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mSessionCallback.onVideoUnavailable(mSession, reason);
+                }
+            });
+        }
+
         public void postSessionEvent(final String eventType, final Bundle eventArgs) {
             mHandler.post(new Runnable() {
                 @Override
@@ -280,6 +339,30 @@
             }
 
             @Override
+            public void onVideoAvailable(int seq) {
+                synchronized (mSessionCallbackRecordMap) {
+                    SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+                    if (record == null) {
+                        Log.e(TAG, "Callback not found for seq " + seq);
+                        return;
+                    }
+                    record.postVideoAvailable();
+                }
+            }
+
+            @Override
+            public void onVideoUnavailable(int reason, int seq) {
+                synchronized (mSessionCallbackRecordMap) {
+                    SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+                    if (record == null) {
+                        Log.e(TAG, "Callback not found for seq " + seq);
+                        return;
+                    }
+                    record.postVideoUnavailable(reason);
+                }
+            }
+
+            @Override
             public void onSessionEvent(String eventType, Bundle eventArgs, int seq) {
                 synchronized (mSessionCallbackRecordMap) {
                     SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index ba12e2e..a994f54 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -267,6 +267,56 @@
         }
 
         /**
+         * Informs the application that video is available and the playback of the TV stream has
+         * been started.
+         */
+        public void dispatchVideoAvailable() {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        if (DEBUG) Log.d(TAG, "dispatchVideoAvailable");
+                        mSessionCallback.onVideoAvailable();
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "error in dispatchVideoAvailable");
+                    }
+                }
+            });
+        }
+
+        /**
+         * Informs the application that video is not available, so the TV input cannot continue
+         * playing the TV stream.
+         *
+         * @param reason The reason why the TV input stopped the playback:
+         * <ul>
+         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_UNKNOWN}
+         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_TUNE}
+         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL}
+         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_BUFFERING}
+         * </ul>
+         */
+        public void dispatchVideoUnavailable(final int reason) {
+            if (reason != TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN
+                    && reason != TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNE
+                    && reason != TvInputManager.VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL
+                    && reason != TvInputManager.VIDEO_UNAVAILABLE_REASON_BUFFERING) {
+                throw new IllegalArgumentException("Unknown reason: " + reason);
+            }
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        if (DEBUG) Log.d(TAG, "dispatchVideoUnavailable");
+                        mSessionCallback.onVideoUnavailable(reason);
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "error in dispatchVideoUnavailable");
+                    }
+                }
+            });
+        }
+
+        /**
          * Called when the session is released.
          */
         public abstract void onRelease();
@@ -289,7 +339,9 @@
         public abstract void onSetStreamVolume(float volume);
 
         /**
-         * Tunes to a given channel.
+         * Tunes to a given channel. When the video is available, {@link #dispatchVideoAvailable()}
+         * should be called. Also, {@link #dispatchVideoUnavailable(int)} should be called when the
+         * TV input cannot continue playing the given channel.
          *
          * @param channelUri The URI of the channel.
          * @return {@code true} the tuning was successful, {@code false} otherwise.
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 7eb27b6..4ac1ba4 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -525,6 +525,29 @@
         }
 
         /**
+         * This is called when the video is available, so the TV input starts the playback.
+         *
+         * @param inputId The ID of the TV input bound to this view.
+         */
+        public void onVideoAvailable(String inputId) {
+        }
+
+        /**
+         * This is called when the video is not available, so the TV input stops the playback.
+         *
+         * @param inputId The ID of the TV input bound to this view.
+         * @param reason The reason why the TV input stopped the playback:
+         * <ul>
+         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_UNKNOWN}
+         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_TUNE}
+         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL}
+         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_BUFFERING}
+         * </ul>
+         */
+        public void onVideoUnavailable(String inputId, int reason) {
+        }
+
+        /**
          * This is invoked when a custom event from the bound TV input is sent to this view.
          *
          * @param eventType The type of the event.
@@ -625,6 +648,24 @@
             }
         }
 
+        public void onVideoAvailable(Session session) {
+            if (DEBUG) {
+                Log.d(TAG, "onVideoAvailable()");
+            }
+            if (mListener != null) {
+                mListener.onVideoAvailable(mInputId);
+            }
+        }
+
+        public void onVideoUnavailable(Session session, int reason) {
+            if (DEBUG) {
+                Log.d(TAG, "onVideoUnavailable(" + reason + ")");
+            }
+            if (mListener != null) {
+                mListener.onVideoUnavailable(mInputId, reason);
+            }
+        }
+
         @Override
         public void onSessionEvent(TvInputManager.Session session, String eventType,
                 Bundle eventArgs) {
diff --git a/packages/PrintSpooler/res/values/constants.xml b/packages/PrintSpooler/res/values/constants.xml
index c17c73b..faad527 100644
--- a/packages/PrintSpooler/res/values/constants.xml
+++ b/packages/PrintSpooler/res/values/constants.xml
@@ -42,4 +42,7 @@
 
     <integer name="print_option_column_count">2</integer>
 
+    <fraction name="page_selected_alpha">100%</fraction>
+    <fraction name="page_unselected_alpha">50%</fraction>
+
 </resources>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
index d802cd8..e4716da 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
@@ -271,6 +271,10 @@
         onStopLoading();
     }
 
+    public boolean areHistoricalPrintersLoaded() {
+        return mPersistenceManager.mReadHistoryCompleted;
+    }
+
     public void setTrackedPrinter(PrinterId printerId) {
         if (isStarted() && mDiscoverySession != null
                 && mDiscoverySession.isPrinterDiscoveryStarted()) {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
index 8885a7b..eaf268d 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
@@ -90,7 +90,10 @@
     private int mSelectedPageCount;
 
     private float mSelectedPageElevation;
+    private float mSelectedPageAlpha;
+
     private float mUnselectedPageElevation;
+    private float mUnselectedPageAlpha;
 
     private int mPreviewPageMargin;
     private int mPreviewListPadding;
@@ -127,8 +130,13 @@
 
         mSelectedPageElevation = mContext.getResources().getDimension(
                 R.dimen.selected_page_elevation);
+        mSelectedPageAlpha = mContext.getResources().getFraction(
+                R.fraction.page_selected_alpha, 1, 1);
+
         mUnselectedPageElevation = mContext.getResources().getDimension(
                 R.dimen.unselected_page_elevation);
+        mUnselectedPageAlpha = mContext.getResources().getFraction(
+                R.fraction.page_unselected_alpha, 1, 1);
 
         mPreviewPageMargin = mContext.getResources().getDimensionPixelSize(
                 R.dimen.preview_page_margin);
@@ -339,9 +347,11 @@
         if (mConfirmedPagesInDocument.indexOfKey(pageInDocument) >= 0) {
             checkbox.setChecked(true);
             page.setTranslationZ(mSelectedPageElevation);
+            page.setAlpha(mSelectedPageAlpha);
         } else {
             checkbox.setChecked(false);
             page.setTranslationZ(mUnselectedPageElevation);
+            page.setAlpha(mUnselectedPageAlpha);
         }
 
         TextView pageNumberView = (TextView) page.findViewById(R.id.page_number);
@@ -760,11 +770,13 @@
             if (mConfirmedPagesInDocument.indexOfKey(pageInDocument) < 0) {
                 mConfirmedPagesInDocument.put(pageInDocument, null);
                 pageSelector.setChecked(true);
-                page.animate().translationZ(mSelectedPageElevation);
+                page.animate().translationZ(mSelectedPageElevation)
+                        .alpha(mSelectedPageAlpha);
             } else {
                 mConfirmedPagesInDocument.remove(pageInDocument);
                 pageSelector.setChecked(false);
-                page.animate().translationZ(mUnselectedPageElevation);
+                page.animate().translationZ(mUnselectedPageElevation)
+                        .alpha(mUnselectedPageAlpha);
             }
         }
     }
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 5ec2111..5e646ff 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -190,7 +190,7 @@
 
     private MediaSizeComparator mMediaSizeComparator;
 
-    private PrinterInfo mOldCurrentPrinter;
+    private PrinterInfo mCurrentPrinter;
 
     private PageRange[] mSelectedPages;
 
@@ -576,7 +576,7 @@
             }
         }
 
-        PrinterId printerId = mOldCurrentPrinter.getId();
+        PrinterId printerId = mCurrentPrinter.getId();
         final int index = mDestinationSpinnerAdapter.getPrinterIndex(printerId);
         mDestinationSpinner.setSelection(index);
     }
@@ -810,7 +810,7 @@
     }
 
     private void requestCreatePdfFileOrFinish() {
-        if (getCurrentPrinter() == mDestinationSpinnerAdapter.getPdfPrinter()) {
+        if (mCurrentPrinter == mDestinationSpinnerAdapter.getPdfPrinter()) {
             startCreateDocumentActivity();
         } else {
             finish();
@@ -898,19 +898,14 @@
     }
 
     private void addCurrentPrinterToHistory() {
-        PrinterInfo currentPrinter = getCurrentPrinter();
-        if (currentPrinter != null) {
+        if (mCurrentPrinter != null) {
             PrinterId fakePdfPrinterId = mDestinationSpinnerAdapter.getPdfPrinter().getId();
-            if (!currentPrinter.getId().equals(fakePdfPrinterId)) {
-                mPrinterRegistry.addHistoricalPrinter(currentPrinter);
+            if (!mCurrentPrinter.getId().equals(fakePdfPrinterId)) {
+                mPrinterRegistry.addHistoricalPrinter(mCurrentPrinter);
             }
         }
     }
 
-    private PrinterInfo getCurrentPrinter() {
-        return ((PrinterHolder) mDestinationSpinner.getSelectedItem()).printer;
-    }
-
     private void cancelPrint() {
         setState(STATE_PRINT_CANCELED);
         updateOptionsUi();
@@ -970,7 +965,6 @@
         mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
         mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
         mDestinationSpinner.setOnItemSelectedListener(itemSelectedListener);
-        mDestinationSpinner.setSelection(0);
 
         // Media size.
         mMediaSizeSpinnerAdapter = new ArrayAdapter<>(
@@ -1036,16 +1030,14 @@
         @Override
         public void onClick(View view) {
             if (view == mPrintButton) {
-                PrinterInfo currentPrinter = getCurrentPrinter();
-                if (currentPrinter != null) {
+                if (mCurrentPrinter != null) {
                     confirmPrint();
                 } else {
                     cancelPrint();
                 }
             } else if (view == mMoreOptionsButton) {
-                PrinterInfo currentPrinter = getCurrentPrinter();
-                if (currentPrinter != null) {
-                    startAdvancedPrintOptionsActivity(currentPrinter);
+                if (mCurrentPrinter != null) {
+                    startAdvancedPrintOptionsActivity(mCurrentPrinter);
                 }
             }
         }
@@ -1090,8 +1082,7 @@
 
         // If no current printer, or it has no capabilities, or it is not
         // available, we disable all print options except the destination.
-        PrinterInfo currentPrinter = getCurrentPrinter();
-        if (currentPrinter == null || !canPrint(currentPrinter)) {
+        if (mCurrentPrinter == null || !canPrint(mCurrentPrinter)) {
             mCopiesEditText.setEnabled(false);
             mMediaSizeSpinner.setEnabled(false);
             mColorModeSpinner.setEnabled(false);
@@ -1103,7 +1094,7 @@
             return;
         }
 
-        PrinterCapabilitiesInfo capabilities = currentPrinter.getCapabilities();
+        PrinterCapabilitiesInfo capabilities = mCurrentPrinter.getCapabilities();
         PrintAttributes defaultAttributes = capabilities.getDefaults();
 
         // Destination.
@@ -1291,7 +1282,7 @@
         }
 
         // Advanced print options
-        ComponentName serviceName = currentPrinter.getId().getServiceName();
+        ComponentName serviceName = mCurrentPrinter.getId().getServiceName();
         if (!TextUtils.isEmpty(PrintOptionUtils.getAdvancedOptionsActivityName(
                 this, serviceName))) {
             mAdvancedPrintOptionsContainer.setVisibility(View.VISIBLE);
@@ -1302,7 +1293,7 @@
         }
 
         // Print
-        if (mDestinationSpinnerAdapter.getPdfPrinter() != currentPrinter) {
+        if (mDestinationSpinnerAdapter.getPdfPrinter() != mCurrentPrinter) {
             mPrintButton.setImageResource(com.android.internal.R.drawable.ic_print);
         } else {
             mPrintButton.setImageResource(com.android.internal.R.drawable.ic_menu_save);
@@ -1317,7 +1308,7 @@
         }
 
         // Copies
-        if (mDestinationSpinnerAdapter.getPdfPrinter() != currentPrinter) {
+        if (mDestinationSpinnerAdapter.getPdfPrinter() != mCurrentPrinter) {
             mCopiesEditText.setEnabled(true);
         } else {
             mCopiesEditText.setEnabled(false);
@@ -1395,8 +1386,7 @@
     }
 
     public void onPrinterAvailable(PrinterInfo printer) {
-        PrinterInfo currentPrinter = getCurrentPrinter();
-        if (currentPrinter.equals(printer)) {
+        if (mCurrentPrinter.equals(printer)) {
             setState(STATE_CONFIGURING);
             if (canUpdateDocument()) {
                 updateDocument(true, false);
@@ -1407,7 +1397,7 @@
     }
 
     public void onPrinterUnavailable(PrinterInfo printer) {
-        if (getCurrentPrinter().getId().equals(printer.getId())) {
+        if (mCurrentPrinter.getId().equals(printer.getId())) {
             setState(STATE_PRINTER_UNAVAILABLE);
             if (mPrintedDocument.isUpdating()) {
                 mPrintedDocument.cancel();
@@ -1444,15 +1434,14 @@
             return false;
         }
 
-        PrinterInfo currentPrinter = getCurrentPrinter();
-        if (currentPrinter == null) {
+        if (mCurrentPrinter == null) {
             return false;
         }
-        PrinterCapabilitiesInfo capabilities = currentPrinter.getCapabilities();
+        PrinterCapabilitiesInfo capabilities = mCurrentPrinter.getCapabilities();
         if (capabilities == null) {
             return false;
         }
-        if (currentPrinter.getStatus() == PrinterInfo.STATUS_UNAVAILABLE) {
+        if (mCurrentPrinter.getStatus() == PrinterInfo.STATUS_UNAVAILABLE) {
             return false;
         }
 
@@ -1560,8 +1549,13 @@
 
         private final PrinterHolder mFakePdfPrinterHolder;
 
+        private boolean mHistoricalPrintersLoaded;
+
         public DestinationAdapter() {
-            addPrinters(mPrinterHolders, mPrinterRegistry.getPrinters());
+            mHistoricalPrintersLoaded = mPrinterRegistry.areHistoricalPrintersLoaded();
+            if (mHistoricalPrintersLoaded) {
+                addPrinters(mPrinterHolders, mPrinterRegistry.getPrinters());
+            }
             mPrinterRegistry.setOnPrintersChangeListener(this);
             mFakePdfPrinterHolder = new PrinterHolder(createFakePdfPrinter());
         }
@@ -1602,7 +1596,10 @@
 
         @Override
         public int getCount() {
-            return Math.min(mPrinterHolders.size() + 2, DEST_ADAPTER_MAX_ITEM_COUNT);
+            if (mHistoricalPrintersLoaded) {
+                return Math.min(mPrinterHolders.size() + 2, DEST_ADAPTER_MAX_ITEM_COUNT);
+            }
+            return 0;
         }
 
         @Override
@@ -1731,6 +1728,12 @@
             // not shown in the initial short list. Therefore, we have
             // to keep the printer order.
 
+            // Check if historical printers are loaded as this adapter is open
+            // for busyness only if they are. This member is updated here and
+            // when the adapter is created because the historical printers may
+            // be loaded before or after the adapter is created.
+            mHistoricalPrintersLoaded = mPrinterRegistry.areHistoricalPrintersLoaded();
+
             // No old printers - do not bother keeping their position.
             if (mPrinterHolders.isEmpty()) {
                 addPrinters(mPrinterHolders, printers);
@@ -1839,7 +1842,7 @@
     private final class PrintersObserver extends DataSetObserver {
         @Override
         public void onChanged() {
-            PrinterInfo oldPrinterState = mOldCurrentPrinter;
+            PrinterInfo oldPrinterState = mCurrentPrinter;
             if (oldPrinterState == null) {
                 return;
             }
@@ -1927,14 +1930,15 @@
                     return;
                 }
 
-                PrinterInfo currentPrinter = getCurrentPrinter();
+                PrinterHolder currentItem = (PrinterHolder) mDestinationSpinner.getSelectedItem();
+                PrinterInfo currentPrinter = (currentItem != null) ? currentItem.printer : null;
 
                 // Why on earth item selected is called if no selection changed.
-                if (mOldCurrentPrinter == currentPrinter) {
+                if (mCurrentPrinter == currentPrinter) {
                     return;
                 }
 
-                mOldCurrentPrinter = currentPrinter;
+                mCurrentPrinter = currentPrinter;
 
                 PrinterHolder printerHolder = mDestinationSpinnerAdapter.getPrinterHolder(
                         currentPrinter.getId());
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrinterRegistry.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrinterRegistry.java
index 7816d66..a3d7f01 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrinterRegistry.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrinterRegistry.java
@@ -83,6 +83,10 @@
         getPrinterProvider().setTrackedPrinter(printerId);
     }
 
+    public boolean areHistoricalPrintersLoaded() {
+        return getPrinterProvider().areHistoricalPrintersLoaded();
+    }
+
     private FusedPrintersProvider getPrinterProvider() {
         Loader<?> loader = mActivity.getLoaderManager().getLoader(LOADER_ID_PRINTERS_LOADER);
         return (FusedPrintersProvider) loader;
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index 3028100..384cd4a 100644
--- a/services/core/java/com/android/server/hdmi/Constants.java
+++ b/services/core/java/com/android/server/hdmi/Constants.java
@@ -203,8 +203,8 @@
     //       in config.xml to allow customization.
     static final int IRT_MS = 300;
 
-    static final String PROPERTY_PREFERRED_ADDRESS_PLAYBACK = "hdmi_cec.preferred_address.playback";
-    static final String PROPERTY_PREFERRED_ADDRESS_TV = "hdmi_cec.preferred_address.tv";
+    static final String PROPERTY_PREFERRED_ADDRESS_PLAYBACK = "hdmi_cec.prefaddr.playback";
+    static final String PROPERTY_PREFERRED_ADDRESS_TV = "hdmi_cec.prefaddr.tv";
 
     private Constants() { /* cannot be instantiated */ }
 }
diff --git a/services/core/java/com/android/server/hdmi/RoutingControlAction.java b/services/core/java/com/android/server/hdmi/RoutingControlAction.java
index 46dc453..8296f69 100644
--- a/services/core/java/com/android/server/hdmi/RoutingControlAction.java
+++ b/services/core/java/com/android/server/hdmi/RoutingControlAction.java
@@ -114,9 +114,8 @@
                 tv().updateActivePortId(tv().pathToPortId(mCurrentRoutingPath));
             }
         }
-        invokeCallback(HdmiControlManager.RESULT_SUCCESS);
-        finish();
-     }
+        finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
+    }
 
     private int getTvPowerStatus() {
         return tv().getPowerStatus();
@@ -132,6 +131,11 @@
                 mCurrentRoutingPath));
     }
 
+    private void finishWithCallback(int result) {
+        invokeCallback(result);
+        finish();
+    }
+
     @Override
     public void handleTimerEvent(int timeoutState) {
         if (mState != timeoutState || mState == STATE_NONE) {
@@ -152,6 +156,7 @@
                     });
                 } else {
                     tv().updateActivePortId(tv().pathToPortId(mCurrentRoutingPath));
+                    finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
                 }
                 return;
             case STATE_WAIT_FOR_REPORT_POWER_STATUS:
@@ -159,8 +164,7 @@
                     tv().updateActivePortId(tv().pathToPortId(mCurrentRoutingPath));
                     sendSetStreamPath();
                 }
-                invokeCallback(HdmiControlManager.RESULT_SUCCESS);
-                finish();
+                finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
                 return;
         }
     }
@@ -177,6 +181,7 @@
         } else {
             tv().updateActivePortId(tv().pathToPortId(mCurrentRoutingPath));
             sendSetStreamPath();
+            finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
         }
     }
 
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index fac78a9..5e95af4 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -472,6 +472,40 @@
             }
 
             @Override
+            public void onVideoAvailable() {
+                synchronized (mLock) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "onVideoAvailable()");
+                    }
+                    if (sessionState.mSession == null || sessionState.mClient == null) {
+                        return;
+                    }
+                    try {
+                        sessionState.mClient.onVideoAvailable(sessionState.mSeq);
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "error in onVideoAvailable");
+                    }
+                }
+            }
+
+            @Override
+            public void onVideoUnavailable(int reason) {
+                synchronized (mLock) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "onVideoUnavailable(" + reason + ")");
+                    }
+                    if (sessionState.mSession == null || sessionState.mClient == null) {
+                        return;
+                    }
+                    try {
+                        sessionState.mClient.onVideoUnavailable(reason, sessionState.mSeq);
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "error in onVideoUnavailable");
+                    }
+                }
+            }
+
+            @Override
             public void onSessionEvent(String eventType, Bundle eventArgs) {
                 synchronized (mLock) {
                     if (DEBUG) {