Merge "libaudiohal: Add optional "msd" devices factory"
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 629d75a..1793877 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -471,10 +471,6 @@
      * Otherwise will always be present.</p>
      * <p>The maximum number of regions supported by the device is determined by the value
      * of android.control.maxRegionsAe.</p>
-     * <p>The data representation is int[5 * area_count].
-     * Every five elements represent a metering region of (xmin, ymin, xmax, ymax, weight).
-     * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
-     * ymax.</p>
      * <p>The coordinate system is based on the active pixel array,
      * with (0,0) being the top-left pixel in the active pixel array, and
      * (ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE.width - 1,
@@ -495,6 +491,10 @@
      * region and output only the intersection rectangle as the metering region in the result
      * metadata.  If the region is entirely outside the crop region, it will be ignored and
      * not reported in the result metadata.</p>
+     * <p>The data representation is <code>int[5 * area_count]</code>.
+     * Every five elements represent a metering region of <code>(xmin, ymin, xmax, ymax, weight)</code>.
+     * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
+     * ymax.</p>
      *
      * @see ACAMERA_SCALER_CROP_REGION
      * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -633,10 +633,6 @@
      * Otherwise will always be present.</p>
      * <p>The maximum number of focus areas supported by the device is determined by the value
      * of android.control.maxRegionsAf.</p>
-     * <p>The data representation is int[5 * area_count].
-     * Every five elements represent a metering region of (xmin, ymin, xmax, ymax, weight).
-     * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
-     * ymax.</p>
      * <p>The coordinate system is based on the active pixel array,
      * with (0,0) being the top-left pixel in the active pixel array, and
      * (ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE.width - 1,
@@ -657,6 +653,10 @@
      * region and output only the intersection rectangle as the metering region in the result
      * metadata. If the region is entirely outside the crop region, it will be ignored and
      * not reported in the result metadata.</p>
+     * <p>The data representation is <code>int[5 * area_count]</code>.
+     * Every five elements represent a metering region of <code>(xmin, ymin, xmax, ymax, weight)</code>.
+     * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
+     * ymax.</p>
      *
      * @see ACAMERA_SCALER_CROP_REGION
      * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -791,10 +791,6 @@
      * Otherwise will always be present.</p>
      * <p>The maximum number of regions supported by the device is determined by the value
      * of android.control.maxRegionsAwb.</p>
-     * <p>The data representation is int[5 * area_count].
-     * Every five elements represent a metering region of (xmin, ymin, xmax, ymax, weight).
-     * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
-     * ymax.</p>
      * <p>The coordinate system is based on the active pixel array,
      * with (0,0) being the top-left pixel in the active pixel array, and
      * (ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE.width - 1,
@@ -815,6 +811,10 @@
      * region and output only the intersection rectangle as the metering region in the result
      * metadata.  If the region is entirely outside the crop region, it will be ignored and
      * not reported in the result metadata.</p>
+     * <p>The data representation is <code>int[5 * area_count]</code>.
+     * Every five elements represent a metering region of <code>(xmin, ymin, xmax, ymax, weight)</code>.
+     * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
+     * ymax.</p>
      *
      * @see ACAMERA_SCALER_CROP_REGION
      * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -885,11 +885,10 @@
      * <p>When set to AUTO, the individual algorithm controls in
      * ACAMERA_CONTROL_* are in effect, such as ACAMERA_CONTROL_AF_MODE.</p>
      * <p>When set to USE_SCENE_MODE, the individual controls in
-     * ACAMERA_CONTROL_* are mostly disabled, and the camera device implements
-     * one of the scene mode settings (such as ACTION, SUNSET, or PARTY)
-     * as it wishes. The camera device scene mode 3A settings are provided by
-     * capture results {@link ACameraMetadata} from
-     * {@link ACameraCaptureSession_captureCallback_result}.</p>
+     * ACAMERA_CONTROL_* are mostly disabled, and the camera device
+     * implements one of the scene mode settings (such as ACTION,
+     * SUNSET, or PARTY) as it wishes. The camera device scene mode
+     * 3A settings are provided by {@link ACameraCaptureSession_captureCallback_result capture results}.</p>
      * <p>When set to OFF_KEEP_STATE, it is similar to OFF mode, the only difference
      * is that this frame will not be used by camera device background 3A statistics
      * update, as if this frame is never captured. This mode can be used in the scenario
@@ -1043,20 +1042,18 @@
      * <p>For constant-framerate recording, for each normal
      * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a>, that is, a
      * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a> that has
-     * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#quality">quality</a>
-     * in the range [
-     * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#QUALITY_LOW">QUALITY_LOW</a>,
-     * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#QUALITY_2160P">QUALITY_2160P</a>],
-     * if the profile is supported by the device and has
-     * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#videoFrameRate">videoFrameRate</a>
-     * <code>x</code>, this list will always include (<code>x</code>,<code>x</code>).</p>
+     * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#quality">quality</a> in
+     * the range [<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#QUALITY_LOW">QUALITY_LOW</a>,
+     * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#QUALITY_2160P">QUALITY_2160P</a>], if the profile is
+     * supported by the device and has
+     * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#videoFrameRate">videoFrameRate</a> <code>x</code>, this list will
+     * always include (<code>x</code>,<code>x</code>).</p>
      * </li>
      * <li>
      * <p>Also, a camera device must either not support any
      * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a>,
      * or support at least one
-     * normal <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a>
-     * that has
+     * normal <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a> that has
      * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#videoFrameRate">videoFrameRate</a> <code>x</code> &gt;= 24.</p>
      * </li>
      * </ul>
@@ -1619,13 +1616,13 @@
      * compared to previous regular requests. enableZsl does not affect requests with other
      * capture intents.</p>
      * <p>For example, when requests are submitted in the following order:
-     *   Request A: enableZsl is <code>true</code>, ACAMERA_CONTROL_CAPTURE_INTENT is PREVIEW
-     *   Request B: enableZsl is <code>true</code>, ACAMERA_CONTROL_CAPTURE_INTENT is STILL_CAPTURE</p>
+     *   Request A: enableZsl is ON, ACAMERA_CONTROL_CAPTURE_INTENT is PREVIEW
+     *   Request B: enableZsl is ON, ACAMERA_CONTROL_CAPTURE_INTENT is STILL_CAPTURE</p>
      * <p>The output images for request B may have contents captured before the output images for
      * request A, and the result metadata for request B may be older than the result metadata for
      * request A.</p>
-     * <p>Note that when enableZsl is <code>true</code>, it is not guaranteed to get output images captured in the
-     * past for requests with STILL_CAPTURE capture intent.</p>
+     * <p>Note that when enableZsl is <code>true</code>, it is not guaranteed to get output images captured in
+     * the past for requests with STILL_CAPTURE capture intent.</p>
      * <p>For applications targeting SDK versions O and newer, the value of enableZsl in
      * TEMPLATE_STILL_CAPTURE template may be <code>true</code>. The value in other templates is always
      * <code>false</code> if present.</p>
@@ -1959,14 +1956,14 @@
      * <p>When an ACAMERA_JPEG_ORIENTATION of non-zero degree is requested,
      * the camera device will handle thumbnail rotation in one of the following ways:</p>
      * <ul>
-     * <li>Set the
-     *   <a href="https://developer.android.com/reference/android/media/ExifInterface.html#TAG_ORIENTATION">EXIF orientation flag</a>
+     * <li>Set the <a href="https://developer.android.com/reference/android/media/ExifInterface.html#TAG_ORIENTATION">EXIF orientation flag</a>
      *   and keep jpeg and thumbnail image data unrotated.</li>
      * <li>Rotate the jpeg and thumbnail image data and not set
-     *   <a href="https://developer.android.com/reference/android/media/ExifInterface.html#TAG_ORIENTATION">EXIF orientation flag</a>.
-     *   In this case, LIMITED or FULL hardware level devices will report rotated thumnail size
-     *   in capture result, so the width and height will be interchanged if 90 or 270 degree
-     *   orientation is requested. LEGACY device will always report unrotated thumbnail size.</li>
+     *   <a href="https://developer.android.com/reference/android/media/ExifInterface.html#TAG_ORIENTATION">EXIF orientation flag</a>. In this
+     *   case, LIMITED or FULL hardware level devices will report rotated thumnail size in
+     *   capture result, so the width and height will be interchanged if 90 or 270 degree
+     *   orientation is requested. LEGACY device will always report unrotated thumbnail
+     *   size.</li>
      * </ul>
      *
      * @see ACAMERA_JPEG_ORIENTATION
@@ -2218,9 +2215,8 @@
      * <p>The position of the camera device's lens optical center,
      * as a three-dimensional vector <code>(x,y,z)</code>, relative to the
      * optical center of the largest camera device facing in the
-     * same direction as this camera, in the
-     * <a href="https://developer.android.com/reference/android/hardware/SensorEvent.html">Android sensor coordinate axes</a>.
-     * Note that only the axis definitions are shared with
+     * same direction as this camera, in the <a href="https://developer.android.com/reference/android/hardware/SensorEvent.html">Android sensor coordinate
+     * axes</a>. Note that only the axis definitions are shared with
      * the sensor coordinate system, but not the origin.</p>
      * <p>If this device is the largest or only camera device with a
      * given facing, then this position will be <code>(0, 0, 0)</code>; a
@@ -2662,11 +2658,12 @@
      * into the 3 stream types as below:</p>
      * <ul>
      * <li>Processed (but stalling): any non-RAW format with a stallDurations &gt; 0.
-     *   Typically {@link AIMAGE_FORMAT_JPEG} format.</li>
-     * <li>Raw formats: {@link AIMAGE_FORMAT_RAW16}, {@link AIMAGE_FORMAT_RAW10}, or
-     *   {@link AIMAGE_FORMAT_RAW12}.</li>
-     * <li>Processed (but not-stalling): any non-RAW format without a stall duration.
-     *   Typically {@link AIMAGE_FORMAT_YUV_420_888}.</li>
+     *   Typically {@link AIMAGE_FORMAT_JPEG JPEG format}.</li>
+     * <li>Raw formats: {@link AIMAGE_FORMAT_RAW16 RAW_SENSOR}, {@link AIMAGE_FORMAT_RAW10 RAW10}, or
+     *   {@link AIMAGE_FORMAT_RAW12 RAW12}.</li>
+     * <li>Processed (but not-stalling): any non-RAW format without a stall duration.  Typically
+     *   {@link AIMAGE_FORMAT_YUV_420_888 YUV_420_888},
+     *   <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#NV21">NV21</a>, or <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YV12">YV12</a>.</li>
      * </ul>
      *
      * @see ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS
@@ -2787,7 +2784,7 @@
             ACAMERA_REQUEST_START + 12,
     /**
      * <p>A list of all keys that the camera device has available
-     * to use with {@link ACaptureRequest}.</p>
+     * to use with {@link ACaptureRequest }.</p>
      *
      * <p>Type: int32[n]</p>
      *
@@ -2809,9 +2806,7 @@
     ACAMERA_REQUEST_AVAILABLE_REQUEST_KEYS =                    // int32[n]
             ACAMERA_REQUEST_START + 13,
     /**
-     * <p>A list of all keys that the camera device has available
-     * to query with {@link ACameraMetadata} from
-     * {@link ACameraCaptureSession_captureCallback_result}.</p>
+     * <p>A list of all keys that the camera device has available to use with {@link ACameraCaptureSession_captureCallback_result }.</p>
      *
      * <p>Type: int32[n]</p>
      *
@@ -2842,9 +2837,7 @@
     ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS =                     // int32[n]
             ACAMERA_REQUEST_START + 14,
     /**
-     * <p>A list of all keys that the camera device has available
-     * to query with {@link ACameraMetadata} from
-     * {@link ACameraManager_getCameraCharacteristics}.</p>
+     * <p>A list of all keys that the camera device has available to use with {@link ACameraManager_getCameraCharacteristics }.</p>
      *
      * <p>Type: int32[n]</p>
      *
@@ -2876,7 +2869,6 @@
      * </ul></p>
      *
      * <p>This control can be used to implement digital zoom.</p>
-     * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
      * <p>The crop region coordinate system is based off
      * ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE, with <code>(0, 0)</code> being the
      * top-left corner of the sensor active array.</p>
@@ -2906,6 +2898,7 @@
      * for rounding and other hardware requirements; the final
      * crop region used will be included in the output capture
      * result.</p>
+     * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
      *
      * @see ACAMERA_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
      * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -3061,13 +3054,14 @@
      * ignored).</p>
      * <p>The following formats may always have a stall duration:</p>
      * <ul>
-     * <li>{@link AIMAGE_FORMAT_JPEG}</li>
-     * <li>{@link AIMAGE_FORMAT_RAW16}</li>
+     * <li>{@link AIMAGE_FORMAT_JPEG }</li>
+     * <li>{@link AIMAGE_FORMAT_RAW16 }</li>
      * </ul>
      * <p>The following formats will never have a stall duration:</p>
      * <ul>
-     * <li>{@link AIMAGE_FORMAT_YUV_420_888}</li>
-     * <li>{@link AIMAGE_FORMAT_RAW10}</li>
+     * <li>{@link AIMAGE_FORMAT_YUV_420_888 }</li>
+     * <li>{@link AIMAGE_FORMAT_RAW10 }</li>
+     * <li>{@link AIMAGE_FORMAT_RAW12 }</li>
      * </ul>
      * <p>All other formats may or may not have an allowed stall duration on
      * a per-capability basis; refer to ACAMERA_REQUEST_AVAILABLE_CAPABILITIES
@@ -3177,39 +3171,29 @@
      * can run concurrently to the rest of the camera pipeline, but
      * cannot process more than 1 capture at a time.</li>
      * </ul>
-     * <p>The necessary information for the application, given the model above,
-     * is provided via
-     * {@link ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS}.
-     * These are used to determine the maximum frame rate / minimum frame
-     * duration that is possible for a given stream configuration.</p>
+     * <p>The necessary information for the application, given the model above, is provided via
+     * {@link ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS }.
+     * These are used to determine the maximum frame rate / minimum frame duration that is
+     * possible for a given stream configuration.</p>
      * <p>Specifically, the application can use the following rules to
      * determine the minimum frame duration it can request from the camera
      * device:</p>
      * <ol>
-     * <li>Let the set of currently configured input/output streams
-     * be called <code>S</code>.</li>
-     * <li>Find the minimum frame durations for each stream in <code>S</code>, by looking
-     * it up in {@link ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS}
-     * (with its respective size/format). Let this set of frame durations be
-     * called <code>F</code>.</li>
-     * <li>For any given request <code>R</code>, the minimum frame duration allowed
-     * for <code>R</code> is the maximum out of all values in <code>F</code>. Let the streams
-     * used in <code>R</code> be called <code>S_r</code>.</li>
+     * <li>Let the set of currently configured input/output streams be called <code>S</code>.</li>
+     * <li>Find the minimum frame durations for each stream in <code>S</code>, by looking it up in {@link ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS }
+     * (with its respective size/format). Let this set of frame durations be called <code>F</code>.</li>
+     * <li>For any given request <code>R</code>, the minimum frame duration allowed for <code>R</code> is the maximum
+     * out of all values in <code>F</code>. Let the streams used in <code>R</code> be called <code>S_r</code>.</li>
      * </ol>
-     * <p>If none of the streams in <code>S_r</code> have a stall time (listed in {@link
-     * ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS}
-     * using its respective size/format), then the frame duration in <code>F</code>
-     * determines the steady state frame rate that the application will get
-     * if it uses <code>R</code> as a repeating request. Let this special kind of
-     * request be called <code>Rsimple</code>.</p>
-     * <p>A repeating request <code>Rsimple</code> can be <em>occasionally</em> interleaved
-     * by a single capture of a new request <code>Rstall</code> (which has at least
-     * one in-use stream with a non-0 stall time) and if <code>Rstall</code> has the
-     * same minimum frame duration this will not cause a frame rate loss
-     * if all buffers from the previous <code>Rstall</code> have already been
-     * delivered.</p>
-     * <p>For more details about stalling, see
-     * {@link ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS}.</p>
+     * <p>If none of the streams in <code>S_r</code> have a stall time (listed in {@link ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS }
+     * using its respective size/format), then the frame duration in <code>F</code> determines the steady
+     * state frame rate that the application will get if it uses <code>R</code> as a repeating request. Let
+     * this special kind of request be called <code>Rsimple</code>.</p>
+     * <p>A repeating request <code>Rsimple</code> can be <em>occasionally</em> interleaved by a single capture of a
+     * new request <code>Rstall</code> (which has at least one in-use stream with a non-0 stall time) and if
+     * <code>Rstall</code> has the same minimum frame duration this will not cause a frame rate loss if all
+     * buffers from the previous <code>Rstall</code> have already been delivered.</p>
+     * <p>For more details about stalling, see {@link ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS }.</p>
      * <p>This control is only effective if ACAMERA_CONTROL_AE_MODE or ACAMERA_CONTROL_MODE is set to
      * OFF; otherwise the auto-exposure algorithm will override this value.</p>
      *
@@ -3567,14 +3551,12 @@
      * timestamps for other captures from the same camera device, but are
      * not guaranteed to be comparable to any other time source.</p>
      * <p>When ACAMERA_SENSOR_INFO_TIMESTAMP_SOURCE <code>==</code> REALTIME, the
-     * timestamps measure time in the same timebase as
-     * <a href="https://developer.android.com/reference/android/os/SystemClock.html#elapsedRealtimeNanos">elapsedRealtimeNanos</a>
-     * (or CLOCK_BOOTTIME), and they can
+     * timestamps measure time in the same timebase as <a href="https://developer.android.com/reference/android/os/SystemClock.html#elapsedRealtimeNanos">SystemClock#elapsedRealtimeNanos</a>, and they can
      * be compared to other timestamps from other subsystems that
      * are using that base.</p>
      * <p>For reprocessing, the timestamp will match the start of exposure of
-     * the input image, i.e. {@link CaptureResult#SENSOR_TIMESTAMP the
-     * timestamp} in the TotalCaptureResult that was used to create the
+     * the input image, i.e. <a href="https://developer.android.com/reference/CaptureResult.html#SENSOR_TIMESTAMP">the
+     * timestamp</a> in the TotalCaptureResult that was used to create the
      * reprocess capture request.</p>
      *
      * @see ACAMERA_SENSOR_INFO_TIMESTAMP_SOURCE
@@ -3775,7 +3757,6 @@
      * optically shielded pixel areas. By blocking light, these pixels
      * provides a reliable black reference for black level compensation
      * in active array region.</p>
-     * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
      * <p>This key provides a list of disjoint rectangles specifying the
      * regions of optically shielded (with metal shield) black pixel
      * regions if the camera device is capable of reading out these black
@@ -3785,6 +3766,7 @@
      * black level of each captured raw images.</p>
      * <p>When this key is reported, the ACAMERA_SENSOR_DYNAMIC_BLACK_LEVEL and
      * ACAMERA_SENSOR_DYNAMIC_WHITE_LEVEL will also be reported.</p>
+     * <p>The data representation is <code>int[4]</code>, which maps to <code>(left, top, width, height)</code>.</p>
      *
      * @see ACAMERA_SENSOR_BLACK_LEVEL_PATTERN
      * @see ACAMERA_SENSOR_DYNAMIC_BLACK_LEVEL
@@ -3825,9 +3807,8 @@
      * layout key (see ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT), i.e. the
      * nth value given corresponds to the black level offset for the nth
      * color channel listed in the CFA.</p>
-     * <p>This key will be available if ACAMERA_SENSOR_OPTICAL_BLACK_REGIONS is
-     * available or the camera device advertises this key via
-     * {@link ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS}.</p>
+     * <p>This key will be available if ACAMERA_SENSOR_OPTICAL_BLACK_REGIONS is available or the
+     * camera device advertises this key via {@link ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS }.</p>
      *
      * @see ACAMERA_SENSOR_BLACK_LEVEL_PATTERN
      * @see ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
@@ -3853,7 +3834,7 @@
      * estimated white level for each frame.</p>
      * <p>This key will be available if ACAMERA_SENSOR_OPTICAL_BLACK_REGIONS is
      * available or the camera device advertises this key via
-     * {@link ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS}.</p>
+     * {@link ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS }.</p>
      *
      * @see ACAMERA_SENSOR_BLACK_LEVEL_PATTERN
      * @see ACAMERA_SENSOR_INFO_WHITE_LEVEL
@@ -3882,13 +3863,13 @@
      * <p>This rectangle is defined relative to the full pixel array; (0,0) is the top-left of
      * the full pixel array, and the size of the full pixel array is given by
      * ACAMERA_SENSOR_INFO_PIXEL_ARRAY_SIZE.</p>
-     * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
      * <p>The coordinate system for most other keys that list pixel coordinates, including
      * ACAMERA_SCALER_CROP_REGION, is defined relative to the active array rectangle given in
      * this field, with <code>(0, 0)</code> being the top-left of this rectangle.</p>
      * <p>The active array may be smaller than the full pixel array, since the full array may
      * include black calibration pixels or other inactive regions, and geometric correction
      * resulting in scaling or cropping may have been applied.</p>
+     * <p>The data representation is <code>int[4]</code>, which maps to <code>(left, top, width, height)</code>.</p>
      *
      * @see ACAMERA_SCALER_CROP_REGION
      * @see ACAMERA_SENSOR_INFO_PIXEL_ARRAY_SIZE
@@ -3960,8 +3941,7 @@
      * <p>Attempting to use frame durations beyond the maximum will result in the frame
      * duration being clipped to the maximum. See that control for a full definition of frame
      * durations.</p>
-     * <p>Refer to {@link
-     * ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS}
+     * <p>Refer to {@link ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS }
      * for the minimum frame duration values.</p>
      */
     ACAMERA_SENSOR_INFO_MAX_FRAME_DURATION =                    // int64
@@ -4000,9 +3980,9 @@
      * the raw buffers produced by this sensor.</p>
      * <p>If a camera device supports raw sensor formats, either this or
      * ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE is the maximum dimensions for the raw
-     * output formats listed in ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS (this depends on
-     * whether or not the image sensor returns buffers containing pixels that are not
-     * part of the active array region for blacklevel calibration or other purposes).</p>
+     * output formats listed in {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS }
+     * (this depends on whether or not the image sensor returns buffers containing pixels that
+     * are not part of the active array region for blacklevel calibration or other purposes).</p>
      * <p>Some parts of the full pixel array may not receive light from the scene,
      * or be otherwise inactive.  The ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE key
      * defines the rectangle of active pixels that will be included in processed image
@@ -4092,7 +4072,6 @@
      *   <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
      * </ul></p>
      *
-     * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
      * <p>This is the rectangle representing the size of the active region of the sensor (i.e.
      * the region that actually receives light from the scene) before any geometric correction
      * has been applied, and should be treated as the active region rectangle for any of the
@@ -4143,6 +4122,7 @@
      * ACAMERA_SENSOR_INFO_PIXEL_ARRAY_SIZE.</p>
      * <p>The pre-correction active array may be smaller than the full pixel array, since the
      * full array may include black calibration pixels or other inactive regions.</p>
+     * <p>The data representation is <code>int[4]</code>, which maps to <code>(left, top, width, height)</code>.</p>
      *
      * @see ACAMERA_LENS_RADIAL_DISTORTION
      * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -4302,10 +4282,10 @@
      *   <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
      * </ul></p>
      *
-     * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
      * <p>The coordinate system is that of ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE, with
      * <code>(0, 0)</code> being the top-left pixel of the active array.</p>
-     * <p>Only available if ACAMERA_STATISTICS_FACE_DETECT_MODE != OFF</p>
+     * <p>Only available if ACAMERA_STATISTICS_FACE_DETECT_MODE != OFF
+     * The data representation is <code>int[4]</code>, which maps to <code>(left, top, width, height)</code>.</p>
      *
      * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
      * @see ACAMERA_STATISTICS_FACE_DETECT_MODE
@@ -4832,7 +4812,7 @@
      * <p>See the individual level enums for full descriptions of the supported capabilities.  The
      * ACAMERA_REQUEST_AVAILABLE_CAPABILITIES entry describes the device's capabilities at a
      * finer-grain level, if needed. In addition, many controls have their available settings or
-     * ranges defined in individual metadata tag entries in this document.</p>
+     * ranges defined in individual entries from {@link ACameraManager_getCameraCharacteristics }.</p>
      * <p>Some features are not part of any particular hardware level or capability and must be
      * queried separately. These include:</p>
      * <ul>
@@ -6157,13 +6137,13 @@
     ACAMERA_EDGE_MODE_HIGH_QUALITY                                   = 2,
 
     /**
-     * <p>Edge enhancement is applied at different levels for different output streams,
-     * based on resolution. Streams at maximum recording resolution (see {@link
-     * ACameraDevice_createCaptureSession}) or below have
-     * edge enhancement applied, while higher-resolution streams have no edge enhancement
-     * applied. The level of edge enhancement for low-resolution streams is tuned so that
-     * frame rate is not impacted, and the quality is equal to or better than FAST (since it
-     * is only applied to lower-resolution outputs, quality may improve from FAST).</p>
+     * <p>Edge enhancement is applied at different
+     * levels for different output streams, based on resolution. Streams at maximum recording
+     * resolution (see {@link ACameraDevice_createCaptureSession })
+     * or below have edge enhancement applied, while higher-resolution streams have no edge
+     * enhancement applied. The level of edge enhancement for low-resolution streams is tuned
+     * so that frame rate is not impacted, and the quality is equal to or better than FAST
+     * (since it is only applied to lower-resolution outputs, quality may improve from FAST).</p>
      * <p>This mode is intended to be used by applications operating in a zero-shutter-lag mode
      * with YUV or PRIVATE reprocessing, where the application continuously captures
      * high-resolution intermediate buffers into a circular buffer, from which a final image is
@@ -6412,13 +6392,12 @@
 
     /**
      * <p>Noise reduction is applied at different levels for different output streams,
-     * based on resolution. Streams at maximum recording resolution (see {@link
-     * ACameraDevice_createCaptureSession}) or below have noise
-     * reduction applied, while higher-resolution streams have MINIMAL (if supported) or no
-     * noise reduction applied (if MINIMAL is not supported.) The degree of noise reduction
-     * for low-resolution streams is tuned so that frame rate is not impacted, and the quality
-     * is equal to or better than FAST (since it is only applied to lower-resolution outputs,
-     * quality may improve from FAST).</p>
+     * based on resolution. Streams at maximum recording resolution (see {@link ACameraDevice_createCaptureSession })
+     * or below have noise reduction applied, while higher-resolution streams have MINIMAL (if
+     * supported) or no noise reduction applied (if MINIMAL is not supported.) The degree of
+     * noise reduction for low-resolution streams is tuned so that frame rate is not impacted,
+     * and the quality is equal to or better than FAST (since it is only applied to
+     * lower-resolution outputs, quality may improve from FAST).</p>
      * <p>This mode is intended to be used by applications operating in a zero-shutter-lag mode
      * with YUV or PRIVATE reprocessing, where the application continuously captures
      * high-resolution intermediate buffers into a circular buffer, from which a final image is
@@ -6635,18 +6614,16 @@
      * to FAST. Additionally, maximum-resolution images can be captured at &gt;= 10 frames
      * per second.  Here, 'high resolution' means at least 8 megapixels, or the maximum
      * resolution of the device, whichever is smaller.</p>
-     * <p>More specifically, this means that at least one output {@link
-     * AIMAGE_FORMAT_YUV_420_888} size listed in
-     * {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS} is larger or equal to the
-     * 'high resolution' defined above, and can be captured at at least 20 fps.
-     * For the largest {@link AIMAGE_FORMAT_YUV_420_888} size listed in
-     * {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS}, camera device can capture this
-     * size for at least 10 frames per second.
-     * Also the ACAMERA_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES entry lists at least one FPS range
-     * where the minimum FPS is &gt;= 1 / minimumFrameDuration for the largest YUV_420_888 size.</p>
-     * <p>If the device supports the {@link AIMAGE_FORMAT_RAW10}, {@link
-     * AIMAGE_FORMAT_RAW12}, then those can also be captured at the same rate
-     * as the maximum-size YUV_420_888 resolution is.</p>
+     * <p>More specifically, this means that at least one output {@link AIMAGE_FORMAT_YUV_420_888 } size listed in
+     * {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS }
+     * is larger or equal to the 'high resolution' defined above, and can be captured at at
+     * least 20 fps.  For the largest {@link AIMAGE_FORMAT_YUV_420_888 } size listed in
+     * {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS },
+     * camera device can capture this size for at least 10 frames per second.  Also the
+     * ACAMERA_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES entry lists at least one FPS range where
+     * the minimum FPS is &gt;= 1 / minimumFrameDuration for the largest YUV_420_888 size.</p>
+     * <p>If the device supports the {@link AIMAGE_FORMAT_RAW10 }, {@link AIMAGE_FORMAT_RAW12 }, then those can also be
+     * captured at the same rate as the maximum-size YUV_420_888 resolution is.</p>
      * <p>In addition, the ACAMERA_SYNC_MAX_LATENCY field is guaranted to have a value between 0
      * and 4, inclusive. ACAMERA_CONTROL_AE_LOCK_AVAILABLE and ACAMERA_CONTROL_AWB_LOCK_AVAILABLE
      * are also guaranteed to be <code>true</code> so burst capture with these two locks ON yields
@@ -6663,13 +6640,13 @@
      * <p>The camera device can produce depth measurements from its field of view.</p>
      * <p>This capability requires the camera device to support the following:</p>
      * <ul>
-     * <li>{@link AIMAGE_FORMAT_DEPTH16} is supported as an output format.</li>
-     * <li>{@link AIMAGE_FORMAT_DEPTH_POINT_CLOUD} is optionally supported as an
-     *   output format.</li>
-     * <li>This camera device, and all camera devices with the same ACAMERA_LENS_FACING,
-     *   will list the following calibration entries in {@link ACameraMetadata} from both
-     *   {@link ACameraManager_getCameraCharacteristics} and
-     *   {@link ACameraCaptureSession_captureCallback_result}:<ul>
+     * <li>{@link AIMAGE_FORMAT_DEPTH16 } is supported as
+     *   an output format.</li>
+     * <li>{@link AIMAGE_FORMAT_DEPTH_POINT_CLOUD } is
+     *   optionally supported as an output format.</li>
+     * <li>This camera device, and all camera devices with the same ACAMERA_LENS_FACING, will
+     *   list the following calibration metadata entries in both {@link ACameraManager_getCameraCharacteristics }
+     *   and {@link ACameraCaptureSession_captureCallback_result }:<ul>
      * <li>ACAMERA_LENS_POSE_TRANSLATION</li>
      * <li>ACAMERA_LENS_POSE_ROTATION</li>
      * <li>ACAMERA_LENS_INTRINSIC_CALIBRATION</li>
@@ -6683,8 +6660,7 @@
      * </ul>
      * <p>Generally, depth output operates at a slower frame rate than standard color capture,
      * so the DEPTH16 and DEPTH_POINT_CLOUD formats will commonly have a stall duration that
-     * should be accounted for (see
-     * {@link ACAMERA_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS}).
+     * should be accounted for (see {@link ACAMERA_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS }).
      * On a device that supports both depth and color-based output, to enable smooth preview,
      * using a repeating burst is recommended, where a depth-output target is only included
      * once every N frames, where N is the ratio between preview output rate and depth output
@@ -6918,8 +6894,8 @@
 
     /**
      * <p>Timestamps from ACAMERA_SENSOR_TIMESTAMP are in the same timebase as
-     * <a href="https://developer.android.com/reference/android/os/SystemClock.html#elapsedRealtimeNanos">elapsedRealtimeNanos</a>
-     * (or CLOCK_BOOTTIME), and they can be compared to other timestamps using that base.</p>
+     * <a href="https://developer.android.com/reference/android/os/SystemClock.html#elapsedRealtimeNanos">SystemClock#elapsedRealtimeNanos</a>,
+     * and they can be compared to other timestamps using that base.</p>
      *
      * @see ACAMERA_SENSOR_TIMESTAMP
      */
@@ -7104,7 +7080,7 @@
      * <p>This camera device does not have enough capabilities to qualify as a <code>FULL</code> device or
      * better.</p>
      * <p>Only the stream configurations listed in the <code>LEGACY</code> and <code>LIMITED</code> tables in the
-     * {@link ACameraDevice_createCaptureSession} documentation are guaranteed to be supported.</p>
+     * {@link ACameraDevice_createCaptureSession createCaptureSession} documentation are guaranteed to be supported.</p>
      * <p>All <code>LIMITED</code> devices support the <code>BACKWARDS_COMPATIBLE</code> capability, indicating basic
      * support for color image capture. The only exception is that the device may
      * alternatively support only the <code>DEPTH_OUTPUT</code> capability, if it can only output depth
@@ -7130,7 +7106,7 @@
     /**
      * <p>This camera device is capable of supporting advanced imaging applications.</p>
      * <p>The stream configurations listed in the <code>FULL</code>, <code>LEGACY</code> and <code>LIMITED</code> tables in the
-     * {@link ACameraDevice_createCaptureSession} documentation are guaranteed to be supported.</p>
+     * {@link ACameraDevice_createCaptureSession createCaptureSession} documentation are guaranteed to be supported.</p>
      * <p>A <code>FULL</code> device will support below capabilities:</p>
      * <ul>
      * <li><code>BURST_CAPTURE</code> capability (ACAMERA_REQUEST_AVAILABLE_CAPABILITIES contains
@@ -7157,8 +7133,7 @@
 
     /**
      * <p>This camera device is running in backward compatibility mode.</p>
-     * <p>Only the stream configurations listed in the <code>LEGACY</code> table in the {@link
-     * ACameraDevice_createCaptureSession} documentation are supported.</p>
+     * <p>Only the stream configurations listed in the <code>LEGACY</code> table in the {@link ACameraDevice_createCaptureSession createCaptureSession} documentation are supported.</p>
      * <p>A <code>LEGACY</code> device does not support per-frame control, manual sensor control, manual
      * post-processing, arbitrary cropping regions, and has relaxed performance constraints.
      * No additional capabilities beyond <code>BACKWARD_COMPATIBLE</code> will ever be listed by a
@@ -7179,9 +7154,7 @@
      * <p>This camera device is capable of YUV reprocessing and RAW data capture, in addition to
      * FULL-level capabilities.</p>
      * <p>The stream configurations listed in the <code>LEVEL_3</code>, <code>RAW</code>, <code>FULL</code>, <code>LEGACY</code> and
-     * <code>LIMITED</code> tables in the {@link
-     * ACameraDevice_createCaptureSession}
-     * documentation are guaranteed to be supported.</p>
+     * <code>LIMITED</code> tables in the {@link ACameraDevice_createCaptureSession createCaptureSession} documentation are guaranteed to be supported.</p>
      * <p>The following additional capabilities are guaranteed to be supported:</p>
      * <ul>
      * <li><code>YUV_REPROCESSING</code> capability (ACAMERA_REQUEST_AVAILABLE_CAPABILITIES contains
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 283bcb4..7623d6d 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -7,16 +7,16 @@
         jpeg.cpp        \
         SineSource.cpp
 
-LOCAL_HEADER_LIBRARIES := \
-        media_plugin_headers \
-
 LOCAL_SHARED_LIBRARIES := \
         libstagefright libmedia libmedia_omx libmediaextractor libutils libbinder \
         libstagefright_foundation libjpeg libui libgui libcutils liblog \
-        libhidlbase \
+        libhidlmemory \
         android.hardware.media.omx@1.0 \
 
 LOCAL_C_INCLUDES:= \
+        frameworks/av/media/libstagefright \
+        frameworks/av/media/libstagefright/include \
+        frameworks/native/include/media/openmax \
         external/jpeg \
 
 LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
@@ -35,13 +35,15 @@
         SineSource.cpp    \
         record.cpp
 
-LOCAL_HEADER_LIBRARIES := \
-        media_plugin_headers \
-
 LOCAL_SHARED_LIBRARIES := \
         libstagefright libmedia libmediaextractor liblog libutils libbinder \
         libstagefright_foundation
 
+LOCAL_C_INCLUDES:= \
+        frameworks/av/media/libstagefright \
+        frameworks/native/include/media/openmax \
+        frameworks/native/include/media/hardware
+
 LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
 
 LOCAL_MODULE_TAGS := optional
@@ -58,13 +60,15 @@
         SineSource.cpp    \
         recordvideo.cpp
 
-LOCAL_HEADER_LIBRARIES := \
-        media_plugin_headers \
-
 LOCAL_SHARED_LIBRARIES := \
         libstagefright libmedia libmediaextractor liblog libutils libbinder \
         libstagefright_foundation
 
+LOCAL_C_INCLUDES:= \
+        frameworks/av/media/libstagefright \
+        frameworks/native/include/media/openmax \
+        frameworks/native/include/media/hardware
+
 LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
 
 LOCAL_MODULE_TAGS := optional
@@ -82,13 +86,14 @@
         SineSource.cpp    \
         audioloop.cpp
 
-LOCAL_HEADER_LIBRARIES := \
-        media_plugin_headers \
-
 LOCAL_SHARED_LIBRARIES := \
         libstagefright libmedia libmediaextractor liblog libutils libbinder \
         libstagefright_foundation
 
+LOCAL_C_INCLUDES:= \
+        frameworks/av/media/libstagefright \
+        frameworks/native/include/media/openmax
+
 LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
 
 LOCAL_MODULE_TAGS := optional
@@ -104,13 +109,14 @@
 LOCAL_SRC_FILES:=         \
         stream.cpp    \
 
-LOCAL_HEADER_LIBRARIES := \
-        media_plugin_headers \
-
 LOCAL_SHARED_LIBRARIES := \
         libstagefright liblog libutils libbinder libui libgui \
         libstagefright_foundation libmedia libcutils
 
+LOCAL_C_INCLUDES:= \
+        frameworks/av/media/libstagefright \
+        frameworks/native/include/media/openmax
+
 LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
 
 LOCAL_MODULE_TAGS := optional
@@ -127,13 +133,14 @@
         codec.cpp               \
         SimplePlayer.cpp        \
 
-LOCAL_HEADER_LIBRARIES := \
-        media_plugin_headers \
-
 LOCAL_SHARED_LIBRARIES := \
         libstagefright liblog libutils libbinder libstagefright_foundation \
         libmedia libmedia_omx libaudioclient libui libgui libcutils
 
+LOCAL_C_INCLUDES:= \
+        frameworks/av/media/libstagefright \
+        frameworks/native/include/media/openmax
+
 LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
 
 LOCAL_MODULE_TAGS := optional
@@ -152,9 +159,6 @@
         filters/saturation.rs \
         mediafilter.cpp \
 
-LOCAL_HEADER_LIBRARIES := \
-        media_plugin_headers \
-
 LOCAL_SHARED_LIBRARIES := \
         libstagefright \
         liblog \
@@ -168,9 +172,14 @@
         libcutils \
         libRScpp \
 
+LOCAL_C_INCLUDES:= \
+        frameworks/av/media/libstagefright \
+        frameworks/native/include/media/openmax \
+        frameworks/rs/cpp \
+        frameworks/rs \
+
 intermediates := $(call intermediates-dir-for,STATIC_LIBRARIES,libRS,TARGET,)
 LOCAL_C_INCLUDES += $(intermediates)
-LOCAL_C_INCLUDES += frameworks/av/media/libstagefright/filters
 
 LOCAL_STATIC_LIBRARIES:= \
         libstagefright_mediafilter
@@ -193,13 +202,14 @@
 LOCAL_SRC_FILES:=               \
         muxer.cpp            \
 
-LOCAL_HEADER_LIBRARIES := \
-        media_plugin_headers \
-
 LOCAL_SHARED_LIBRARIES := \
         libstagefright liblog libutils libbinder libstagefright_foundation \
         libcutils libc
 
+LOCAL_C_INCLUDES:= \
+        frameworks/av/media/libstagefright \
+        frameworks/native/include/media/openmax
+
 LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
 
 LOCAL_MODULE_TAGS := optional
diff --git a/cmds/stagefright/mediafilter.cpp b/cmds/stagefright/mediafilter.cpp
index c90a2e4..f24d2dd 100644
--- a/cmds/stagefright/mediafilter.cpp
+++ b/cmds/stagefright/mediafilter.cpp
@@ -20,7 +20,7 @@
 #include <inttypes.h>
 
 #include <binder/ProcessState.h>
-#include <ColorConvert.h>
+#include <filters/ColorConvert.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/SurfaceComposerClient.h>
 #include <gui/Surface.h>
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index f873ba5..50b034a 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -36,12 +36,13 @@
 #include <media/MediaSource.h>
 #include <media/ICrypto.h>
 #include <media/IMediaHTTPService.h>
+#include <media/IMediaCodecService.h>
 #include <media/IMediaPlayerService.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AUtils.h>
-#include <NuCachedSource2.h>
+#include "include/NuCachedSource2.h"
 #include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/DataSourceFactory.h>
 #include <media/stagefright/JPEGSource.h>
@@ -67,6 +68,7 @@
 #include <gui/SurfaceComposerClient.h>
 
 #include <android/hardware/media/omx/1.0/IOmx.h>
+#include <media/omx/1.0/WOmx.h>
 
 using namespace android;
 
@@ -910,24 +912,37 @@
     }
 
     if (listComponents) {
-        using ::android::hardware::hidl_vec;
-        using ::android::hardware::hidl_string;
-        using namespace ::android::hardware::media::omx::V1_0;
-        sp<IOmx> omx = IOmx::getService();
-        CHECK(omx.get() != nullptr);
+        sp<IOMX> omx;
+        if (property_get_bool("persist.media.treble_omx", true)) {
+            using namespace ::android::hardware::media::omx::V1_0;
+            sp<IOmx> tOmx = IOmx::getService();
 
-        hidl_vec<IOmx::ComponentInfo> nodeList;
-        auto transStatus = omx->listNodes([](
-                const auto& status, const auto& nodeList) {
-                    CHECK(status == Status::OK);
-                    for (const auto& info : nodeList) {
-                        printf("%s\t Roles: ", info.mName.c_str());
-                        for (const auto& role : info.mRoles) {
-                            printf("%s\t", role.c_str());
-                        }
-                    }
-                });
-        CHECK(transStatus.isOk());
+            CHECK(tOmx.get() != NULL);
+
+            omx = new utils::LWOmx(tOmx);
+        } else {
+            sp<IServiceManager> sm = defaultServiceManager();
+            sp<IBinder> binder = sm->getService(String16("media.codec"));
+            sp<IMediaCodecService> service = interface_cast<IMediaCodecService>(binder);
+
+            CHECK(service.get() != NULL);
+
+            omx = service->getOMX();
+        }
+        CHECK(omx.get() != NULL);
+
+        List<IOMX::ComponentInfo> list;
+        omx->listNodes(&list);
+
+        for (List<IOMX::ComponentInfo>::iterator it = list.begin();
+             it != list.end(); ++it) {
+            printf("%s\t Roles: ", (*it).mName.string());
+            for (List<String8>::iterator itRoles = (*it).mRoles.begin() ;
+                    itRoles != (*it).mRoles.end() ; ++itRoles) {
+                printf("%s\t", (*itRoles).string());
+            }
+            printf("\n");
+        }
     }
 
     sp<SurfaceComposerClient> composerClient;
diff --git a/media/audioserver/Android.mk b/media/audioserver/Android.mk
index 0777890..ee87751 100644
--- a/media/audioserver/Android.mk
+++ b/media/audioserver/Android.mk
@@ -13,11 +13,12 @@
 	libbinder \
 	libcutils \
 	liblog \
+	libhidltransport \
+	libhwbinder \
 	libmedialogservice \
 	libnbaio \
 	libsoundtriggerservice \
-	libutils \
-	libhwbinder
+	libutils
 
 # TODO oboeservice is the old folder name for aaudioservice. It will be changed.
 LOCAL_C_INCLUDES := \
diff --git a/media/audioserver/main_audioserver.cpp b/media/audioserver/main_audioserver.cpp
index 474ef97..5a9d1bb 100644
--- a/media/audioserver/main_audioserver.cpp
+++ b/media/audioserver/main_audioserver.cpp
@@ -25,12 +25,9 @@
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
+#include <hidl/HidlTransportSupport.h>
 #include <utils/Log.h>
 
-// FIXME: remove when BUG 31748996 is fixed
-#include <hwbinder/IPCThreadState.h>
-#include <hwbinder/ProcessState.h>
-
 // from LOCAL_C_INCLUDES
 #include "aaudio/AAudioTesting.h"
 #include "AudioFlinger.h"
@@ -128,6 +125,7 @@
             prctl(PR_SET_PDEATHSIG, SIGKILL);   // if parent media.log dies before me, kill me also
             setpgid(0, 0);                      // but if I die first, don't kill my parent
         }
+        android::hardware::configureRpcThreadpool(4, false /*callerWillJoin*/);
         sp<ProcessState> proc(ProcessState::self());
         sp<IServiceManager> sm = defaultServiceManager();
         ALOGI("ServiceManager: %p", sm.get());
@@ -145,10 +143,6 @@
 
         SoundTriggerHwService::instantiate();
         ProcessState::self()->startThreadPool();
-
-// FIXME: remove when BUG 31748996 is fixed
-        android::hardware::ProcessState::self()->startThreadPool();
-
         IPCThreadState::self()->joinThreadPool();
     }
 }
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index fa1d253..cfb5be6 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -811,6 +811,20 @@
                         { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
           .repeatCnt = ToneGenerator::TONEGEN_INF,
           .repeatSegment = 0 },                              // TONE_HK_RINGTONE
+        { .segments = { { .duration = 400, .waveFreq = { 400, 450, 0 }, 0, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 400, .waveFreq = { 400, 450, 0 }, 0, 0 },
+                        { .duration = 2000, .waveFreq = { 0 }, 0, 0},
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_IE_RINGTONE
+        { .segments = { { .duration = 180, .waveFreq = { 425, 0 }, 0, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 200, .waveFreq = { 425, 0 }, 0, 0 },
+                        { .duration = 4500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_IE_CALL_WAITING
 };
 
 // Used by ToneGenerator::getToneForRegion() to convert user specified supervisory tone type
@@ -875,6 +889,16 @@
             TONE_SUP_ERROR,              // TONE_SUP_ERROR
             TONE_SUP_CALL_WAITING,       // TONE_SUP_CALL_WAITING
             TONE_HK_RINGTONE             // TONE_SUP_RINGTONE
+        },
+        {   // IRELAND
+            TONE_SUP_DIAL,               // TONE_SUP_DIAL
+            TONE_SUP_BUSY,               // TONE_SUP_BUSY
+            TONE_SUP_CONGESTION,         // TONE_SUP_CONGESTION
+            TONE_SUP_RADIO_ACK,          // TONE_SUP_RADIO_ACK
+            TONE_SUP_RADIO_NOTAVAIL,     // TONE_SUP_RADIO_NOTAVAIL
+            TONE_SUP_ERROR,              // TONE_SUP_ERROR
+            TONE_IE_CALL_WAITING,        // TONE_SUP_CALL_WAITING
+            TONE_IE_RINGTONE             // TONE_SUP_RINGTONE
         }
 };
 
@@ -944,6 +968,8 @@
         mRegion = SINGAPORE;
     } else if (strstr(value, "hk") != NULL) {
         mRegion = HONGKONG;
+    } else if (strstr(value, "ie") != NULL) {
+        mRegion = IRELAND;
     } else {
         mRegion = CEPT;
     }
diff --git a/media/libaudioclient/include/media/ToneGenerator.h b/media/libaudioclient/include/media/ToneGenerator.h
index 97bc825..247703f 100644
--- a/media/libaudioclient/include/media/ToneGenerator.h
+++ b/media/libaudioclient/include/media/ToneGenerator.h
@@ -209,6 +209,9 @@
         // HONG KONG Supervisory tones
         TONE_HK_BUSY,               // Busy tone: 480 Hz + 620 Hz, 500ms ON, 500ms OFF...
         TONE_HK_RINGTONE,           // Ring Tone: 440 Hz + 480 Hz repeated with pattern 0,4s on, 0,2s off, 0,4s on and 3s off.
+        // IRELAND Supervisory tones
+        TONE_IE_RINGTONE,           // Ring Tone: A 400Hz + 450Hz tone repeated in a 0.4s on, 0.2s off, 0.4s on, 2.0s off pattern.
+        TONE_IE_CALL_WAITING,       // Call waiting tone: 425Hz tone repeated in a 0.18s on, 0.2s off, 0.2s on, 4.5s off pattern.
         NUM_ALTERNATE_TONES
     };
 
@@ -219,6 +222,7 @@
         AUSTRALIA,
         SINGAPORE,
         HONGKONG,
+        IRELAND,
         CEPT,
         NUM_REGIONS
     };
diff --git a/media/libaudiohal/HalDeathHandlerHidl.cpp b/media/libaudiohal/HalDeathHandlerHidl.cpp
index a742671..1e3ab58 100644
--- a/media/libaudiohal/HalDeathHandlerHidl.cpp
+++ b/media/libaudiohal/HalDeathHandlerHidl.cpp
@@ -48,12 +48,13 @@
 
 void HalDeathHandler::serviceDied(uint64_t /*cookie*/, const wp<IBase>& /*who*/) {
     // No matter which of the service objects has died,
-    // we need to run all the registered handlers and crash our process.
+    // we need to run all the registered handlers and exit.
     std::lock_guard<std::mutex> guard(mHandlersLock);
     for (const auto& handler : mHandlers) {
         handler.second();
     }
-    LOG_ALWAYS_FATAL("HAL server crashed, need to restart");
+    ALOGE("HAL server crashed, audio server is restarting");
+    exit(1);
 }
 
 } // namespace android
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index 238925d..3e72c89 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -813,7 +813,7 @@
                 mMixerInFormat, sampleRate, playbackRate);
         reconfigureBufferProviders();
     } else {
-        reinterpret_cast<TimestretchBufferProvider*>(mTimestretchBufferProvider)
+        static_cast<TimestretchBufferProvider*>(mTimestretchBufferProvider)
                 ->setPlaybackRate(playbackRate);
     }
     return true;
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 1f4bd0a..1381d27 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -45,7 +45,9 @@
         "aidl/android/IOMXBufferSource.aidl",
 
         "IMediaCodecList.cpp",
+        "IMediaCodecService.cpp",
         "IOMX.cpp",
+        "IOMXStore.cpp",
         "MediaCodecBuffer.cpp",
         "MediaCodecInfo.cpp",
         "OMXBuffer.cpp",
diff --git a/media/libmedia/IMediaCodecService.cpp b/media/libmedia/IMediaCodecService.cpp
new file mode 100644
index 0000000..adfa93d
--- /dev/null
+++ b/media/libmedia/IMediaCodecService.cpp
@@ -0,0 +1,86 @@
+/*
+**
+** Copyright 2015, 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.
+*/
+
+#define LOG_TAG "IMediaCodecService"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <media/IMediaCodecService.h>
+
+namespace android {
+
+enum {
+    GET_OMX = IBinder::FIRST_CALL_TRANSACTION,
+    GET_OMX_STORE
+};
+
+class BpMediaCodecService : public BpInterface<IMediaCodecService>
+{
+public:
+    explicit BpMediaCodecService(const sp<IBinder>& impl)
+        : BpInterface<IMediaCodecService>(impl)
+    {
+    }
+
+    virtual sp<IOMX> getOMX() {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaCodecService::getInterfaceDescriptor());
+        remote()->transact(GET_OMX, data, &reply);
+        return interface_cast<IOMX>(reply.readStrongBinder());
+    }
+
+    virtual sp<IOMXStore> getOMXStore() {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaCodecService::getInterfaceDescriptor());
+        remote()->transact(GET_OMX_STORE, data, &reply);
+        return interface_cast<IOMXStore>(reply.readStrongBinder());
+    }
+
+};
+
+IMPLEMENT_META_INTERFACE(MediaCodecService, "android.media.IMediaCodecService");
+
+// ----------------------------------------------------------------------
+
+status_t BnMediaCodecService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch (code) {
+
+        case GET_OMX: {
+            CHECK_INTERFACE(IMediaCodecService, data, reply);
+            sp<IOMX> omx = getOMX();
+            reply->writeStrongBinder(IInterface::asBinder(omx));
+            return NO_ERROR;
+        }
+        case GET_OMX_STORE: {
+            CHECK_INTERFACE(IMediaCodecService, data, reply);
+            sp<IOMXStore> omxStore = getOMXStore();
+            reply->writeStrongBinder(IInterface::asBinder(omxStore));
+            return NO_ERROR;
+        }
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+} // namespace android
diff --git a/media/libmedia/IOMXStore.cpp b/media/libmedia/IOMXStore.cpp
new file mode 100644
index 0000000..4948f1a
--- /dev/null
+++ b/media/libmedia/IOMXStore.cpp
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2009 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "IOMXStore"
+
+#include <utils/Log.h>
+
+#include <media/IOMX.h>
+#include <media/IOMXStore.h>
+#include <android/hardware/media/omx/1.0/IOmxStore.h>
+
+#include <binder/IInterface.h>
+#include <binder/IBinder.h>
+#include <binder/Parcel.h>
+
+#include <vector>
+#include <string>
+
+namespace android {
+
+namespace {
+
+enum {
+    CONNECT = IBinder::FIRST_CALL_TRANSACTION,
+    LIST_SERVICE_ATTRIBUTES,
+    GET_NODE_PREFIX,
+    LIST_ROLES,
+    GET_OMX,
+};
+
+// Forward declarations of std::vector<T> <-> Parcel conversion funcitons that
+// depend on writeToParcel() and readToParcel() for T <-> Parcel.
+
+template <typename T>
+status_t writeToParcel(const std::vector<T>& v, Parcel* p);
+
+template <typename T>
+status_t readFromParcel(std::vector<T>* v, const Parcel& p);
+
+// std::string <-> Parcel
+
+status_t writeToParcel(const std::string& s, Parcel* p) {
+    if (s.size() > INT32_MAX) {
+        return BAD_VALUE;
+    }
+    return p->writeByteArray(
+            s.size(), reinterpret_cast<const uint8_t*>(s.c_str()));
+}
+
+status_t readFromParcel(std::string* s, const Parcel& p) {
+    int32_t len;
+    status_t status = p.readInt32(&len);
+    if (status != NO_ERROR) {
+        return status;
+    } else if ((len < 0) || (static_cast<uint64_t>(len) > SIZE_MAX)) {
+        return BAD_VALUE;
+    }
+    s->resize(len);
+    if (len == 0) {
+        return NO_ERROR;
+    }
+    return p.read(static_cast<void*>(&s->front()), static_cast<size_t>(len));
+}
+
+// IOMXStore::Attribute <-> Parcel
+
+status_t writeToParcel(const IOMXStore::Attribute& a, Parcel* p) {
+    status_t status = writeToParcel(a.key, p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    return writeToParcel(a.value, p);
+}
+
+status_t readFromParcel(IOMXStore::Attribute* a, const Parcel& p) {
+    status_t status = readFromParcel(&(a->key), p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    return readFromParcel(&(a->value), p);
+}
+
+// IOMXStore::NodeInfo <-> Parcel
+
+status_t writeToParcel(const IOMXStore::NodeInfo& n, Parcel* p) {
+    status_t status = writeToParcel(n.name, p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    status = writeToParcel(n.owner, p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    return writeToParcel(n.attributes, p);
+}
+
+status_t readFromParcel(IOMXStore::NodeInfo* n, const Parcel& p) {
+    status_t status = readFromParcel(&(n->name), p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    status = readFromParcel(&(n->owner), p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    return readFromParcel(&(n->attributes), p);
+}
+
+// IOMXStore::RoleInfo <-> Parcel
+
+status_t writeToParcel(const IOMXStore::RoleInfo& r, Parcel* p) {
+    status_t status = writeToParcel(r.role, p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    status = writeToParcel(r.type, p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    status = p->writeBool(r.isEncoder);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    status = p->writeBool(r.preferPlatformNodes);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    return writeToParcel(r.nodes, p);
+}
+
+status_t readFromParcel(IOMXStore::RoleInfo* r, const Parcel& p) {
+    status_t status = readFromParcel(&(r->role), p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    status = readFromParcel(&(r->type), p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    status = p.readBool(&(r->isEncoder));
+    if (status != NO_ERROR) {
+        return status;
+    }
+    status = p.readBool(&(r->preferPlatformNodes));
+    if (status != NO_ERROR) {
+        return status;
+    }
+    return readFromParcel(&(r->nodes), p);
+}
+
+// std::vector<NodeInfo> <-> Parcel
+// std::vector<RoleInfo> <-> Parcel
+
+template <typename T>
+status_t writeToParcel(const std::vector<T>& v, Parcel* p) {
+    status_t status = p->writeVectorSize(v);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    for (const T& x : v) {
+        status = writeToParcel(x, p);
+        if (status != NO_ERROR) {
+            return status;
+        }
+    }
+    return NO_ERROR;
+}
+
+template <typename T>
+status_t readFromParcel(std::vector<T>* v, const Parcel& p) {
+    status_t status = p.resizeOutVector(v);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    for (T& x : *v) {
+        status = readFromParcel(&x, p);
+        if (status != NO_ERROR) {
+            return status;
+        }
+    }
+    return NO_ERROR;
+}
+
+} // unnamed namespace
+
+////////////////////////////////////////////////////////////////////////////////
+
+class BpOMXStore : public BpInterface<IOMXStore> {
+public:
+    explicit BpOMXStore(const sp<IBinder> &impl)
+        : BpInterface<IOMXStore>(impl) {
+    }
+
+    status_t listServiceAttributes(
+            std::vector<Attribute>* attributes) override {
+        Parcel data, reply;
+        status_t status;
+        status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = remote()->transact(LIST_SERVICE_ATTRIBUTES, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        return readFromParcel(attributes, reply);
+    }
+
+    status_t getNodePrefix(std::string* prefix) override {
+        Parcel data, reply;
+        status_t status;
+        status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = remote()->transact(GET_NODE_PREFIX, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        return readFromParcel(prefix, reply);
+    }
+
+    status_t listRoles(std::vector<RoleInfo>* roleList) override {
+        Parcel data, reply;
+        status_t status;
+        status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = remote()->transact(LIST_ROLES, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        return readFromParcel(roleList, reply);
+    }
+
+    status_t getOmx(const std::string& name, sp<IOMX>* omx) override {
+        Parcel data, reply;
+        status_t status;
+        status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = writeToParcel(name, &data);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = remote()->transact(GET_OMX, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        return reply.readStrongBinder(omx);
+    }
+
+};
+
+IMPLEMENT_META_INTERFACE(OMXStore, "android.hardware.IOMXStore");
+
+////////////////////////////////////////////////////////////////////////////////
+
+#define CHECK_OMX_INTERFACE(interface, data, reply) \
+        do { if (!(data).enforceInterface(interface::getInterfaceDescriptor())) { \
+            ALOGW("Call incorrectly routed to " #interface); \
+            return PERMISSION_DENIED; \
+        } } while (0)
+
+status_t BnOMXStore::onTransact(
+    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
+    switch (code) {
+        case LIST_SERVICE_ATTRIBUTES: {
+            CHECK_OMX_INTERFACE(IOMXStore, data, reply);
+            status_t status;
+            std::vector<Attribute> attributes;
+
+            status = listServiceAttributes(&attributes);
+            if (status != NO_ERROR) {
+                ALOGE("listServiceAttributes() fails with status %d",
+                        static_cast<int>(status));
+                return NO_ERROR;
+            }
+            status = writeToParcel(attributes, reply);
+            if (status != NO_ERROR) {
+                ALOGE("listServiceAttributes() fails to send reply");
+                return NO_ERROR;
+            }
+            return NO_ERROR;
+        }
+        case GET_NODE_PREFIX: {
+            CHECK_OMX_INTERFACE(IOMXStore, data, reply);
+            status_t status;
+            std::string prefix;
+
+            status = getNodePrefix(&prefix);
+            if (status != NO_ERROR) {
+                ALOGE("getNodePrefix() fails with status %d",
+                        static_cast<int>(status));
+                return NO_ERROR;
+            }
+            status = writeToParcel(prefix, reply);
+            if (status != NO_ERROR) {
+                ALOGE("getNodePrefix() fails to send reply");
+                return NO_ERROR;
+            }
+            return NO_ERROR;
+        }
+        case LIST_ROLES: {
+            CHECK_OMX_INTERFACE(IOMXStore, data, reply);
+            status_t status;
+            std::vector<RoleInfo> roleList;
+
+            status = listRoles(&roleList);
+            if (status != NO_ERROR) {
+                ALOGE("listRoles() fails with status %d",
+                        static_cast<int>(status));
+                return NO_ERROR;
+            }
+            status = writeToParcel(roleList, reply);
+            if (status != NO_ERROR) {
+                ALOGE("listRoles() fails to send reply");
+                return NO_ERROR;
+            }
+            return NO_ERROR;
+        }
+        case GET_OMX: {
+            CHECK_OMX_INTERFACE(IOMXStore, data, reply);
+            status_t status;
+            std::string name;
+            sp<IOMX> omx;
+
+            status = readFromParcel(&name, data);
+            if (status != NO_ERROR) {
+                ALOGE("getOmx() fails to retrieve name");
+                return NO_ERROR;
+            }
+            status = getOmx(name, &omx);
+            if (status != NO_ERROR) {
+                ALOGE("getOmx() fails with status %d",
+                        static_cast<int>(status));
+                return NO_ERROR;
+            }
+            status = reply->writeStrongBinder(IInterface::asBinder(omx));
+            if (status != NO_ERROR) {
+                ALOGE("getOmx() fails to send reply");
+                return NO_ERROR;
+            }
+            return NO_ERROR;
+        }
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}  // namespace android
diff --git a/media/libmedia/include/media/IMediaCodecService.h b/media/libmedia/include/media/IMediaCodecService.h
new file mode 100644
index 0000000..59fb1c0
--- /dev/null
+++ b/media/libmedia/include/media/IMediaCodecService.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ANDROID_IMEDIACODECSERVICE_H
+#define ANDROID_IMEDIACODECSERVICE_H
+
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <media/IDataSource.h>
+#include <media/IOMX.h>
+#include <media/IOMXStore.h>
+
+namespace android {
+
+class IMediaCodecService: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(MediaCodecService);
+
+    virtual sp<IOMX> getOMX() = 0;
+    virtual sp<IOMXStore> getOMXStore() = 0;
+};
+
+class BnMediaCodecService: public BnInterface<IMediaCodecService>
+{
+public:
+    virtual status_t    onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                uint32_t flags = 0);
+};
+
+}   // namespace android
+
+#endif  // ANDROID_IMEDIACODECSERVICE_H
diff --git a/media/libmedia/include/media/IOMXStore.h b/media/libmedia/include/media/IOMXStore.h
new file mode 100644
index 0000000..628db70
--- /dev/null
+++ b/media/libmedia/include/media/IOMXStore.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef ANDROID_IOMXSTORE_H_
+
+#define ANDROID_IOMXSTORE_H_
+
+#include <media/IOMX.h>
+#include <android/hardware/media/omx/1.0/IOmxStore.h>
+
+#include <binder/IInterface.h>
+#include <binder/IBinder.h>
+
+#include <vector>
+#include <string>
+
+namespace android {
+
+using hardware::media::omx::V1_0::IOmxStore;
+
+class IOMXStore : public IInterface {
+public:
+    DECLARE_META_INTERFACE(OMXStore);
+
+    struct Attribute {
+        std::string key;
+        std::string value;
+    };
+
+    struct NodeInfo {
+        std::string name;
+        std::string owner;
+        std::vector<Attribute> attributes;
+    };
+
+    struct RoleInfo {
+        std::string role;
+        std::string type;
+        bool isEncoder;
+        bool preferPlatformNodes;
+        std::vector<NodeInfo> nodes;
+    };
+
+    virtual status_t listServiceAttributes(
+            std::vector<Attribute>* attributes) = 0;
+
+    virtual status_t getNodePrefix(std::string* prefix) = 0;
+
+    virtual status_t listRoles(std::vector<RoleInfo>* roleList) = 0;
+
+    virtual status_t getOmx(const std::string& name, sp<IOMX>* omx) = 0;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+class BnOMXStore : public BnInterface<IOMXStore> {
+public:
+    virtual status_t onTransact(
+            uint32_t code, const Parcel &data, Parcel *reply,
+            uint32_t flags = 0);
+};
+
+}  // namespace android
+
+#endif  // ANDROID_IOMX_H_
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 98a47c4..6b2c81d 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -741,14 +741,26 @@
             new ServiceDeathNotifier(binder, p, MEDIAEXTRACTOR_PROCESS_DEATH);
     binder->linkToDeath(extractorDeathListener);
 
-    sp<IOmx> omx = IOmx::getService();
-    if (omx == nullptr) {
-        ALOGE("IOmx service is not available");
-        return NULL;
+    sp<ServiceDeathNotifier> codecDeathListener;
+    if (property_get_bool("persist.media.treble_omx", true)) {
+        // Treble IOmx
+        sp<IOmx> omx = IOmx::getService();
+        if (omx == nullptr) {
+            ALOGE("Treble IOmx not available");
+            return NULL;
+        }
+        codecDeathListener = new ServiceDeathNotifier(omx, p, MEDIACODEC_PROCESS_DEATH);
+        omx->linkToDeath(codecDeathListener, 0);
+    } else {
+        // Legacy IOMX
+        binder = sm->getService(String16("media.codec"));
+        if (binder == NULL) {
+            ALOGE("codec service not available");
+            return NULL;
+        }
+        codecDeathListener = new ServiceDeathNotifier(binder, p, MEDIACODEC_PROCESS_DEATH);
+        binder->linkToDeath(codecDeathListener);
     }
-    sp<ServiceDeathNotifier> codecDeathListener =
-            new ServiceDeathNotifier(omx, p, MEDIACODEC_PROCESS_DEATH);
-    omx->linkToDeath(codecDeathListener, 0);
 
     Mutex::Autolock lock(mLock);
 
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index a423fee..9b9b3bb 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -450,14 +450,27 @@
     }
     sCameraChecked = true;
 
-    sp<IOmx> omx = IOmx::getService();
-    if (omx == nullptr) {
-        ALOGE("IOmx service is not available");
-        return NO_INIT;
+    if (property_get_bool("persist.media.treble_omx", true)) {
+        // Treble IOmx
+        sp<IOmx> omx = IOmx::getService();
+        if (omx == nullptr) {
+            ALOGE("Treble IOmx not available");
+            return NO_INIT;
+        }
+        mCodecDeathListener = new ServiceDeathNotifier(omx, listener,
+                MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
+        omx->linkToDeath(mCodecDeathListener, 0);
+    } else {
+        // Legacy IOMX
+        binder = sm->getService(String16("media.codec"));
+        if (binder == NULL) {
+           ALOGE("Unable to connect to media codec service");
+           return NO_INIT;
+        }
+        mCodecDeathListener = new ServiceDeathNotifier(binder, listener,
+                MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
+        binder->linkToDeath(mCodecDeathListener);
     }
-    mCodecDeathListener = new ServiceDeathNotifier(omx, listener,
-            MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
-    omx->linkToDeath(mCodecDeathListener, 0);
 
     return OK;
 }
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index c3127ae..a3f4efb 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -677,6 +677,12 @@
           break;
       }
 
+      case kWhatSeek:
+      {
+          onSeek(msg);
+          break;
+      }
+
       case kWhatReadBuffer:
       {
           onReadBuffer(msg);
@@ -1097,8 +1103,39 @@
 }
 
 status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
-    Mutex::Autolock _l(mLock);
     ALOGV("seekTo: %lld, %d", (long long)seekTimeUs, mode);
+    sp<AMessage> msg = new AMessage(kWhatSeek, this);
+    msg->setInt64("seekTimeUs", seekTimeUs);
+    msg->setInt32("mode", mode);
+
+    // Need to call readBuffer on |mLooper| to ensure the calls to
+    // IMediaSource::read* are serialized. Note that IMediaSource::read*
+    // is called without |mLock| acquired and MediaSource is not thread safe.
+    sp<AMessage> response;
+    status_t err = msg->postAndAwaitResponse(&response);
+    if (err == OK && response != NULL) {
+        CHECK(response->findInt32("err", &err));
+    }
+
+    return err;
+}
+
+void NuPlayer::GenericSource::onSeek(const sp<AMessage>& msg) {
+    int64_t seekTimeUs;
+    int32_t mode;
+    CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
+    CHECK(msg->findInt32("mode", &mode));
+
+    sp<AMessage> response = new AMessage;
+    status_t err = doSeek(seekTimeUs, (MediaPlayerSeekMode)mode);
+    response->setInt32("err", err);
+
+    sp<AReplyToken> replyID;
+    CHECK(msg->senderAwaitsResponse(&replyID));
+    response->postReply(replyID);
+}
+
+status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
     if (mVideoTrack.mSource != NULL) {
         ++mVideoDataGeneration;
 
@@ -1321,13 +1358,14 @@
         Vector<MediaBuffer *> mediaBuffers;
         status_t err = NO_ERROR;
 
+        sp<IMediaSource> source = track->mSource;
         mLock.unlock();
         if (couldReadMultiple) {
-            err = track->mSource->readMultiple(
+            err = source->readMultiple(
                     &mediaBuffers, maxBuffers - numBuffers, &options);
         } else {
             MediaBuffer *mbuf = NULL;
-            err = track->mSource->read(&mbuf, &options);
+            err = source->read(&mbuf, &options);
             if (err == OK && mbuf != NULL) {
                 mediaBuffers.push_back(mbuf);
             }
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index 16c0224..cb9c27f 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -112,6 +112,7 @@
         kWhatSendTimedTextData,
         kWhatChangeAVSource,
         kWhatPollBuffering,
+        kWhatSeek,
         kWhatReadBuffer,
         kWhatStart,
         kWhatResume,
@@ -183,6 +184,9 @@
     void finishPrepareAsync();
     status_t startSources();
 
+    void onSeek(const sp<AMessage>& msg);
+    status_t doSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode);
+
     void onPrepareAsync();
 
     void fetchTextData(
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index a26d525..6c4b823 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -182,6 +182,7 @@
       mAudioDecoderGeneration(0),
       mVideoDecoderGeneration(0),
       mRendererGeneration(0),
+      mLastStartedPlayingTimeNs(0),
       mPreviousSeekTimeUs(0),
       mAudioEOS(false),
       mVideoEOS(false),
@@ -1309,6 +1310,7 @@
             ALOGV("kWhatReset");
 
             mResetting = true;
+            stopPlaybackTimer("kWhatReset");
 
             mDeferredActions.push_back(
                     new FlushDecoderAction(
@@ -1449,7 +1451,7 @@
         ALOGW("resume called when renderer is gone or not set");
     }
 
-    mLastStartedPlayingTimeNs = systemTime();
+    startPlaybackTimer("onresume");
 }
 
 status_t NuPlayer::onInstantiateSecureDecoders() {
@@ -1569,12 +1571,43 @@
         mAudioDecoder->setRenderer(mRenderer);
     }
 
-    mLastStartedPlayingTimeNs = systemTime();
+    startPlaybackTimer("onstart");
 
     postScanSources();
 }
 
+void NuPlayer::startPlaybackTimer(const char *where) {
+    Mutex::Autolock autoLock(mPlayingTimeLock);
+    if (mLastStartedPlayingTimeNs == 0) {
+        mLastStartedPlayingTimeNs = systemTime();
+        ALOGV("startPlaybackTimer() time %20" PRId64 " (%s)",  mLastStartedPlayingTimeNs, where);
+    }
+}
+
+void NuPlayer::stopPlaybackTimer(const char *where) {
+    Mutex::Autolock autoLock(mPlayingTimeLock);
+
+    ALOGV("stopPlaybackTimer()  time %20" PRId64 " (%s)", mLastStartedPlayingTimeNs, where);
+
+    if (mLastStartedPlayingTimeNs != 0) {
+        sp<NuPlayerDriver> driver = mDriver.promote();
+        if (driver != NULL) {
+            int64_t now = systemTime();
+            int64_t played = now - mLastStartedPlayingTimeNs;
+            ALOGV("stopPlaybackTimer()  log  %20" PRId64 "", played);
+
+            if (played > 0) {
+                driver->notifyMorePlayingTimeUs((played+500)/1000);
+            }
+        }
+        mLastStartedPlayingTimeNs = 0;
+    }
+}
+
 void NuPlayer::onPause() {
+
+    stopPlaybackTimer("onPause");
+
     if (mPaused) {
         return;
     }
@@ -1590,13 +1623,6 @@
         ALOGW("pause called when renderer is gone or not set");
     }
 
-    sp<NuPlayerDriver> driver = mDriver.promote();
-    if (driver != NULL) {
-        int64_t now = systemTime();
-        int64_t played = now - mLastStartedPlayingTimeNs;
-
-        driver->notifyMorePlayingTimeUs((played+500)/1000);
-    }
 }
 
 bool NuPlayer::audioDecoderStillNeeded() {
@@ -2223,6 +2249,8 @@
     CHECK(mAudioDecoder == NULL);
     CHECK(mVideoDecoder == NULL);
 
+    stopPlaybackTimer("performReset");
+
     cancelPollDuration();
 
     ++mScanSourcesGeneration;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 747dc47..492b8d4 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -178,7 +178,10 @@
     int32_t mVideoDecoderGeneration;
     int32_t mRendererGeneration;
 
+    Mutex mPlayingTimeLock;
     int64_t mLastStartedPlayingTimeNs;
+    void stopPlaybackTimer(const char *where);
+    void startPlaybackTimer(const char *where);
 
     int64_t mPreviousSeekTimeUs;
 
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index d9fdfe3..a7a1b05 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -28,6 +28,8 @@
 
 #include <media/stagefright/ACodec.h>
 
+#include <binder/MemoryDealer.h>
+
 #include <media/stagefright/foundation/avc_utils.h>
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/foundation/ABuffer.h>
@@ -573,6 +575,8 @@
     memset(&mLastNativeWindowCrop, 0, sizeof(mLastNativeWindowCrop));
 
     changeState(mUninitializedState);
+
+    mTrebleFlag = false;
 }
 
 ACodec::~ACodec() {
@@ -824,7 +828,11 @@
 status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
 
-    CHECK(mAllocator[portIndex] == NULL);
+    if (getTrebleFlag()) {
+        CHECK(mAllocator[portIndex] == NULL);
+    } else {
+        CHECK(mDealer[portIndex] == NULL);
+    }
     CHECK(mBuffers[portIndex].isEmpty());
 
     status_t err;
@@ -866,10 +874,7 @@
                 }
             }
 
-            size_t alignment = 32; // This is the value currently returned by
-                                   // MemoryDealer::getAllocationAlignment().
-                                   // TODO: Fix this when Treble has
-                                   // MemoryHeap/MemoryDealer.
+            size_t alignment = MemoryDealer::getAllocationAlignment();
 
             ALOGV("[%s] Allocating %u buffers of size %zu (from %u using %s) on %s port",
                     mComponentName.c_str(),
@@ -891,15 +896,18 @@
             }
 
             if (mode != IOMX::kPortModePresetSecureBuffer) {
-                mAllocator[portIndex] = TAllocator::getService("ashmem");
-                if (mAllocator[portIndex] == nullptr) {
-                    ALOGE("hidl allocator on port %d is null",
-                            (int)portIndex);
-                    return NO_MEMORY;
+                if (getTrebleFlag()) {
+                    mAllocator[portIndex] = TAllocator::getService("ashmem");
+                    if (mAllocator[portIndex] == nullptr) {
+                        ALOGE("hidl allocator on port %d is null",
+                                (int)portIndex);
+                        return NO_MEMORY;
+                    }
+                } else {
+                    size_t totalSize = def.nBufferCountActual *
+                            (alignedSize + alignedConvSize);
+                    mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
                 }
-                // TODO: When Treble has MemoryHeap/MemoryDealer, we should
-                // specify the heap size to be
-                // def.nBufferCountActual * (alignedSize + alignedConvSize).
             }
 
             const sp<AMessage> &format =
@@ -928,55 +936,23 @@
                             : new SecureBuffer(format, native_handle, bufSize);
                     info.mCodecData = info.mData;
                 } else {
-                    bool success;
-                    auto transStatus = mAllocator[portIndex]->allocate(
-                            bufSize,
-                            [&success, &hidlMemToken](
-                                    bool s,
-                                    hidl_memory const& m) {
-                                success = s;
-                                hidlMemToken = m;
-                            });
-
-                    if (!transStatus.isOk()) {
-                        ALOGE("hidl's AshmemAllocator failed at the "
-                                "transport: %s",
-                                transStatus.description().c_str());
-                        return NO_MEMORY;
-                    }
-                    if (!success) {
-                        return NO_MEMORY;
-                    }
-                    hidlMem = mapMemory(hidlMemToken);
-                    if (hidlMem == nullptr) {
-                        return NO_MEMORY;
-                    }
-                    err = mOMXNode->useBuffer(
-                            portIndex, hidlMemToken, &info.mBufferID);
-
-                    if (mode == IOMX::kPortModeDynamicANWBuffer) {
-                        VideoNativeMetadata* metaData = (VideoNativeMetadata*)(
-                                (void*)hidlMem->getPointer());
-                        metaData->nFenceFd = -1;
-                    }
-
-                    info.mCodecData = new SharedMemoryBuffer(
-                            format, hidlMem);
-                    info.mCodecRef = hidlMem;
-
-                    // if we require conversion, allocate conversion buffer for client use;
-                    // otherwise, reuse codec buffer
-                    if (mConverter[portIndex] != NULL) {
-                        CHECK_GT(conversionBufferSize, (size_t)0);
+                    if (getTrebleFlag()) {
                         bool success;
-                        mAllocator[portIndex]->allocate(
-                                conversionBufferSize,
+                        auto transStatus = mAllocator[portIndex]->allocate(
+                                bufSize,
                                 [&success, &hidlMemToken](
                                         bool s,
                                         hidl_memory const& m) {
                                     success = s;
                                     hidlMemToken = m;
                                 });
+
+                        if (!transStatus.isOk()) {
+                            ALOGE("hidl's AshmemAllocator failed at the "
+                                    "transport: %s",
+                                    transStatus.description().c_str());
+                            return NO_MEMORY;
+                        }
                         if (!success) {
                             return NO_MEMORY;
                         }
@@ -984,8 +960,67 @@
                         if (hidlMem == nullptr) {
                             return NO_MEMORY;
                         }
-                        info.mData = new SharedMemoryBuffer(format, hidlMem);
-                        info.mMemRef = hidlMem;
+                        err = mOMXNode->useBuffer(
+                                portIndex, hidlMemToken, &info.mBufferID);
+                    } else {
+                        mem = mDealer[portIndex]->allocate(bufSize);
+                        if (mem == NULL || mem->pointer() == NULL) {
+                            return NO_MEMORY;
+                        }
+
+                        err = mOMXNode->useBuffer(
+                                portIndex, mem, &info.mBufferID);
+                    }
+
+                    if (mode == IOMX::kPortModeDynamicANWBuffer) {
+                        VideoNativeMetadata* metaData = (VideoNativeMetadata*)(
+                                getTrebleFlag() ?
+                                (void*)hidlMem->getPointer() : mem->pointer());
+                        metaData->nFenceFd = -1;
+                    }
+
+                    if (getTrebleFlag()) {
+                        info.mCodecData = new SharedMemoryBuffer(
+                                format, hidlMem);
+                        info.mCodecRef = hidlMem;
+                    } else {
+                        info.mCodecData = new SharedMemoryBuffer(
+                                format, mem);
+                        info.mCodecRef = mem;
+                    }
+
+                    // if we require conversion, allocate conversion buffer for client use;
+                    // otherwise, reuse codec buffer
+                    if (mConverter[portIndex] != NULL) {
+                        CHECK_GT(conversionBufferSize, (size_t)0);
+                        if (getTrebleFlag()) {
+                            bool success;
+                            mAllocator[portIndex]->allocate(
+                                    conversionBufferSize,
+                                    [&success, &hidlMemToken](
+                                            bool s,
+                                            hidl_memory const& m) {
+                                        success = s;
+                                        hidlMemToken = m;
+                                    });
+                            if (!success) {
+                                return NO_MEMORY;
+                            }
+                            hidlMem = mapMemory(hidlMemToken);
+                            if (hidlMem == nullptr) {
+                                return NO_MEMORY;
+                            }
+                            info.mData = new SharedMemoryBuffer(format, hidlMem);
+                            info.mMemRef = hidlMem;
+                        } else {
+                            mem = mDealer[portIndex]->allocate(
+                                    conversionBufferSize);
+                            if (mem == NULL|| mem->pointer() == NULL) {
+                                return NO_MEMORY;
+                            }
+                            info.mData = new SharedMemoryBuffer(format, mem);
+                            info.mMemRef = mem;
+                        }
                     } else {
                         info.mData = info.mCodecData;
                         info.mMemRef = info.mCodecRef;
@@ -1546,7 +1581,11 @@
         }
     }
 
-    mAllocator[portIndex].clear();
+    if (getTrebleFlag()) {
+        mAllocator[portIndex].clear();
+    } else {
+        mDealer[portIndex].clear();
+    }
     return err;
 }
 
@@ -6212,8 +6251,13 @@
 
     if (mDeathNotifier != NULL) {
         if (mCodec->mOMXNode != NULL) {
-            auto tOmxNode = mCodec->mOMXNode->getHalInterface();
-            tOmxNode->unlinkToDeath(mDeathNotifier);
+            if (mCodec->getTrebleFlag()) {
+                auto tOmxNode = mCodec->mOMXNode->getHalInterface();
+                tOmxNode->unlinkToDeath(mDeathNotifier);
+            } else {
+                sp<IBinder> binder = IInterface::asBinder(mCodec->mOMXNode);
+                binder->unlinkToDeath(mDeathNotifier);
+            }
         }
         mDeathNotifier.clear();
     }
@@ -6361,7 +6405,8 @@
         componentName = matchingCodecs[matchIndex];
 
         OMXClient client;
-        if (client.connect(owners[matchIndex].c_str()) != OK) {
+        bool trebleFlag;
+        if (client.connect(owners[matchIndex].c_str(), &trebleFlag) != OK) {
             mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
             return false;
         }
@@ -6374,6 +6419,7 @@
         androidSetThreadPriority(tid, prevPriority);
 
         if (err == OK) {
+            mCodec->setTrebleFlag(trebleFlag);
             break;
         } else {
             ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
@@ -6395,9 +6441,17 @@
     }
 
     mDeathNotifier = new DeathNotifier(notify);
-    auto tOmxNode = omxNode->getHalInterface();
-    if (!tOmxNode->linkToDeath(mDeathNotifier, 0)) {
-        mDeathNotifier.clear();
+    if (mCodec->getTrebleFlag()) {
+        auto tOmxNode = omxNode->getHalInterface();
+        if (!tOmxNode->linkToDeath(mDeathNotifier, 0)) {
+            mDeathNotifier.clear();
+        }
+    } else {
+        if (IInterface::asBinder(omxNode)->linkToDeath(mDeathNotifier) != OK) {
+            // This was a local binder, if it dies so do we, we won't care
+            // about any notifications in the afterlife.
+            mDeathNotifier.clear();
+        }
     }
 
     notify = new AMessage(kWhatOMXMessageList, mCodec);
@@ -7804,7 +7858,11 @@
                             mCodec->mBuffers[kPortIndexOutput].size());
                     err = FAILED_TRANSACTION;
                 } else {
-                    mCodec->mAllocator[kPortIndexOutput].clear();
+                    if (mCodec->getTrebleFlag()) {
+                        mCodec->mAllocator[kPortIndexOutput].clear();
+                    } else {
+                        mCodec->mDealer[kPortIndexOutput].clear();
+                    }
                 }
 
                 if (err == OK) {
@@ -8406,4 +8464,12 @@
     return OK;
 }
 
+void ACodec::setTrebleFlag(bool trebleFlag) {
+    mTrebleFlag = trebleFlag;
+}
+
+bool ACodec::getTrebleFlag() const {
+    return mTrebleFlag;
+}
+
 }  // namespace android
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 54265a4..4feba37 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -24,6 +24,7 @@
 
 #include <media/IMediaCodecList.h>
 #include <media/IMediaPlayerService.h>
+#include <media/IMediaCodecService.h>
 #include <media/MediaCodecInfo.h>
 
 #include <media/stagefright/foundation/ADebug.h>
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index cd07262..5f50e46 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -25,6 +25,7 @@
 #include <cutils/properties.h>
 
 #include <binder/IServiceManager.h>
+#include <media/IMediaCodecService.h>
 #include <media/stagefright/OMXClient.h>
 
 #include <media/IOMX.h>
@@ -36,22 +37,71 @@
 OMXClient::OMXClient() {
 }
 
-status_t OMXClient::connect(const char* name) {
+status_t OMXClient::connect() {
+    return connect("default", nullptr);
+}
+
+status_t OMXClient::connect(bool* trebleFlag) {
+    if (property_get_bool("persist.media.treble_omx", true)) {
+        if (trebleFlag != nullptr) {
+            *trebleFlag = true;
+        }
+        return connectTreble();
+    }
+    if (trebleFlag != nullptr) {
+        *trebleFlag = false;
+    }
+    return connectLegacy();
+}
+
+status_t OMXClient::connect(const char* name, bool* trebleFlag) {
+    if (property_get_bool("persist.media.treble_omx", true)) {
+        if (trebleFlag != nullptr) {
+            *trebleFlag = true;
+        }
+        return connectTreble(name);
+    }
+    if (trebleFlag != nullptr) {
+        *trebleFlag = false;
+    }
+    return connectLegacy();
+}
+
+status_t OMXClient::connectLegacy() {
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> codecbinder = sm->getService(String16("media.codec"));
+    sp<IMediaCodecService> codecservice = interface_cast<IMediaCodecService>(codecbinder);
+
+    if (codecservice.get() == NULL) {
+        ALOGE("Cannot obtain IMediaCodecService");
+        return NO_INIT;
+    }
+
+    mOMX = codecservice->getOMX();
+    if (mOMX.get() == NULL) {
+        ALOGE("Cannot obtain mediacodec IOMX");
+        return NO_INIT;
+    }
+
+    return OK;
+}
+
+status_t OMXClient::connectTreble(const char* name) {
     using namespace ::android::hardware::media::omx::V1_0;
     if (name == nullptr) {
         name = "default";
     }
     sp<IOmx> tOmx = IOmx::getService(name);
     if (tOmx.get() == nullptr) {
-        ALOGE("Cannot obtain IOmx service.");
+        ALOGE("Cannot obtain Treble IOmx.");
         return NO_INIT;
     }
     if (!tOmx->isRemote()) {
-        ALOGE("IOmx service running in passthrough mode.");
+        ALOGE("Treble IOmx is in passthrough mode.");
         return NO_INIT;
     }
     mOMX = new utils::LWOmx(tOmx);
-    ALOGI("IOmx service obtained");
+    ALOGI("Treble IOmx obtained");
     return OK;
 }
 
@@ -59,8 +109,4 @@
     mOMX.clear();
 }
 
-sp<IOMX> OMXClient::interface() {
-    return mOMX;
-}
-
 }  // namespace android
diff --git a/media/libstagefright/OmxInfoBuilder.cpp b/media/libstagefright/OmxInfoBuilder.cpp
index c174371..063d13e 100644
--- a/media/libstagefright/OmxInfoBuilder.cpp
+++ b/media/libstagefright/OmxInfoBuilder.cpp
@@ -24,6 +24,8 @@
 #include <utils/Log.h>
 #include <cutils/properties.h>
 
+#include <binder/IServiceManager.h>
+#include <media/IMediaCodecService.h>
 #include <media/stagefright/foundation/MediaDefs.h>
 #include <media/stagefright/OmxInfoBuilder.h>
 #include <media/stagefright/ACodec.h>
@@ -33,6 +35,7 @@
 #include <android/hardware/media/omx/1.0/IOmxNode.h>
 #include <media/stagefright/omx/OMXUtils.h>
 
+#include <media/IOMXStore.h>
 #include <media/IOMX.h>
 #include <media/omx/1.0/WOmx.h>
 
@@ -45,18 +48,10 @@
 
 namespace android {
 
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using namespace ::android::hardware::media::omx::V1_0;
-
 namespace /* unnamed */ {
 
-bool hasPrefix(const hidl_string& s, const char* prefix) {
-    return strncmp(s.c_str(), prefix, strlen(prefix)) == 0;
-}
-
 status_t queryCapabilities(
-        const IOmxStore::NodeInfo& node, const char* mime, bool isEncoder,
+        const IOMXStore::NodeInfo& node, const char* mime, bool isEncoder,
         MediaCodecInfo::CapabilitiesWriter* caps) {
     sp<ACodec> codec = new ACodec();
     status_t err = codec->queryCapabilities(
@@ -67,13 +62,14 @@
     for (const auto& attribute : node.attributes) {
         // All features have an int32 value except
         // "feature-bitrate-modes", which has a string value.
-        if (hasPrefix(attribute.key, "feature-") &&
-                !hasPrefix(attribute.key, "feature-bitrate-modes")) {
-            // If this attribute.key is a feature that is not bitrate modes,
-            // add an int32 value.
+        if ((attribute.key.compare(0, 8, "feature-") == 0) &&
+                (attribute.key.compare(8, 15, "bitrate-modes")
+                 != 0)) {
+            // If this attribute.key is a feature that is not a bitrate
+            // control, add an int32 value.
             caps->addDetail(
                     attribute.key.c_str(),
-                    hasPrefix(attribute.value, "1") ? 1 : 0);
+                    attribute.value == "1" ? 1 : 0);
         } else {
             // Non-feature attributes
             caps->addDetail(
@@ -89,53 +85,138 @@
 }
 
 status_t OmxInfoBuilder::buildMediaCodecList(MediaCodecListWriter* writer) {
-    hidl_vec<IOmxStore::RoleInfo> roles;
+    bool treble;
+    sp<IOMX> omx;
+    std::vector<IOMXStore::RoleInfo> roles;
 
-    // Obtain IOmxStore
-    sp<IOmxStore> omxStore = IOmxStore::getService();
-    if (omxStore == nullptr) {
-        ALOGE("Cannot find an IOmxStore service.");
-        return NO_INIT;
-    }
+    treble = property_get_bool("persist.media.treble_omx", true);
+    if (treble) {
+        using namespace ::android::hardware::media::omx::V1_0;
+        using ::android::hardware::hidl_vec;
+        using ::android::hardware::hidl_string;
 
-    // List service attributes (global settings)
-    Status status;
-    hidl_vec<IOmxStore::ServiceAttribute> serviceAttributes;
-    auto transStatus = omxStore->listServiceAttributes(
-            [&status, &serviceAttributes] (
-            Status inStatus,
-            const hidl_vec<IOmxStore::ServiceAttribute>& inAttributes) {
-                status = inStatus;
-                serviceAttributes = inAttributes;
-            });
-    if (!transStatus.isOk()) {
-        ALOGE("Fail to obtain global settings from IOmxStore.");
-        return NO_INIT;
-    }
-    if (status != Status::OK) {
-        ALOGE("IOmxStore reports parsing error.");
-        return NO_INIT;
-    }
-    for (const auto& p : serviceAttributes) {
-        writer->addGlobalSetting(
-                p.key.c_str(), p.value.c_str());
-    }
+        // Obtain IOmxStore
+        sp<IOmxStore> omxStore = IOmxStore::getService();
+        if (omxStore == nullptr) {
+            ALOGE("Cannot connect to an IOmxStore instance.");
+            return NO_INIT;
+        }
 
-    transStatus = omxStore->listRoles(
-            [&roles] (
-            const hidl_vec<IOmxStore::RoleInfo>& inRoleList) {
-                roles = inRoleList;
-            });
-    if (!transStatus.isOk()) {
-        ALOGE("Fail to obtain codec roles from IOmxStore.");
-        return NO_INIT;
+        // List service attributes (global settings)
+        Status status;
+        hidl_vec<IOmxStore::ServiceAttribute> serviceAttributes;
+        auto transStatus = omxStore->listServiceAttributes(
+                [&status, &serviceAttributes]
+                (Status inStatus, const hidl_vec<IOmxStore::ServiceAttribute>&
+                        inAttributes) {
+                    status = inStatus;
+                    serviceAttributes = inAttributes;
+                });
+        if (!transStatus.isOk()) {
+            ALOGE("Fail to obtain global settings from IOmxStore.");
+            return NO_INIT;
+        }
+        if (status != Status::OK) {
+            ALOGE("IOmxStore reports parsing error.");
+            return NO_INIT;
+        }
+        for (const auto& p : serviceAttributes) {
+            writer->addGlobalSetting(
+                    p.key.c_str(), p.value.c_str());
+        }
+
+        // List roles and convert to IOMXStore's format
+        transStatus = omxStore->listRoles(
+                [&roles]
+                (const hidl_vec<IOmxStore::RoleInfo>& inRoleList) {
+                    roles.reserve(inRoleList.size());
+                    for (const auto& inRole : inRoleList) {
+                        IOMXStore::RoleInfo role;
+                        role.role = inRole.role;
+                        role.type = inRole.type;
+                        role.isEncoder = inRole.isEncoder;
+                        role.preferPlatformNodes = inRole.preferPlatformNodes;
+                        std::vector<IOMXStore::NodeInfo>& nodes =
+                                role.nodes;
+                        nodes.reserve(inRole.nodes.size());
+                        for (const auto& inNode : inRole.nodes) {
+                            IOMXStore::NodeInfo node;
+                            node.name = inNode.name;
+                            node.owner = inNode.owner;
+                            std::vector<IOMXStore::Attribute>& attributes =
+                                    node.attributes;
+                            attributes.reserve(inNode.attributes.size());
+                            for (const auto& inAttr : inNode.attributes) {
+                                IOMXStore::Attribute attr;
+                                attr.key = inAttr.key;
+                                attr.value = inAttr.value;
+                                attributes.push_back(std::move(attr));
+                            }
+                            nodes.push_back(std::move(node));
+                        }
+                        roles.push_back(std::move(role));
+                    }
+                });
+        if (!transStatus.isOk()) {
+            ALOGE("Fail to obtain codec roles from IOmxStore.");
+            return NO_INIT;
+        }
+    } else {
+        // Obtain IOMXStore
+        sp<IServiceManager> sm = defaultServiceManager();
+        if (sm == nullptr) {
+            ALOGE("Cannot obtain the default service manager.");
+            return NO_INIT;
+        }
+        sp<IBinder> codecBinder = sm->getService(String16("media.codec"));
+        if (codecBinder == nullptr) {
+            ALOGE("Cannot obtain the media codec service.");
+            return NO_INIT;
+        }
+        sp<IMediaCodecService> codecService =
+                interface_cast<IMediaCodecService>(codecBinder);
+        if (codecService == nullptr) {
+            ALOGE("Wrong type of media codec service obtained.");
+            return NO_INIT;
+        }
+        omx = codecService->getOMX();
+        if (omx == nullptr) {
+            ALOGE("Cannot connect to an IOMX instance.");
+        }
+        sp<IOMXStore> omxStore = codecService->getOMXStore();
+        if (omxStore == nullptr) {
+            ALOGE("Cannot connect to an IOMXStore instance.");
+            return NO_INIT;
+        }
+
+        // List service attributes (global settings)
+        std::vector<IOMXStore::Attribute> serviceAttributes;
+        status_t status = omxStore->listServiceAttributes(&serviceAttributes);
+        if (status != OK) {
+            ALOGE("Fail to obtain global settings from IOMXStore.");
+            return NO_INIT;
+        }
+        for (const auto& p : serviceAttributes) {
+            writer->addGlobalSetting(
+                    p.key.c_str(), p.value.c_str());
+        }
+
+        // List roles
+        status = omxStore->listRoles(&roles);
+        if (status != OK) {
+            ALOGE("Fail to obtain codec roles from IOMXStore.");
+            return NO_INIT;
+        }
     }
 
     // Convert roles to lists of codecs
 
-    // codec name -> index into swCodecs/hwCodecs
-    std::map<hidl_string, std::unique_ptr<MediaCodecInfoWriter>>
-            swCodecName2Info, hwCodecName2Info;
+    // codec name -> index into swCodecs
+    std::map<std::string, std::unique_ptr<MediaCodecInfoWriter> >
+            swCodecName2Info;
+    // codec name -> index into hwCodecs
+    std::map<std::string, std::unique_ptr<MediaCodecInfoWriter> >
+            hwCodecName2Info;
     // owner name -> MediaCodecInfo
     // This map will be used to obtain the correct IOmx service(s) needed for
     // creating IOmxNode instances and querying capabilities.
@@ -149,10 +230,10 @@
         // If preferPlatformNodes is true, hardware nodes must be added after
         // platform (software) nodes. hwCodecs is used to hold hardware nodes
         // that need to be added after software nodes for the same role.
-        std::vector<const IOmxStore::NodeInfo*> hwCodecs;
+        std::vector<const IOMXStore::NodeInfo*> hwCodecs;
         for (const auto& node : role.nodes) {
             const auto& nodeName = node.name;
-            bool isSoftware = hasPrefix(nodeName, "OMX.google");
+            bool isSoftware = nodeName.compare(0, 10, "OMX.google") == 0;
             MediaCodecInfoWriter* info;
             if (isSoftware) {
                 auto c2i = swCodecName2Info.find(nodeName);
diff --git a/media/libstagefright/codec2/include/C2.h b/media/libstagefright/codec2/include/C2.h
index 7d00a03..bd563ff 100644
--- a/media/libstagefright/codec2/include/C2.h
+++ b/media/libstagefright/codec2/include/C2.h
@@ -66,8 +66,8 @@
  * mitigate binary breaks by adhering to the following conventions:
  *
  * - at most one vtable with placeholder virtual methods
- * - all optional/placeholder virtual methods returning a status_t, with C2_NOT_IMPLEMENTED not
- *   requiring any update to input/output arguments.
+ * - all optional/placeholder virtual methods returning a C2Status, with C2_OMITTED not requiring
+ *   any update to input/output arguments.
  * - limiting symbol export of inline methods
  * - use of pimpl (or shared-pimpl)
  *
@@ -98,49 +98,62 @@
  * C2String: basic string implementation
  */
 typedef std::string C2String;
+
+/**
+ * C2StringLiteral: basic string literal implementation.
+ * \note these are never owned by any object, and can only refer to C string literals.
+ */
 typedef const char *C2StringLiteral;
 
 /**
- * C2Error: status codes used.
+ * C2Status: status codes used.
  */
-typedef int32_t C2Error;
-enum {
+enum C2Status : int32_t {
+
+/*
+ * Use android status constants if available. Otherwise, define the android status constants as
+ * additional enum values using POSIX errno constants.
+ */
 #ifndef __ANDROID__
-    OK                  = 0,
+    ALREADY_EXISTS      = -EEXIST,
     BAD_VALUE           = -EINVAL,
     BAD_INDEX           = -EOVERFLOW,
-    UNKNOWN_TRANSACTION = -EBADMSG,
-    ALREADY_EXISTS      = -EEXIST,
-    NAME_NOT_FOUND      = -ENOENT,
+    FAILED_TRANSACTION  = -ENOTSUP,
     INVALID_OPERATION   = -ENOSYS,
+    NAME_NOT_FOUND      = -ENOENT,
     NO_MEMORY           = -ENOMEM,
+    NO_INIT             = -ENODEV,
+    OK                  = 0,
     PERMISSION_DENIED   = -EPERM,
     TIMED_OUT           = -ETIMEDOUT,
-    UNKNOWN_ERROR       = -EINVAL,
+    UNKNOWN_ERROR       = -EFAULT,
+    UNKNOWN_TRANSACTION = -EBADMSG,
 #endif
 
-    C2_OK               = OK,                   ///< operation completed successfully
+    C2_OK        = OK,                   ///< operation completed successfully
 
     // bad input
-    C2_BAD_VALUE        = BAD_VALUE,            ///< argument has invalid value (user error)
-    C2_BAD_INDEX        = BAD_INDEX,            ///< argument uses invalid index (user error)
-    C2_UNSUPPORTED      = UNKNOWN_TRANSACTION,  ///< argument/index is value but not supported \todo is this really BAD_INDEX/VALUE?
+    C2_BAD_VALUE = BAD_VALUE,            ///< argument has invalid value (user error)
+    C2_BAD_INDEX = BAD_INDEX,            ///< argument uses invalid index (user error)
+    C2_CANNOT_DO = FAILED_TRANSACTION,   ///< argument/index is valid but not possible
 
     // bad sequencing of events
-    C2_DUPLICATE        = ALREADY_EXISTS,       ///< object already exists
-    C2_NOT_FOUND        = NAME_NOT_FOUND,       ///< object not found
-    C2_BAD_STATE        = INVALID_OPERATION,    ///< operation is not permitted in the current state
+    C2_DUPLICATE = ALREADY_EXISTS,       ///< object already exists
+    C2_NOT_FOUND = NAME_NOT_FOUND,       ///< object not found
+    C2_BAD_STATE = INVALID_OPERATION,    ///< operation is not permitted in the current state
 
     // bad environment
-    C2_NO_MEMORY        = NO_MEMORY,            ///< not enough memory to complete operation
-    C2_NO_PERMISSION    = PERMISSION_DENIED,    ///< missing permission to complete operation
-    C2_TIMED_OUT        = TIMED_OUT,            ///< operation did not complete within timeout
+    C2_NO_MEMORY = NO_MEMORY,            ///< not enough memory to complete operation
+    C2_REFUSED   = PERMISSION_DENIED,    ///< missing permission to complete operation
+
+    C2_TIMED_OUT = TIMED_OUT,            ///< operation did not complete within timeout
 
     // bad versioning
-    C2_NOT_IMPLEMENTED  = UNKNOWN_TRANSACTION,  ///< operation is not implemented (optional only) \todo for now reuse error code
+    C2_OMITTED   = UNKNOWN_TRANSACTION,  ///< operation is not implemented/supported (optional only)
 
     // unknown fatal
-    C2_CORRUPTED        = UNKNOWN_ERROR,        ///< some unexpected error prevented the operation
+    C2_CORRUPTED = UNKNOWN_ERROR,        ///< some unexpected error prevented the operation
+    C2_NO_INIT   = NO_INIT,              ///< status has not been initialized
 };
 
 /// @}
diff --git a/media/libstagefright/codec2/include/C2Buffer.h b/media/libstagefright/codec2/include/C2Buffer.h
index 9580449..cb8c2d2 100644
--- a/media/libstagefright/codec2/include/C2Buffer.h
+++ b/media/libstagefright/codec2/include/C2Buffer.h
@@ -88,10 +88,10 @@
      * \retval C2_TIMED_OUT     the fence has not been signaled within the timeout
      * \retval C2_BAD_STATE     the fence has been abandoned without being signaled (it will never
      *                          be signaled)
-     * \retval C2_NO_PERMISSION no permission to wait for the fence (unexpected - system)
+     * \retval C2_REFUSED       no permission to wait for the fence (unexpected - system)
      * \retval C2_CORRUPTED     some unknown error prevented waiting for the fence (unexpected)
      */
-    C2Error wait(nsecs_t timeoutNs);
+    C2Status wait(nsecs_t timeoutNs);
 
     /**
      * Used to check if this fence is valid (if there is a chance for it to be signaled.)
@@ -155,10 +155,10 @@
      * \retval C2_OK            the fence(s) were successfully signaled
      * \retval C2_BAD_STATE     the fence(s) have already been abandoned or merged (caller error)
      * \retval C2_DUPLICATE     the fence(s) have already been signaled (caller error)
-     * \retval C2_NO_PERMISSION no permission to signal the fence (unexpected - system)
+     * \retval C2_REFUSED       no permission to signal the fence (unexpected - system)
      * \retval C2_CORRUPTED     some unknown error prevented signaling the fence(s) (unexpected)
      */
-    C2Error fire();
+    C2Status fire();
 
     /**
      * Trigger this event from the merging of the supplied fences. This means that it will be
@@ -169,10 +169,10 @@
      * \retval C2_NO_MEMORY     not enough memory to perform the merging
      * \retval C2_DUPLICATE     the fence have already been merged (caller error)
      * \retval C2_BAD_STATE     the fence have already been signaled or abandoned (caller error)
-     * \retval C2_NO_PERMISSION no permission to merge the fence (unexpected - system)
+     * \retval C2_REFUSED       no permission to merge the fence (unexpected - system)
      * \retval C2_CORRUPTED     some unknown error prevented merging the fence(s) (unexpected)
      */
-    C2Error merge(std::vector<C2Fence> fences);
+    C2Status merge(std::vector<C2Fence> fences);
 
     /**
      * Abandons the event and any associated fence(s).
@@ -183,10 +183,10 @@
      * \retval C2_OK            the fence(s) were successfully signaled
      * \retval C2_BAD_STATE     the fence(s) have already been signaled or merged (caller error)
      * \retval C2_DUPLICATE     the fence(s) have already been abandoned (caller error)
-     * \retval C2_NO_PERMISSION no permission to abandon the fence (unexpected - system)
+     * \retval C2_REFUSED       no permission to abandon the fence (unexpected - system)
      * \retval C2_CORRUPTED     some unknown error prevented signaling the fence(s) (unexpected)
      */
-    C2Error abandon();
+    C2Status abandon();
 
 private:
     class Impl;
@@ -197,15 +197,15 @@
 /// @{
 
 /**
- * Interface for objects that encapsulate an updatable error value.
+ * Interface for objects that encapsulate an updatable status value.
  */
-struct _C2InnateError {
-    inline C2Error error() const { return mError; }
+struct _C2InnateStatus {
+    inline C2Status status() const { return mStatus; }
 
 protected:
-    _C2InnateError(C2Error error) : mError(error) { }
+    _C2InnateStatus(C2Status status) : mStatus(status) { }
 
-    C2Error mError; // this error is updatable by the object
+    C2Status mStatus; // this status is updatable by the object
 };
 
 /// @}
@@ -230,10 +230,10 @@
     }
 
 protected:
-    C2Acquirable(C2Error error, C2Fence fence, T t) : C2Fence(fence), mInitialError(error), mT(t) { }
+    C2Acquirable(C2Status error, C2Fence fence, T t) : C2Fence(fence), mInitialError(error), mT(t) { }
 
 private:
-    C2Error mInitialError;
+    C2Status mInitialError;
     T mT; // TODO: move instead of copy
 };
 
@@ -449,11 +449,11 @@
     /**
      * \return error during the creation/mapping of this view.
      */
-    C2Error error();
+    C2Status error() const;
 
 protected:
     C2ReadView(const _C2LinearCapacityAspect *parent, const uint8_t *data);
-    explicit C2ReadView(C2Error error);
+    explicit C2ReadView(C2Status error);
 
 private:
     class Impl;
@@ -482,11 +482,11 @@
     /**
      * \return error during the creation/mapping of this view.
      */
-    C2Error error();
+    C2Status error() const;
 
 protected:
     C2WriteView(const _C2LinearRangeAspect *parent, uint8_t *base);
-    explicit C2WriteView(C2Error error);
+    explicit C2WriteView(C2Status error);
 
 private:
     class Impl;
@@ -631,7 +631,7 @@
      * \retval C2_TIMED_OUT     the reservation timed out \todo when?
      * \retval C2_CORRUPTED     some unknown error prevented reserving space. (unexpected)
      */
-    C2Error reserve(size_t size, C2Fence *fence /* nullable */);
+    C2Status reserve(size_t size, C2Fence *fence /* nullable */);
 
     /**
      * Abandons a portion of this segment. This will move to the beginning of this segment.
@@ -644,7 +644,7 @@
      * \retval C2_TIMED_OUT     the operation timed out (unexpected)
      * \retval C2_CORRUPTED     some unknown error prevented abandoning the data (unexpected)
      */
-    C2Error abandon(size_t size);
+    C2Status abandon(size_t size);
 
     /**
      * Share a portion as block(s) with consumers (these are moved to the used section).
@@ -661,7 +661,7 @@
      * \retval C2_TIMED_OUT     the operation timed out (unexpected)
      * \retval C2_CORRUPTED     some unknown error prevented sharing the data (unexpected)
      */
-    C2Error share(size_t size, C2Fence fence, std::list<C2ConstLinearBlock> &blocks);
+    C2Status share(size_t size, C2Fence fence, std::list<C2ConstLinearBlock> &blocks);
 
     /**
      * Returns the beginning offset of this segment from the start of this circular block.
@@ -695,7 +695,7 @@
     /**
      * \return error during the creation/mapping of this view.
      */
-    C2Error error();
+    C2Status error() const;
 };
 
 /**
@@ -716,7 +716,7 @@
      * \param size    number of bytes to commit to the next segment
      * \param fence   fence used for the commit (the fence must signal before the data is committed)
      */
-    C2Error commit(size_t size, C2Fence fence);
+    C2Status commit(size_t size, C2Fence fence);
 
     /**
      * Maps this block into memory and returns a write view for it.
@@ -1016,14 +1016,14 @@
     /**
      * \return error during the creation/mapping of this view.
      */
-    C2Error error() const;
+    C2Status error() const;
 
 protected:
     C2GraphicView(
             const _C2PlanarCapacityAspect *parent,
             uint8_t *const *data,
             const C2PlaneLayout& layout);
-    explicit C2GraphicView(C2Error error);
+    explicit C2GraphicView(C2Status error);
 
 private:
     class Impl;
@@ -1224,7 +1224,7 @@
      * \retval C2_NO_MEMORY not enough memory to register for this callback
      * \retval C2_CORRUPTED an unknown error prevented the registration (unexpected)
      */
-    C2Error registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
+    C2Status registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
 
     /**
      * Unregisters a previously registered pre-destroy notification.
@@ -1236,7 +1236,7 @@
      * \retval C2_NOT_FOUND the notification was not found
      * \retval C2_CORRUPTED an unknown error prevented the registration (unexpected)
      */
-    C2Error unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
+    C2Status unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
 
     ///@}
 
@@ -1262,7 +1262,7 @@
      * \retval C2_NO_MEMORY not enough memory to attach the metadata (this return value is not
      *                      used if the same kind of metadata is already attached to the buffer).
      */
-    C2Error setInfo(const std::shared_ptr<C2Info> &info);
+    C2Status setInfo(const std::shared_ptr<C2Info> &info);
 
     /**
      * Checks if there is a certain type of metadata attached to this buffer.
@@ -1377,7 +1377,7 @@
      * \todo Do we need to support sync operation as we could just wait for the fence?
      *
      * \retval C2_OK        the operation was successful
-     * \retval C2_NO_PERMISSION no permission to map the portion
+     * \retval C2_REFUSED   no permission to map the portion
      * \retval C2_TIMED_OUT the operation timed out
      * \retval C2_DUPLICATE if the allocation is already mapped.
      * \retval C2_NO_MEMORY not enough memory to complete the operation
@@ -1385,7 +1385,7 @@
      *                      the usage flags are invalid (caller error)
      * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
      */
-    virtual C2Error map(
+    virtual C2Status map(
             size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd /* nullable */,
             void **addr /* nonnull */) = 0;
 
@@ -1407,9 +1407,9 @@
      * \retval C2_BAD_VALUE the parameters (addr/size) do not correspond to previously mapped
      *                      regions (caller error)
      * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
-     * \retval C2_NO_PERMISSION no permission to unmap the portion (unexpected - system)
+     * \retval C2_REFUSED   no permission to unmap the portion (unexpected - system)
      */
-    virtual C2Error unmap(void *addr, size_t size, int *fenceFd /* nullable */) = 0;
+    virtual C2Status unmap(void *addr, size_t size, int *fenceFd /* nullable */) = 0;
 
     /**
      * Returns true if this is a valid allocation.
@@ -1463,7 +1463,7 @@
      * \todo Do we need to support sync operation as we could just wait for the fence?
      *
      * \retval C2_OK        the operation was successful
-     * \retval C2_NO_PERMISSION no permission to map the section
+     * \retval C2_REFUSED   no permission to map the section
      * \retval C2_DUPLICATE there is already a mapped region (caller error)
      * \retval C2_TIMED_OUT the operation timed out
      * \retval C2_NO_MEMORY not enough memory to complete the operation
@@ -1472,7 +1472,7 @@
      * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
 
      */
-    virtual C2Error map(
+    virtual C2Status map(
             C2Rect rect, C2MemoryUsage usage, int *fenceFd,
             // TODO: return <addr, size> buffers with plane sizes
             C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) = 0;
@@ -1490,9 +1490,9 @@
      * \retval C2_TIMED_OUT the operation timed out
      * \retval C2_NOT_FOUND there is no mapped region (caller error)
      * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
-     * \retval C2_NO_PERMISSION no permission to unmap the section (unexpected - system)
+     * \retval C2_REFUSED   no permission to unmap the section (unexpected - system)
      */
-    virtual C2Error unmap(C2Fence *fenceFd /* nullable */) = 0;
+    virtual C2Status unmap(C2Fence *fenceFd /* nullable */) = 0;
 
     /**
      * Returns true if this is a valid allocation.
@@ -1545,16 +1545,16 @@
      * \retval C2_OK        the allocation was successful
      * \retval C2_NO_MEMORY not enough memory to complete the allocation
      * \retval C2_TIMED_OUT the allocation timed out
-     * \retval C2_NO_PERMISSION     no permission to complete the allocation
+     * \retval C2_REFUSED   no permission to complete the allocation
      * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
-     * \retval C2_UNSUPPORTED       this allocator does not support 1D allocations
+     * \retval C2_OMITTED   this allocator does not support 1D allocations
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
      */
-    virtual C2Error allocateLinearBuffer(
+    virtual C2Status allocateLinearBuffer(
             uint32_t capacity __unused, C2MemoryUsage usage __unused,
             std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
         *allocation = nullptr;
-        return C2_UNSUPPORTED;
+        return C2_OMITTED;
     }
 
     /**
@@ -1568,16 +1568,16 @@
      * \retval C2_OK        the allocation was recreated successfully
      * \retval C2_NO_MEMORY not enough memory to recreate the allocation
      * \retval C2_TIMED_OUT the recreation timed out (unexpected)
-     * \retval C2_NO_PERMISSION     no permission to recreate the allocation
+     * \retval C2_REFUSED   no permission to recreate the allocation
      * \retval C2_BAD_VALUE invalid handle (caller error)
-     * \retval C2_UNSUPPORTED       this allocator does not support 1D allocations
+     * \retval C2_OMITTED   this allocator does not support 1D allocations
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
      */
-    virtual C2Error recreateLinearBuffer(
+    virtual C2Status recreateLinearBuffer(
             const C2Handle *handle __unused,
             std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
         *allocation = nullptr;
-        return C2_UNSUPPORTED;
+        return C2_OMITTED;
     }
 
     /**
@@ -1601,17 +1601,17 @@
      * \retval C2_OK        the allocation was successful
      * \retval C2_NO_MEMORY not enough memory to complete the allocation
      * \retval C2_TIMED_OUT the allocation timed out
-     * \retval C2_NO_PERMISSION     no permission to complete the allocation
+     * \retval C2_REFUSED   no permission to complete the allocation
      * \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller error)
-     * \retval C2_UNSUPPORTED       this allocator does not support 2D allocations
+     * \retval C2_OMITTED   this allocator does not support 2D allocations
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
      */
-    virtual C2Error allocateGraphicBuffer(
+    virtual C2Status allocateGraphicBuffer(
             uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
             C2MemoryUsage usage __unused,
             std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
         *allocation = nullptr;
-        return C2_UNSUPPORTED;
+        return C2_OMITTED;
     }
 
     /**
@@ -1625,16 +1625,16 @@
      * \retval C2_OK        the allocation was recreated successfully
      * \retval C2_NO_MEMORY not enough memory to recreate the allocation
      * \retval C2_TIMED_OUT the recreation timed out (unexpected)
-     * \retval C2_NO_PERMISSION     no permission to recreate the allocation
+     * \retval C2_REFUSED   no permission to recreate the allocation
      * \retval C2_BAD_VALUE invalid handle (caller error)
-     * \retval C2_UNSUPPORTED       this allocator does not support 2D allocations
+     * \retval C2_OMITTED   this allocator does not support 2D allocations
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during recreation (unexpected)
      */
-    virtual C2Error recreateGraphicBuffer(
+    virtual C2Status recreateGraphicBuffer(
             const C2Handle *handle __unused,
             std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
         *allocation = nullptr;
-        return C2_UNSUPPORTED;
+        return C2_OMITTED;
     }
 
 protected:
@@ -1669,16 +1669,16 @@
      * \retval C2_OK        the allocation was successful
      * \retval C2_NO_MEMORY not enough memory to complete the allocation
      * \retval C2_TIMED_OUT the allocation timed out
-     * \retval C2_NO_PERMISSION     no permission to complete the allocation
+     * \retval C2_REFUSED   no permission to complete the allocation
      * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
-     * \retval C2_UNSUPPORTED       this allocator does not support linear allocations
+     * \retval C2_OMITTED   this allocator does not support linear allocations
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
      */
-    virtual C2Error allocateLinearBlock(
+    virtual C2Status allocateLinearBlock(
             uint32_t capacity __unused, C2MemoryUsage usage __unused,
             std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
         *block = nullptr;
-        return C2_UNSUPPORTED;
+        return C2_OMITTED;
     }
 
     /**
@@ -1698,16 +1698,16 @@
      * \retval C2_OK            the allocation was successful
      * \retval C2_NO_MEMORY     not enough memory to complete the allocation
      * \retval C2_TIMED_OUT     the allocation timed out
-     * \retval C2_NO_PERMISSION     no permission to complete the allocation
+     * \retval C2_REFUSED       no permission to complete the allocation
      * \retval C2_BAD_VALUE     capacity or usage are not supported (invalid) (caller error)
-     * \retval C2_UNSUPPORTED   this allocator does not support circular allocations
+     * \retval C2_OMITTED       this allocator does not support circular allocations
      * \retval C2_CORRUPTED     some unknown, unrecoverable error occured during allocation (unexpected)
      */
-    virtual C2Error allocateCircularBlock(
+    virtual C2Status allocateCircularBlock(
             uint32_t capacity __unused, C2MemoryUsage usage __unused,
             std::shared_ptr<C2CircularBlock> *block /* nonnull */) {
         *block = nullptr;
-        return C2_UNSUPPORTED;
+        return C2_OMITTED;
     }
 
     /**
@@ -1731,17 +1731,17 @@
      * \retval C2_OK            the allocation was successful
      * \retval C2_NO_MEMORY     not enough memory to complete the allocation
      * \retval C2_TIMED_OUT     the allocation timed out
-     * \retval C2_NO_PERMISSION     no permission to complete the allocation
+     * \retval C2_REFUSED       no permission to complete the allocation
      * \retval C2_BAD_VALUE     width, height, format or usage are not supported (invalid) (caller error)
-     * \retval C2_UNSUPPORTED   this allocator does not support 2D allocations
+     * \retval C2_OMITTED       this allocator does not support 2D allocations
      * \retval C2_CORRUPTED     some unknown, unrecoverable error occured during allocation (unexpected)
      */
-    virtual C2Error allocateGraphicBlock(
+    virtual C2Status allocateGraphicBlock(
             uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
             C2MemoryUsage usage __unused,
             std::shared_ptr<C2GraphicBlock> *block /* nonnull */) {
         *block = nullptr;
-        return C2_UNSUPPORTED;
+        return C2_OMITTED;
     }
 
 protected:
diff --git a/media/libstagefright/codec2/include/C2Component.h b/media/libstagefright/codec2/include/C2Component.h
index a9b1702..2ac9c72 100644
--- a/media/libstagefright/codec2/include/C2Component.h
+++ b/media/libstagefright/codec2/include/C2Component.h
@@ -55,6 +55,31 @@
     virtual ~C2ComponentListener() = default;
 };
 
+struct C2FieldSupportedValuesQuery {
+    enum Type : uint32_t {
+        POSSIBLE, ///< query all possible values regardless of other settings
+        CURRENT,  ///< query currently possible values given dependent settings
+    };
+
+    const C2ParamField field;
+    const Type type;
+    C2Status status;
+    C2FieldSupportedValues values;
+
+    C2FieldSupportedValuesQuery(const C2ParamField &field_, Type type_)
+        : field(field_), type(type_), status(C2_NO_INIT) { }
+
+    static C2FieldSupportedValuesQuery&&
+    Current(const C2ParamField &field_) {
+        return std::move(C2FieldSupportedValuesQuery(field_, CURRENT));
+    }
+
+    static C2FieldSupportedValuesQuery&&
+    Possible(const C2ParamField &field_) {
+        return std::move(C2FieldSupportedValuesQuery(field_, POSSIBLE));
+    }
+};
+
 /**
  * Component interface object. This object contains all of the configuration of a potential or
  * actual component. It can be created and used independently of an actual C2Component instance to
@@ -129,7 +154,7 @@
      * \retval C2_CORRUPTED some unknown error prevented the querying of the parameters
      *                      (unexpected)
      */
-    virtual status_t query_nb(
+    virtual C2Status query_nb(
         const std::vector<C2Param* const> &stackParams,
         const std::vector<C2Param::Index> &heapParamIndices,
         std::vector<std::unique_ptr<C2Param>>* const heapParams) const = 0;
@@ -166,7 +191,7 @@
      * \retval C2_CORRUPTED some unknown error prevented the update of the parameters
      *                      (unexpected)
      */
-    virtual status_t config_nb(
+    virtual C2Status config_nb(
             const std::vector<C2Param* const> &params,
             std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
 
@@ -205,7 +230,7 @@
      * \retval C2_CORRUPTED some unknown error prevented the update of the parameters
      *                      (unexpected)
      */
-    virtual status_t commit_sm(
+    virtual C2Status commit_sm(
             const std::vector<C2Param* const> &params,
             std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
 
@@ -225,12 +250,13 @@
      * \retval C2_OK        the tunnel was successfully created
      * \retval C2_BAD_INDEX the target component does not exist
      * \retval C2_DUPLICATE the tunnel already exists
-     * \retval C2_UNSUPPORTED  the tunnel is not supported
+     * \retval C2_OMITTED   tunneling is not supported by this component
+     * \retval C2_CANNOT_DO the specific tunnel is not supported
      *
      * \retval C2_TIMED_OUT could not create the tunnel within the time limit (unexpected)
      * \retval C2_CORRUPTED some unknown error prevented the creation of the tunnel (unexpected)
      */
-    virtual status_t createTunnel_sm(node_id targetComponent) = 0;
+    virtual C2Status createTunnel_sm(node_id targetComponent) = 0;
 
     /**
      * Releases a tunnel from this component to the target component.
@@ -246,11 +272,12 @@
      * \retval C2_OK        the tunnel was marked for release successfully
      * \retval C2_BAD_INDEX the target component does not exist
      * \retval C2_NOT_FOUND the tunnel does not exist
+     * \retval C2_OMITTED   tunneling is not supported by this component
      *
      * \retval C2_TIMED_OUT could not mark the tunnel for release within the time limit (unexpected)
      * \retval C2_CORRUPTED some unknown error prevented the release of the tunnel (unexpected)
      */
-    virtual status_t releaseTunnel_sm(node_id targetComponent) = 0;
+    virtual C2Status releaseTunnel_sm(node_id targetComponent) = 0;
 
 
     // REFLECTION MECHANISM (USED FOR EXTENSION)
@@ -273,7 +300,7 @@
      * \retval C2_OK        the operation completed successfully.
      * \retval C2_NO_MEMORY not enough memory to complete this method.
      */
-    virtual status_t getSupportedParams(
+    virtual C2Status getSupportedParams(
             std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const = 0;
 
     /**
@@ -281,9 +308,8 @@
      * \todo should this take a list considering that setting some fields may further limit other
      * fields in the same list?
      */
-    virtual status_t getSupportedValues(
-            const std::vector<const C2ParamField> &fields,
-            std::vector<C2FieldSupportedValues>* const values) const = 0;
+    virtual C2Status getSupportedValues(
+            std::vector<C2FieldSupportedValuesQuery> &fields) const = 0;
 
     virtual ~C2ComponentInterface() = default;
 };
@@ -305,12 +331,12 @@
      *
      * \retval C2_OK        the work was successfully queued
      * \retval C2_BAD_INDEX some component(s) in the work do(es) not exist
-     * \retval C2_UNSUPPORTED  the components are not tunneled
+     * \retval C2_CANNOT_DO the components are not tunneled
      *
      * \retval C2_NO_MEMORY not enough memory to queue the work
      * \retval C2_CORRUPTED some unknown error prevented queuing the work (unexpected)
      */
-    virtual status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) = 0;
+    virtual C2Status queue_nb(std::list<std::unique_ptr<C2Work>>* const items) = 0;
 
     /**
      * Announces a work to be queued later for the component. This reserves a slot for the queue
@@ -322,14 +348,14 @@
      *
      * \retval C2_OK        the work announcement has been successfully recorded
      * \retval C2_BAD_INDEX some component(s) in the work outline do(es) not exist
-     * \retval C2_UNSUPPORTED  the componentes are not tunneled
+     * \retval C2_CANNOT_DO the componentes are not tunneled
      *
      * \retval C2_NO_MEMORY not enough memory to record the work announcement
      * \retval C2_CORRUPTED some unknown error prevented recording the announcement (unexpected)
      *
      * \todo Can this be rolled into queue_nb?
      */
-    virtual status_t announce_nb(const std::vector<C2WorkOutline> &items) = 0;
+    virtual C2Status announce_nb(const std::vector<C2WorkOutline> &items) = 0;
 
     /**
      * Discards and abandons any pending work for the component, and optionally any component
@@ -361,7 +387,7 @@
      * \retval C2_TIMED_OUT the flush could not be completed within the time limit (unexpected)
      * \retval C2_CORRUPTED some unknown error prevented flushing from completion (unexpected)
      */
-    virtual status_t flush_sm(bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) = 0;
+    virtual C2Status flush_sm(bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) = 0;
 
     /**
      * Drains the component, and optionally downstream components
@@ -390,7 +416,7 @@
      * \retval C2_TIMED_OUT the flush could not be completed within the time limit (unexpected)
      * \retval C2_CORRUPTED some unknown error prevented flushing from completion (unexpected)
      */
-    virtual status_t drain_nb(bool drainThrough) = 0;
+    virtual C2Status drain_nb(bool drainThrough) = 0;
 
     // STATE CHANGE METHODS
     // =============================================================================================
@@ -411,7 +437,7 @@
      * \retval C2_TIMED_OUT the component could not be started within the time limit (unexpected)
      * \retval C2_CORRUPTED some unknown error prevented starting the component (unexpected)
      */
-    virtual status_t start() = 0;
+    virtual C2Status start() = 0;
 
     /**
      * Stops the component.
@@ -428,7 +454,7 @@
      * This does not alter any settings and tunings that may have resulted in a tripped state.
      * (Is this material given the definition? Perhaps in case we want to start again.)
      */
-    virtual status_t stop() = 0;
+    virtual C2Status stop() = 0;
 
     /**
      * Resets the component.
@@ -502,9 +528,9 @@
      * \retval C2_TIMED_OUT could not reset the parser within the time limit (unexpected)
      * \retval C2_CORRUPTED some unknown error prevented the resetting of the parser (unexpected)
      */
-    virtual status_t reset() { return C2_OK; }
+    virtual C2Status reset() { return C2_OK; }
 
-    virtual status_t parseFrame(C2BufferPack &frame);
+    virtual C2Status parseFrame(C2BufferPack &frame);
 
     virtual ~C2FrameInfoParser() = default;
 };
@@ -542,7 +568,7 @@
      * \retval C2_NOT_FOUND no such allocator
      * \retval C2_NO_MEMORY not enough memory to create the allocator
      */
-    virtual status_t createAllocator(ID id, std::shared_ptr<C2Allocator>* const allocator) = 0;
+    virtual C2Status createAllocator(ID id, std::shared_ptr<C2Allocator>* const allocator) = 0;
 
     virtual ~C2AllocatorStore() = default;
 };
@@ -565,7 +591,7 @@
      * \retval C2_NOT_FOUND no such component
      * \retval C2_NO_MEMORY not enough memory to create the component
      */
-    virtual status_t createComponent(C2String name, std::shared_ptr<C2Component>* const component);
+    virtual C2Status createComponent(C2String name, std::shared_ptr<C2Component>* const component);
 
     /**
      * Creates a component interface.
@@ -586,7 +612,7 @@
      *
      * \todo Do we need an interface, or could this just be a component that is never started?
      */
-    virtual status_t createInterface(C2String name, std::shared_ptr<C2ComponentInterface>* const interface);
+    virtual C2Status createInterface(C2String name, std::shared_ptr<C2ComponentInterface>* const interface);
 
     /**
      * Returns the list of components supported by this component store.
@@ -600,9 +626,9 @@
     // -------------------------------------- UTILITY METHODS --------------------------------------
 
     // on-demand buffer layout conversion (swizzling)
-    virtual status_t copyBuffer(std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst);
+    virtual C2Status copyBuffer(std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst);
 
-    // status_t selectPreferredColor(formats<A>, formats<B>);
+    // C2Status selectPreferredColor(formats<A>, formats<B>);
 
     // GLOBAL SETTINGS
     // system-wide stride & slice-height (???)
@@ -636,7 +662,7 @@
      * \retval C2_CORRUPTED some unknown error prevented the querying of the parameters
      *                      (unexpected)
      */
-    virtual status_t query_sm(
+    virtual C2Status query_sm(
         const std::vector<C2Param* const> &stackParams,
         const std::vector<C2Param::Index> &heapParamIndices,
         std::vector<std::unique_ptr<C2Param>>* const heapParams) const = 0;
@@ -675,7 +701,7 @@
      * \retval C2_CORRUPTED some unknown error prevented the update of the parameters
      *                      (unexpected)
      */
-    virtual status_t config_nb(
+    virtual C2Status config_nb(
             const std::vector<C2Param* const> &params,
             std::list<std::unique_ptr<C2SettingResult>>* const failures) = 0;
 
diff --git a/media/libstagefright/codec2/include/C2Param.h b/media/libstagefright/codec2/include/C2Param.h
index 02403c5..f0b92a3 100644
--- a/media/libstagefright/codec2/include/C2Param.h
+++ b/media/libstagefright/codec2/include/C2Param.h
@@ -344,6 +344,10 @@
     /// returns the parameter type: the parameter index without the stream ID
     inline uint32_t type() const { return _mIndex.type(); }
 
+    /// returns the index of this parameter
+    /// \todo: should we restrict this to C2ParamField?
+    inline uint32_t index() const { return (uint32_t)_mIndex; }
+
     /// returns the kind of this parameter
     inline Kind kind() const { return _mIndex.kind(); }
 
@@ -562,7 +566,6 @@
     /**
      * Constructor used to identify a field in an object.
      *
-     * \param U[type] pointer to the object that contains this field
      * \param pm[im] member pointer to the field
      */
     template<typename R, typename T, typename B=typename std::remove_extent<R>::type>
@@ -597,23 +600,93 @@
 };
 
 /**
- * Structure uniquely specifying a field in a configuration
+ * Structure uniquely specifying a 'field' in a configuration. The field
+ * can be a field of a configuration, a subfield of a field of a configuration,
+ * and even the whole configuration. Moreover, if the field can point to an
+ * element in a array field, or to the entire array field.
+ *
+ * This structure is used for querying supported values for a field, as well
+ * as communicating configuration failures and conflicts when trying to change
+ * a configuration for a component/interface or a store.
  */
 struct C2ParamField {
 //public:
-    // TODO: fix what this is for T[] (for now size becomes T[1])
+    /**
+     * Create a field identifier using a configuration parameter (variable),
+     * and a pointer to member.
+     *
+     * ~~~~~~~~~~~~~ (.cpp)
+     *
+     * struct C2SomeParam {
+     *   uint32_t mField;
+     *   uint32_t mArray[2];
+     *   C2OtherStruct mStruct;
+     *   uint32_t mFlexArray[];
+     * } *mParam;
+     *
+     * C2ParamField(mParam, &mParam->mField);
+     * C2ParamField(mParam, &mParam->mArray);
+     * C2ParamField(mParam, &mParam->mArray[0]);
+     * C2ParamField(mParam, &mParam->mStruct.mSubField);
+     * C2ParamField(mParam, &mParam->mFlexArray);
+     * C2ParamField(mParam, &mParam->mFlexArray[2]);
+     *
+     * ~~~~~~~~~~~~~
+     *
+     * \todo fix what this is for T[] (for now size becomes T[1])
+     *
+     * \param param pointer to parameter
+     * \param offset member pointer
+     */
     template<typename S, typename T>
     inline C2ParamField(S* param, T* offset)
         : _mIndex(param->index()),
           _mFieldId(offset) {}
 
+    /**
+     * Create a field identifier using a configuration parameter (variable),
+     * and a member pointer. This method cannot be used to refer to an
+     * array element or a subfield.
+     *
+     * ~~~~~~~~~~~~~ (.cpp)
+     *
+     * C2SomeParam mParam;
+     * C2ParamField(&mParam, &C2SomeParam::mMemberField);
+     *
+     * ~~~~~~~~~~~~~
+     *
+     * \param p pointer to parameter
+     * \param T member pointer to the field member
+     */
     template<typename R, typename T, typename U>
-    inline C2ParamField(U *p, R T::* pm) : _mIndex(p->type()), _mFieldId(p, pm) { }
+    inline C2ParamField(U *p, R T::* pm) : _mIndex(p->index()), _mFieldId(p, pm) { }
 
+    /**
+     * Create a field identifier to a configuration parameter (variable).
+     *
+     * ~~~~~~~~~~~~~ (.cpp)
+     *
+     * C2SomeParam mParam;
+     * C2ParamField(&mParam);
+     *
+     * ~~~~~~~~~~~~~
+     *
+     * \param param pointer to parameter
+     */
+    template<typename S>
+    inline C2ParamField(S* param)
+        : _mIndex(param->index()), _mFieldId(0u, param->size()) {}
+
+    /**
+     * Equality operator.
+     */
     inline bool operator==(const C2ParamField &other) const {
         return _mIndex == other._mIndex && _mFieldId == other._mFieldId;
     }
 
+    /**
+     * Ordering operator.
+     */
     inline bool operator<(const C2ParamField &other) const {
         return _mIndex < other._mIndex ||
             (_mIndex == other._mIndex && _mFieldId < other._mFieldId);
@@ -622,8 +695,8 @@
     DEFINE_OTHER_COMPARISON_OPERATORS(C2ParamField)
 
 private:
-    C2Param::Index _mIndex;
-    _C2FieldId _mFieldId;
+    C2Param::Index _mIndex; ///< parameter index
+    _C2FieldId _mFieldId;   ///< field identifier
 };
 
 /**
@@ -1153,6 +1226,7 @@
 struct C2FieldSupportedValues {
 //public:
     enum Type {
+        EMPTY,      ///< no supported values
         RANGE,      ///< a numeric range that can be continuous or discrete
         VALUES,     ///< a list of values
         FLAGS       ///< a list of flags that can be OR-ed
@@ -1171,6 +1245,10 @@
     } range;
     std::vector<Primitive> values;
 
+    C2FieldSupportedValues()
+        : type(EMPTY) {
+    }
+
     template<typename T>
     C2FieldSupportedValues(T min, T max, T step = T(std::is_floating_point<T>::value ? 0 : 1))
         : type(RANGE),
@@ -1199,6 +1277,9 @@
         }
     }
 
+    /// \internal
+    /// \todo: create separate values vs. flags initializer as for flags we want
+    /// to list both allowed and disallowed flags
     template<typename T, typename E=decltype(C2FieldDescriptor::namedValuesFor(*(T*)0))>
     C2FieldSupportedValues(bool flags, const T*)
         : type(flags ? FLAGS : VALUES),
@@ -1210,6 +1291,21 @@
     }
 };
 
+/**
+ * Spported values for a specific field.
+ *
+ * This is a pair of the field specifier together with an optional supported values object.
+ * This structure is used when reporting parameter configuration failures and conflicts.
+ */
+struct C2ParamFieldValues {
+    C2ParamField paramOrField; ///< the field or parameter
+    /// optional supported values for the field if paramOrField specifies an actual field that is
+    /// numeric (non struct, blob or string). Supported values for arrays (including string and
+    /// blobs) describe the supported values for each element (character for string, and bytes for
+    /// blobs). It is optional for read-only strings and blobs.
+    std::unique_ptr<C2FieldSupportedValues> values;
+};
+
 /// @}
 
 }  // namespace android
diff --git a/media/libstagefright/codec2/include/C2Work.h b/media/libstagefright/codec2/include/C2Work.h
index a378623..69c16ab 100644
--- a/media/libstagefright/codec2/include/C2Work.h
+++ b/media/libstagefright/codec2/include/C2Work.h
@@ -28,28 +28,47 @@
 #include <list>
 #include <vector>
 
-typedef int status_t;
-
 namespace android {
 
 /// \defgroup work Work and data processing
 /// @{
 
+/**
+ * Information describing the reason a parameter settings may fail, or
+ * may be overriden.
+ */
 struct C2SettingResult {
-    enum Failure {
+    enum Failure : uint32_t {
         READ_ONLY,  ///< parameter is read-only and cannot be set
         MISMATCH,   ///< parameter mismatches input data
         BAD_VALUE,  ///< parameter does not accept value
         BAD_TYPE,   ///< parameter is not supported
         BAD_PORT,   ///< parameter is not supported on the specific port
         BAD_INDEX,  ///< parameter is not supported on the specific stream
-        CONFLICT,   ///< parameter is in conflict with another setting
+        CONFLICT,   ///< parameter is in conflict with an/other setting(s)
+        /// parameter is out of range due to other settings (this failure mode
+        /// can only be used for strict parameters)
+        UNSUPPORTED,
+
+
+        /// requested parameter value is in conflict with an/other setting(s)
+        /// and has been corrected to the closest supported value. This failure
+        /// mode is given to provide suggestion to the client as to how to
+        /// enable the requested parameter value.
+        INFO_CONFLICT,
     };
 
-    C2ParamField field;
-    Failure failure;
-    std::unique_ptr<C2FieldSupportedValues> supportedValues; //< if different from normal (e.g. in conflict w/another param or input data)
-    std::list<C2ParamField> conflictingFields;
+    Failure failure;    ///< failure code
+
+    /// Failing (or corrected) field. Currently supported values for the field. This is set if
+    /// different from the globally supported values (e.g. due to restrictions by another param or
+    /// input data)
+    /// \todo need to define suggestions for masks to be set and unset.
+    C2ParamFieldValues field;
+
+    /// Conflicting parameters or fields with optional suggestions with (optional) suggested values
+    /// for any conflicting fields to avoid the conflict.
+    std::list<C2ParamFieldValues> conflicts;
 };
 
 // ================================================================================================
@@ -146,7 +165,7 @@
     std::list<std::unique_ptr<C2Worklet>> worklets;
 
     uint32_t worklets_processed;
-    status_t result;
+    C2Status result;
 };
 
 struct C2WorkOutline {
diff --git a/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp b/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp
index 0c8ca3e..b725d76 100644
--- a/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp
+++ b/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp
@@ -112,11 +112,11 @@
     // check if a component has a parameter whose type is |T|.
     // If a component has, the value should be copied into an argument, that is
     // |p| in queryOnStack() and |heapParams| in queryOnHeap().
-    // The return value is status_t (e.g. C2_OK).
-    template <typename T> status_t queryOnStack(T *const p);
+    // The return value is C2Status (e.g. C2_OK).
+    template <typename T> C2Status queryOnStack(T *const p);
 
     template <typename T>
-    status_t queryOnHeap(const T &p,
+    C2Status queryOnHeap(const T &p,
                          std::vector<std::unique_ptr<C2Param>> *const heapParams);
 
     // Get a value whose type is |T| in a component. The value is copied to |param|.
@@ -139,7 +139,7 @@
     // Execute an interface's config_nb(). |T| is a single parameter type, not std::vector.
     // config() creates std::vector<C2Param *const> {p} and passes it to config_nb().
     template <typename T>
-    status_t
+    C2Status
     config(T *const p,
            std::vector<std::unique_ptr<C2SettingResult>> *const failures);
 
@@ -150,7 +150,7 @@
     // Test if config works correctly for writable parameters.
     // This changes the parameter's value to |newParam|.
     // |stConfig| is a return value of config().
-    template <typename T> void configWritableParamValidValue(const T &newParam, status_t *stConfig);
+    template <typename T> void configWritableParamValidValue(const T &newParam, C2Status *stConfig);
 
     // Test if config works correctly in the case an invalid value |newParam| is tried to write
     // to an writable parameter.
@@ -162,7 +162,7 @@
     //                   config() should be failed if these values are used as new values.
     // This function should be called only for writable and supported parameters.
     template <typename TField>
-    void getTestValues(const std::vector<C2FieldSupportedValues> &validValueInfos,
+    void getTestValues(const C2FieldSupportedValues &validValueInfos,
                        std::vector<TField> *const validValues,
                        std::vector<TField> *const invalidValues);
 
@@ -194,13 +194,13 @@
         }                                               \
     } while (false)
 
-template <typename T> status_t C2CompIntfTest::queryOnStack(T *const p) {
+template <typename T> C2Status C2CompIntfTest::queryOnStack(T *const p) {
     std::vector<C2Param *const> stackParams{p};
     return mIntf->query_nb(stackParams, {}, nullptr);
 }
 
 template <typename T>
-status_t C2CompIntfTest::queryOnHeap(
+C2Status C2CompIntfTest::queryOnHeap(
         const T &p, std::vector<std::unique_ptr<C2Param>> *const heapParams) {
     uint32_t index = p.type();
     if (p.forStream()) {
@@ -258,7 +258,7 @@
 }
 
 template <typename T>
-status_t C2CompIntfTest::config(
+C2Status C2CompIntfTest::config(
         T *const p, std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
     std::vector<C2Param *const> params{p};
     return mIntf->config_nb(params, failures);
@@ -286,7 +286,7 @@
 }
 
 template <typename T>
-void C2CompIntfTest::configWritableParamValidValue(const T &newParam, status_t *configResult) {
+void C2CompIntfTest::configWritableParamValidValue(const T &newParam, C2Status *configResult) {
     std::unique_ptr<T> p = makeParamFrom(newParam);
 
     std::vector<C2Param *const> params{p.get()};
@@ -297,7 +297,7 @@
     // because there may be dependent limitations between fields or between parameters.
     // TODO(hiroh): I have to fill the return value. Comments in C2Component.h doesn't mention
     // about the return value when conflict happens. I set C2_BAD_VALUE to it temporarily now.
-    status_t stConfig = mIntf->config_nb(params, &failures);
+    C2Status stConfig = mIntf->config_nb(params, &failures);
     if (stConfig == C2_OK) {
         EXPECT_EQ(0u, failures.size());
     } else {
@@ -325,7 +325,7 @@
 // If another field type is added, it is necessary to add function for that.
 template <>
 void C2CompIntfTest::getTestValues(
-        const std::vector<C2FieldSupportedValues> &validValueInfos,
+        const C2FieldSupportedValues &validValueInfos,
         std::vector<C2DomainKind> *const validValues,
         std::vector<C2DomainKind> *const invalidValues) {
     UNUSED(validValueInfos);
@@ -339,7 +339,7 @@
 
 template <typename TField>
 void C2CompIntfTest::getTestValues(
-        const std::vector<C2FieldSupportedValues> &validValueInfos,
+        const C2FieldSupportedValues &validValueInfos,
         std::vector<TField> *const validValues,
         std::vector<TField> *const invalidValues) {
 
@@ -366,9 +366,14 @@
     };
 
     // The size of validValueInfos is one.
-    const auto &c2FSV = validValueInfos[0];
+    const auto &c2FSV = validValueInfos;
 
     switch (c2FSV.type) {
+    case C2FieldSupportedValues::Type::EMPTY: {
+        invalidValues->emplace_back(TField(0));
+        // TODO(hiroh) : Should other invalid values be tested?
+        break;
+    }
     case C2FieldSupportedValues::Type::RANGE: {
         const auto &range = c2FSV.range;
         auto rmin = prim2Value(range.min);
@@ -476,7 +481,7 @@
         TParam *const param, TRealField *const writableField,
         const std::vector<TField> &validValues,
         const std::vector<TField> &invalidValues) {
-    status_t stConfig;
+    C2Status stConfig;
 
     // Get the parameter's value in the beginning in order to reset the value at the end.
     TRACED_FAILURE(getValue(param));
@@ -550,7 +555,7 @@
     std::vector<std::unique_ptr<C2SettingResult>> failures;
     // Config does not change the parameter, because param is the present param.
     // This config is executed to find out if a parameter is read-only or writable.
-    status_t stStack = config(param.get(), &failures);
+    C2Status stStack = config(param.get(), &failures);
     if (stStack == C2_BAD_VALUE) {
         // Read-only
         std::unique_ptr<T> newParam = makeParam<T>();
@@ -584,15 +589,16 @@
 #define TEST_GENERAL_WRITABLE_FIELD(TParam_, field_type_name_, field_name_) \
     do {                                                                \
         std::unique_ptr<TParam_> param = makeParam<TParam_>();          \
-        std::vector<C2FieldSupportedValues> validValueInfos;            \
+        std::vector<C2FieldSupportedValuesQuery> validValueInfos = {    \
+            C2FieldSupportedValuesQuery::Current(                       \
+                    C2ParamField(param.get(), &field_type_name_::field_name_)) \
+        };                                                              \
         ASSERT_EQ(C2_OK,                                                \
-                  mIntf->getSupportedValues(                            \
-                          {C2ParamField(param.get(), &field_type_name_::field_name_)}, \
-                          &validValueInfos));                           \
+                  mIntf->getSupportedValues(validValueInfos));          \
         ASSERT_EQ(1u, validValueInfos.size());                          \
         std::vector<decltype(param->field_name_)> validValues;          \
         std::vector<decltype(param->field_name_)> invalidValues;        \
-        getTestValues(validValueInfos, &validValues, &invalidValues);   \
+        getTestValues(validValueInfos[0].values, &validValues, &invalidValues);   \
         testWritableParam(param.get(), &param->field_name_, validValues,\
                           invalidValues);                               \
     } while (0)
diff --git a/media/libstagefright/codec2/tests/C2Param_test.cpp b/media/libstagefright/codec2/tests/C2Param_test.cpp
index 0e71b2a..97c5f91 100644
--- a/media/libstagefright/codec2/tests/C2Param_test.cpp
+++ b/media/libstagefright/codec2/tests/C2Param_test.cpp
@@ -2403,28 +2403,28 @@
         return 0;
     }
 
-    virtual status_t commit_sm(
+    virtual C2Status commit_sm(
             const std::vector<C2Param* const> &params,
             std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
         (void)params;
         (void)failures;
-        return C2_UNSUPPORTED;
+        return C2_OMITTED;
     }
 
-    virtual status_t config_nb(
+    virtual C2Status config_nb(
             const std::vector<C2Param* const> &params,
             std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
         (void)params;
         (void)failures;
-        return C2_UNSUPPORTED;
+        return C2_OMITTED;
     }
 
-    virtual status_t createTunnel_sm(node_id targetComponent) {
+    virtual C2Status createTunnel_sm(node_id targetComponent) {
         (void)targetComponent;
-        return C2_UNSUPPORTED;
+        return C2_OMITTED;
     }
 
-    virtual status_t query_nb(
+    virtual C2Status query_nb(
             const std::vector<C2Param* const> &stackParams,
             const std::vector<C2Param::Index> &heapParamIndices,
             std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
@@ -2466,9 +2466,9 @@
         mMyParams.insert({mDomainInfo.type(), mDomainInfo});
     }
 
-    virtual status_t releaseTunnel_sm(node_id targetComponent) {
+    virtual C2Status releaseTunnel_sm(node_id targetComponent) {
         (void)targetComponent;
-        return C2_UNSUPPORTED;
+        return C2_OMITTED;
     }
 
     class MyParamReflector : public C2ParamReflector {
@@ -2490,17 +2490,19 @@
         }
     };
 
-    virtual status_t getSupportedValues(
-            const std::vector<const C2ParamField> &fields,
-            std::vector<C2FieldSupportedValues>* const values) const {
-        for (const C2ParamField &field : fields) {
-            if (field == C2ParamField(&mDomainInfo, &C2ComponentDomainInfo::mValue)) {
-                values->push_back(C2FieldSupportedValues(
+    virtual C2Status getSupportedValues(
+            std::vector<C2FieldSupportedValuesQuery> &fields) const {
+        for (C2FieldSupportedValuesQuery &query : fields) {
+            if (query.field == C2ParamField(&mDomainInfo, &C2ComponentDomainInfo::mValue)) {
+                query.values = C2FieldSupportedValues(
                     false /* flag */,
                     &mDomainInfo.mValue
                     //,
                     //{(int32_t)C2DomainVideo}
-                ));
+                );
+                query.status = C2_OK;
+            } else {
+                query.status = C2_BAD_INDEX;
             }
         }
         return C2_OK;
@@ -2510,13 +2512,13 @@
         return std::shared_ptr<C2ParamReflector>(new MyParamReflector(this));
     }
 
-    virtual status_t getSupportedParams(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const {
+    virtual C2Status getSupportedParams(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const {
         params->push_back(std::make_shared<C2ParamDescriptor>(
                 true /* required */, "_domain", &mDomainInfo));
         return C2_OK;
     }
 
-    status_t getSupportedParams2(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) {
+    C2Status getSupportedParams2(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) {
         params->push_back(std::shared_ptr<C2ParamDescriptor>(
                 new C2ParamDescriptor(true /* required */, "_domain", &mDomainInfo)));
         return C2_OK;
@@ -2699,21 +2701,23 @@
 TEST_F(C2ParamTest, ReflectorTest) {
     C2ComponentDomainInfo domainInfo;
     std::shared_ptr<C2ComponentInterface> comp(new MyComponentInstance);
-    std::vector<C2FieldSupportedValues> values;
 
     std::unique_ptr<C2StructDescriptor> desc{
         comp->getParamReflector()->describe(C2ComponentDomainInfo::indexFlags)};
     dumpStruct(*desc);
 
-    EXPECT_EQ(
-        C2_OK,
-        comp->getSupportedValues(
-            { C2ParamField(&domainInfo, &C2ComponentDomainInfo::mValue) },
-            &values)
-    );
+    std::vector<C2FieldSupportedValuesQuery> query = {
+        { C2ParamField(&domainInfo, &C2ComponentDomainInfo::mValue),
+          C2FieldSupportedValuesQuery::CURRENT },
+        C2FieldSupportedValuesQuery(C2ParamField(&domainInfo, &C2ComponentDomainInfo::mValue),
+          C2FieldSupportedValuesQuery::CURRENT),
+        C2FieldSupportedValuesQuery::Current(C2ParamField(&domainInfo, &C2ComponentDomainInfo::mValue)),
+    };
 
-    for (const C2FieldSupportedValues &sv : values) {
-        dumpFSV(sv, &domainInfo.mValue);
+    EXPECT_EQ(C2_OK, comp->getSupportedValues(query));
+
+    for (const C2FieldSupportedValuesQuery &q : query) {
+        dumpFSV(q.values, &domainInfo.mValue);
     }
 }
 
diff --git a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
index a185880..8c78334 100644
--- a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
+++ b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
@@ -38,7 +38,7 @@
     ~C2BufferTest() = default;
 
     void allocateLinear(size_t capacity) {
-        C2Error err = mLinearAllocator->allocateLinearBuffer(
+        C2Status err = mLinearAllocator->allocateLinearBuffer(
                 capacity,
                 { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
                 &mLinearAllocation);
@@ -50,7 +50,7 @@
 
     void mapLinear(size_t offset, size_t size, uint8_t **addr) {
         ASSERT_TRUE(mLinearAllocation);
-        C2Error err = mLinearAllocation->map(
+        C2Status err = mLinearAllocation->map(
                 offset,
                 size,
                 { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
@@ -82,7 +82,7 @@
     }
 
     void allocateGraphic(uint32_t width, uint32_t height) {
-        C2Error err = mGraphicAllocator->allocateGraphicBuffer(
+        C2Status err = mGraphicAllocator->allocateGraphicBuffer(
                 width,
                 height,
                 HAL_PIXEL_FORMAT_YCBCR_420_888,
@@ -96,7 +96,7 @@
 
     void mapGraphic(C2Rect rect, C2PlaneLayout *layout, uint8_t **addr) {
         ASSERT_TRUE(mGraphicAllocation);
-        C2Error err = mGraphicAllocation->map(
+        C2Status err = mGraphicAllocation->map(
                 rect,
                 { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
                 // TODO: fence
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp b/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
index baa6637..6530cc1 100644
--- a/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
@@ -38,14 +38,14 @@
 using ::android::hardware::hidl_vec;
 
 /* ===================================== GRALLOC ALLOCATION ==================================== */
-static C2Error maperr2error(Error maperr) {
+static C2Status maperr2error(Error maperr) {
     switch (maperr) {
         case Error::NONE:           return C2_OK;
         case Error::BAD_DESCRIPTOR: return C2_BAD_VALUE;
         case Error::BAD_BUFFER:     return C2_BAD_VALUE;
         case Error::BAD_VALUE:      return C2_BAD_VALUE;
         case Error::NO_RESOURCES:   return C2_NO_MEMORY;
-        case Error::UNSUPPORTED:    return C2_UNSUPPORTED;
+        case Error::UNSUPPORTED:    return C2_CANNOT_DO;
     }
     return C2_CORRUPTED;
 }
@@ -54,10 +54,10 @@
 public:
     virtual ~C2AllocationGralloc();
 
-    virtual C2Error map(
+    virtual C2Status map(
             C2Rect rect, C2MemoryUsage usage, int *fenceFd,
             C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
-    virtual C2Error unmap(C2Fence *fenceFd /* nullable */) override;
+    virtual C2Status unmap(C2Fence *fenceFd /* nullable */) override;
     virtual bool isValid() const override { return true; }
     virtual const C2Handle *handle() const override { return mHandle; }
     virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
@@ -69,7 +69,7 @@
               const sp<IMapper> &mapper,
               hidl_handle &handle);
     int dup() const;
-    C2Error status() const;
+    C2Status status() const;
 
 private:
     const IMapper::BufferDescriptorInfo mInfo;
@@ -100,7 +100,7 @@
     mMapper->freeBuffer(const_cast<native_handle_t *>(mBuffer));
 }
 
-C2Error C2AllocationGralloc::map(
+C2Status C2AllocationGralloc::map(
         C2Rect rect, C2MemoryUsage usage, int *fenceFd,
         C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
     // TODO
@@ -114,7 +114,7 @@
         return C2_BAD_VALUE;
     }
 
-    C2Error err = C2_OK;
+    C2Status err = C2_OK;
     if (!mBuffer) {
         mMapper->importBuffer(
                 mHandle, [&err, this](const auto &maperr, const auto &buffer) {
@@ -195,16 +195,16 @@
             return err;
         }
         // TODO
-        return C2_UNSUPPORTED;
+        return C2_OMITTED;
     }
     mLocked = true;
 
     return C2_OK;
 }
 
-C2Error C2AllocationGralloc::unmap(C2Fence *fenceFd /* nullable */) {
+C2Status C2AllocationGralloc::unmap(C2Fence *fenceFd /* nullable */) {
     // TODO: fence
-    C2Error err = C2_OK;
+    C2Status err = C2_OK;
     mMapper->unlock(
             const_cast<native_handle_t *>(mBuffer),
             [&err, &fenceFd](const auto &maperr, const auto &releaseFence) {
@@ -231,18 +231,18 @@
 public:
     Impl();
 
-    C2Error allocateGraphicBuffer(
+    C2Status allocateGraphicBuffer(
             uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
             std::shared_ptr<C2GraphicAllocation> *allocation);
 
-    C2Error recreateGraphicBuffer(
+    C2Status recreateGraphicBuffer(
             const C2Handle *handle,
             std::shared_ptr<C2GraphicAllocation> *allocation);
 
-    C2Error status() const { return mInit; }
+    C2Status status() const { return mInit; }
 
 private:
-    C2Error mInit;
+    C2Status mInit;
     sp<IAllocator> mAllocator;
     sp<IMapper> mMapper;
 };
@@ -256,7 +256,7 @@
     }
 }
 
-C2Error C2AllocatorGralloc::Impl::allocateGraphicBuffer(
+C2Status C2AllocatorGralloc::Impl::allocateGraphicBuffer(
         uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
         std::shared_ptr<C2GraphicAllocation> *allocation) {
     // TODO: buffer usage should be determined according to |usage|
@@ -269,7 +269,7 @@
         (PixelFormat)format,
         BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
     };
-    C2Error err = C2_OK;
+    C2Status err = C2_OK;
     BufferDescriptor desc;
     mMapper->createDescriptor(
             info, [&err, &desc](const auto &maperr, const auto &descriptor) {
@@ -307,33 +307,33 @@
     return C2_OK;
 }
 
-C2Error C2AllocatorGralloc::Impl::recreateGraphicBuffer(
+C2Status C2AllocatorGralloc::Impl::recreateGraphicBuffer(
         const C2Handle *handle,
         std::shared_ptr<C2GraphicAllocation> *allocation) {
     (void) handle;
 
     // TODO: need to figure out BufferDescriptorInfo from the handle.
     allocation->reset();
-    return C2_UNSUPPORTED;
+    return C2_OMITTED;
 }
 
 C2AllocatorGralloc::C2AllocatorGralloc() : mImpl(new Impl) {}
 
 C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
 
-C2Error C2AllocatorGralloc::allocateGraphicBuffer(
+C2Status C2AllocatorGralloc::allocateGraphicBuffer(
         uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
         std::shared_ptr<C2GraphicAllocation> *allocation) {
     return mImpl->allocateGraphicBuffer(width, height, format, usage, allocation);
 }
 
-C2Error C2AllocatorGralloc::recreateGraphicBuffer(
+C2Status C2AllocatorGralloc::recreateGraphicBuffer(
         const C2Handle *handle,
         std::shared_ptr<C2GraphicAllocation> *allocation) {
     return mImpl->recreateGraphicBuffer(handle, allocation);
 }
 
-C2Error C2AllocatorGralloc::status() const {
+C2Status C2AllocatorGralloc::status() const {
     return mImpl->status();
 }
 
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
index 7aa7769..06b4874 100644
--- a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
+++ b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
@@ -82,10 +82,10 @@
 /* ======================================= ION ALLOCATION ====================================== */
 class C2AllocationIon : public C2LinearAllocation {
 public:
-    virtual C2Error map(
+    virtual C2Status map(
         size_t offset, size_t size, C2MemoryUsage usage, int *fence,
         void **addr /* nonnull */);
-    virtual C2Error unmap(void *addr, size_t size, int *fenceFd);
+    virtual C2Status unmap(void *addr, size_t size, int *fenceFd);
     virtual bool isValid() const;
     virtual ~C2AllocationIon();
     virtual const C2Handle *handle() const;
@@ -95,7 +95,7 @@
     C2AllocationIon(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags);
     C2AllocationIon(int ionFd, size_t size, int shareFd);
     int dup() const;
-    C2Error status() const;
+    C2Status status() const;
 
 protected:
     class Impl;
@@ -121,18 +121,28 @@
     }
 
     Impl(int ionFd, size_t capacity, int shareFd)
-        : mHandle(ionFd, -1),
+        : mInit(C2_OK),
+          mHandle(ionFd, -1),
           mMapFd(-1),
           mCapacity(capacity) {
         ion_user_handle_t buffer;
-        mInit = ion_import(mHandle.ionFd(), shareFd, &buffer);
-        if (mInit == 0) {
+        int ret = ion_import(mHandle.ionFd(), shareFd, &buffer);
+        switch (-ret) {
+        case 0:
             mHandle.setBuffer(buffer);
+            break;
+        case EBADF: // bad ion handle - should not happen
+        case ENOTTY: // bad ion driver
+            mInit = C2_CORRUPTED;
+            break;
+        default:
+            mInit = c2_map_errno<ENOMEM, EACCES, EINVAL>(-ret);
+            break;
         }
         (void)mCapacity; // TODO
     }
 
-    C2Error map(size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
+    C2Status map(size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
         (void)fenceFd; // TODO: wait for fence
         *addr = nullptr;
         int prot = PROT_NONE;
@@ -149,7 +159,7 @@
         size_t mapOffset = offset - alignmentBytes;
         size_t mapSize = size + alignmentBytes;
 
-        C2Error err = C2_OK;
+        C2Status err = C2_OK;
         if (mMapFd == -1) {
             int ret = ion_map(mHandle.ionFd(), mHandle.buffer(), mapSize, prot,
                               flags, mapOffset, (unsigned char**)&mMapAddr, &mMapFd);
@@ -176,7 +186,7 @@
         return err;
     }
 
-    C2Error unmap(void *addr, size_t size, int *fenceFd) {
+    C2Status unmap(void *addr, size_t size, int *fenceFd) {
         if (addr != (uint8_t *)mMapAddr + mMapAlignmentBytes ||
                 size + mMapAlignmentBytes != mMapSize) {
             return C2_BAD_VALUE;
@@ -200,7 +210,7 @@
         (void)ion_free(mHandle.ionFd(), mHandle.buffer());
     }
 
-    C2Error status() const {
+    C2Status status() const {
         return mInit;
     }
 
@@ -217,7 +227,7 @@
     }
 
 private:
-    C2Error mInit;
+    C2Status mInit;
     C2HandleIon mHandle;
     int mMapFd; // only one for now
     void *mMapAddr;
@@ -226,12 +236,12 @@
     size_t mCapacity;
 };
 
-C2Error C2AllocationIon::map(
+C2Status C2AllocationIon::map(
     size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
     return mImpl->map(offset, size, usage, fenceFd, addr);
 }
 
-C2Error C2AllocationIon::unmap(void *addr, size_t size, int *fenceFd) {
+C2Status C2AllocationIon::unmap(void *addr, size_t size, int *fenceFd) {
     return mImpl->unmap(addr, size, fenceFd);
 }
 
@@ -239,7 +249,7 @@
     return mImpl->status() == C2_OK;
 }
 
-C2Error C2AllocationIon::status() const {
+C2Status C2AllocationIon::status() const {
     return mImpl->status();
 }
 
@@ -272,7 +282,7 @@
 C2AllocatorIon::C2AllocatorIon() : mInit(C2_OK), mIonFd(ion_open()) {
     if (mIonFd < 0) {
         switch (errno) {
-        case ENOENT:    mInit = C2_UNSUPPORTED; break;
+        case ENOENT:    mInit = C2_OMITTED; break;
         default:        mInit = c2_map_errno<EACCES>(errno); break;
         }
     }
@@ -284,7 +294,7 @@
     }
 }
 
-C2Error C2AllocatorIon::allocateLinearBuffer(
+C2Status C2AllocatorIon::allocateLinearBuffer(
         uint32_t capacity, C2MemoryUsage usage, std::shared_ptr<C2LinearAllocation> *allocation) {
     if (allocation == nullptr) {
         return C2_BAD_VALUE;
@@ -292,7 +302,7 @@
 
     allocation->reset();
     if (mInit != C2_OK) {
-        return C2_UNSUPPORTED;
+        return mInit;
     }
 
     // get align, heapMask and flags
@@ -311,18 +321,18 @@
 
     std::shared_ptr<C2AllocationIon> alloc
         = std::make_shared<C2AllocationIon>(mIonFd, capacity, align, heapMask, flags);
-    C2Error ret = alloc->status();
+    C2Status ret = alloc->status();
     if (ret == C2_OK) {
         *allocation = alloc;
     }
     return ret;
 }
 
-C2Error C2AllocatorIon::recreateLinearBuffer(
+C2Status C2AllocatorIon::recreateLinearBuffer(
         const C2Handle *handle, std::shared_ptr<C2LinearAllocation> *allocation) {
     *allocation = nullptr;
     if (mInit != C2_OK) {
-        return C2_UNSUPPORTED;
+        return mInit;
     }
 
     if (!C2HandleIon::isValid(handle)) {
@@ -333,7 +343,7 @@
     const C2HandleIon *h = static_cast<const C2HandleIon*>(handle);
     std::shared_ptr<C2AllocationIon> alloc
         = std::make_shared<C2AllocationIon>(mIonFd, 0 /* capacity */, h->buffer());
-    C2Error ret = alloc->status();
+    C2Status ret = alloc->status();
     if (ret == C2_OK) {
         *allocation = alloc;
     }
diff --git a/media/libstagefright/codec2/vndk/C2Buffer.cpp b/media/libstagefright/codec2/vndk/C2Buffer.cpp
index 1ffbf49..d3f0d70 100644
--- a/media/libstagefright/codec2/vndk/C2Buffer.cpp
+++ b/media/libstagefright/codec2/vndk/C2Buffer.cpp
@@ -129,26 +129,26 @@
     explicit Impl(const uint8_t *data)
         : mData(data), mError(C2_OK) {}
 
-    explicit Impl(C2Error error)
+    explicit Impl(C2Status error)
         : mData(nullptr), mError(error) {}
 
     const uint8_t *data() const {
         return mData;
     }
 
-    C2Error error() const {
+    C2Status error() const {
         return mError;
     }
 
 private:
     const uint8_t *mData;
-    C2Error mError;
+    C2Status mError;
 };
 
 C2ReadView::C2ReadView(const _C2LinearCapacityAspect *parent, const uint8_t *data)
     : _C2LinearCapacityAspect(parent), mImpl(std::make_shared<Impl>(data)) {}
 
-C2ReadView::C2ReadView(C2Error error)
+C2ReadView::C2ReadView(C2Status error)
     : _C2LinearCapacityAspect(0u), mImpl(std::make_shared<Impl>(error)) {}
 
 const uint8_t *C2ReadView::data() const {
@@ -167,7 +167,7 @@
     return C2ReadView(&newCapacity, data() + offset);
 }
 
-C2Error C2ReadView::error() {
+C2Status C2ReadView::error() const {
     return mImpl->error();
 }
 
@@ -176,33 +176,33 @@
     explicit Impl(uint8_t *base)
         : mBase(base), mError(C2_OK) {}
 
-    explicit Impl(C2Error error)
+    explicit Impl(C2Status error)
         : mBase(nullptr), mError(error) {}
 
     uint8_t *base() const {
         return mBase;
     }
 
-    C2Error error() const {
+    C2Status error() const {
         return mError;
     }
 
 private:
     uint8_t *mBase;
-    C2Error mError;
+    C2Status mError;
 };
 
 C2WriteView::C2WriteView(const _C2LinearRangeAspect *parent, uint8_t *base)
     : _C2EditableLinearRange(parent), mImpl(std::make_shared<Impl>(base)) {}
 
-C2WriteView::C2WriteView(C2Error error)
+C2WriteView::C2WriteView(C2Status error)
     : _C2EditableLinearRange(nullptr), mImpl(std::make_shared<Impl>(error)) {}
 
 uint8_t *C2WriteView::base() { return mImpl->base(); }
 
 uint8_t *C2WriteView::data() { return mImpl->base() + offset(); }
 
-C2Error C2WriteView::error() { return mImpl->error(); }
+C2Status C2WriteView::error() const { return mImpl->error(); }
 
 class C2ConstLinearBlock::Impl {
 public:
@@ -212,7 +212,7 @@
     ~Impl() {
         if (mBase != nullptr) {
             // TODO: fence
-            C2Error err = mAllocation->unmap(mBase, mSize, nullptr);
+            C2Status err = mAllocation->unmap(mBase, mSize, nullptr);
             if (err != C2_OK) {
                 // TODO: Log?
             }
@@ -238,13 +238,13 @@
 
     const uint8_t *base() const { return mBase; }
 
-    C2Error error() const { return mError; }
+    C2Status error() const { return mError; }
 
 private:
     std::shared_ptr<C2LinearAllocation> mAllocation;
     uint8_t *mBase;
     size_t mSize;
-    C2Error mError;
+    C2Status mError;
 };
 
 C2ConstLinearBlock::C2ConstLinearBlock(std::shared_ptr<C2LinearAllocation> alloc)
@@ -277,7 +277,7 @@
     ~Impl() {
         if (mBase != nullptr) {
             // TODO: fence
-            C2Error err = mAllocation->unmap(mBase, mSize, nullptr);
+            C2Status err = mAllocation->unmap(mBase, mSize, nullptr);
             if (err != C2_OK) {
                 // TODO: Log?
             }
@@ -309,7 +309,7 @@
 
     uint8_t *base() const { return mBase; }
 
-    C2Error error() const { return mError; }
+    C2Status error() const { return mError; }
 
     C2Fence fence() const { return mFence; }
 
@@ -317,7 +317,7 @@
     std::shared_ptr<C2LinearAllocation> mAllocation;
     uint8_t *mBase;
     size_t mSize;
-    C2Error mError;
+    C2Status mError;
     C2Fence mFence;
 };
 
@@ -349,14 +349,14 @@
         const std::shared_ptr<C2Allocator> &allocator)
   : mAllocator(allocator) {}
 
-C2Error C2DefaultBlockAllocator::allocateLinearBlock(
+C2Status C2DefaultBlockAllocator::allocateLinearBlock(
         uint32_t capacity,
         C2MemoryUsage usage,
         std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
     block->reset();
 
     std::shared_ptr<C2LinearAllocation> alloc;
-    C2Error err = mAllocator->allocateLinearBuffer(capacity, usage, &alloc);
+    C2Status err = mAllocator->allocateLinearBuffer(capacity, usage, &alloc);
     if (err != C2_OK) {
         return err;
     }
@@ -392,16 +392,16 @@
 public:
     Impl(uint8_t *const *data, const C2PlaneLayout &layout)
         : mData(data), mLayout(layout), mError(C2_OK) {}
-    explicit Impl(C2Error error) : mData(nullptr), mError(error) {}
+    explicit Impl(C2Status error) : mData(nullptr), mError(error) {}
 
     uint8_t *const *data() const { return mData; }
     const C2PlaneLayout &layout() const { return mLayout; }
-    C2Error error() const { return mError; }
+    C2Status error() const { return mError; }
 
 private:
     uint8_t *const *mData;
     C2PlaneLayout mLayout;
-    C2Error mError;
+    C2Status mError;
 };
 
 C2GraphicView::C2GraphicView(
@@ -410,7 +410,7 @@
         const C2PlaneLayout& layout)
     : _C2PlanarSection(parent), mImpl(new Impl(data, layout)) {}
 
-C2GraphicView::C2GraphicView(C2Error error)
+C2GraphicView::C2GraphicView(C2Status error)
     : _C2PlanarSection(nullptr), mImpl(new Impl(error)) {}
 
 const uint8_t *const *C2GraphicView::data() const {
@@ -437,7 +437,7 @@
     return view;
 }
 
-C2Error C2GraphicView::error() const {
+C2Status C2GraphicView::error() const {
     return mImpl->error();
 }
 
@@ -453,12 +453,12 @@
         }
     }
 
-    C2Error map(C2Rect rect) {
+    C2Status map(C2Rect rect) {
         if (mData[0] != nullptr) {
             // Already mapped.
             return C2_OK;
         }
-        C2Error err = mAllocation->map(
+        C2Status err = mAllocation->map(
                 rect,
                 { C2MemoryUsage::kSoftwareRead, 0 },
                 nullptr,
@@ -493,7 +493,7 @@
     : C2Block2D(alloc), mImpl(new Impl(alloc)), mFence(fence) {}
 
 C2Acquirable<const C2GraphicView> C2ConstGraphicBlock::map() const {
-    C2Error err = mImpl->map(crop());
+    C2Status err = mImpl->map(crop());
     if (err != C2_OK) {
         C2DefaultGraphicView view(err);
         return C2AcquirableConstGraphicView(err, mFence, view);
@@ -518,13 +518,13 @@
         }
     }
 
-    C2Error map(C2Rect rect) {
+    C2Status map(C2Rect rect) {
         if (mData[0] != nullptr) {
             // Already mapped.
             return C2_OK;
         }
         uint8_t *data[C2PlaneLayout::MAX_NUM_PLANES];
-        C2Error err = mAllocation->map(
+        C2Status err = mAllocation->map(
                 rect,
                 { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
                 nullptr,
@@ -560,7 +560,7 @@
     : C2Block2D(alloc), mImpl(new Impl(alloc)) {}
 
 C2Acquirable<C2GraphicView> C2GraphicBlock::map() {
-    C2Error err = mImpl->map(crop());
+    C2Status err = mImpl->map(crop());
     if (err != C2_OK) {
         C2DefaultGraphicView view(err);
         // TODO: fence
@@ -579,7 +579,7 @@
         const std::shared_ptr<C2Allocator> &allocator)
   : mAllocator(allocator) {}
 
-C2Error C2DefaultGraphicBlockAllocator::allocateGraphicBlock(
+C2Status C2DefaultGraphicBlockAllocator::allocateGraphicBlock(
         uint32_t width,
         uint32_t height,
         uint32_t format,
@@ -588,7 +588,7 @@
     block->reset();
 
     std::shared_ptr<C2GraphicAllocation> alloc;
-    C2Error err = mAllocator->allocateGraphicBuffer(width, height, format, usage, &alloc);
+    C2Status err = mAllocator->allocateGraphicBuffer(width, height, format, usage, &alloc);
     if (err != C2_OK) {
         return err;
     }
@@ -650,7 +650,7 @@
 
     const C2BufferData &data() const { return mData; }
 
-    C2Error registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+    C2Status registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
         auto it = std::find_if(
                 mNotify.begin(), mNotify.end(),
                 [onDestroyNotify, arg] (const auto &pair) {
@@ -663,7 +663,7 @@
         return C2_OK;
     }
 
-    C2Error unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+    C2Status unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
         auto it = std::find_if(
                 mNotify.begin(), mNotify.end(),
                 [onDestroyNotify, arg] (const auto &pair) {
@@ -684,7 +684,7 @@
         return result;
     }
 
-    C2Error setInfo(const std::shared_ptr<C2Info> &info) {
+    C2Status setInfo(const std::shared_ptr<C2Info> &info) {
         // To "update" you need to erase the existing one if any, and then insert.
         (void) mInfos.erase(info->type());
         (void) mInfos.insert({ info->type(), info });
@@ -720,11 +720,11 @@
 
 const C2BufferData C2Buffer::data() const { return mImpl->data(); }
 
-C2Error C2Buffer::registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+C2Status C2Buffer::registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
     return mImpl->registerOnDestroyNotify(onDestroyNotify, arg);
 }
 
-C2Error C2Buffer::unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+C2Status C2Buffer::unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
     return mImpl->unregisterOnDestroyNotify(onDestroyNotify, arg);
 }
 
@@ -732,7 +732,7 @@
     return mImpl->infos();
 }
 
-C2Error C2Buffer::setInfo(const std::shared_ptr<C2Info> &info) {
+C2Status C2Buffer::setInfo(const std::shared_ptr<C2Info> &info) {
     return mImpl->setInfo(info);
 }
 
diff --git a/media/libstagefright/codec2/vndk/C2Store.cpp b/media/libstagefright/codec2/vndk/C2Store.cpp
index f21a3f0..42bdf0e 100644
--- a/media/libstagefright/codec2/vndk/C2Store.cpp
+++ b/media/libstagefright/codec2/vndk/C2Store.cpp
@@ -35,7 +35,7 @@
     C2PlatformAllocatorStore(
         /* ionmapper */
     );
-    virtual status_t createAllocator(ID id, std::shared_ptr<C2Allocator> *const allocator);
+    virtual C2Status createAllocator(ID id, std::shared_ptr<C2Allocator> *const allocator);
 
 private:
     // returns a shared-singleton ion allocator
@@ -48,7 +48,7 @@
 C2PlatformAllocatorStore::C2PlatformAllocatorStore() {
 }
 
-status_t C2PlatformAllocatorStore::createAllocator(
+C2Status C2PlatformAllocatorStore::createAllocator(
         ID id, std::shared_ptr<C2Allocator> *const allocator) {
     allocator->reset();
     switch (id) {
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
index 94f74c8..9bfd987 100644
--- a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
@@ -30,17 +30,17 @@
     typedef std::function<int (C2MemoryUsage, size_t,
                       /* => */ size_t*, unsigned*, unsigned*)> usage_mapper_fn;
 
-    virtual C2Error allocateGraphicBuffer(
+    virtual C2Status allocateGraphicBuffer(
             uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
             std::shared_ptr<C2GraphicAllocation> *allocation) override;
 
-    virtual C2Error recreateGraphicBuffer(
+    virtual C2Status recreateGraphicBuffer(
             const C2Handle *handle,
             std::shared_ptr<C2GraphicAllocation> *allocation) override;
 
     C2AllocatorGralloc();
 
-    C2Error status() const;
+    C2Status status() const;
 
     virtual ~C2AllocatorGralloc();
 
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
index a453a7d..00c33fe 100644
--- a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
@@ -29,22 +29,22 @@
     typedef std::function<int (C2MemoryUsage, size_t,
                       /* => */ size_t*, unsigned*, unsigned*)> usage_mapper_fn;
 
-    virtual C2Error allocateLinearBuffer(
+    virtual C2Status allocateLinearBuffer(
             uint32_t capacity, C2MemoryUsage usage,
             std::shared_ptr<C2LinearAllocation> *allocation) override;
 
-    virtual C2Error recreateLinearBuffer(
+    virtual C2Status recreateLinearBuffer(
             const C2Handle *handle,
             std::shared_ptr<C2LinearAllocation> *allocation) override;
 
     C2AllocatorIon();
 
-    C2Error status() const { return mInit; }
+    C2Status status() const { return mInit; }
 
     virtual ~C2AllocatorIon();
 
 private:
-    C2Error mInit;
+    C2Status mInit;
     int mIonFd;
     usage_mapper_fn mUsageMapper;
 };
diff --git a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
index 6a8f94e..f1e8acb 100644
--- a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
+++ b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
@@ -29,7 +29,7 @@
 
     virtual ~C2DefaultBlockAllocator() = default;
 
-    virtual C2Error allocateLinearBlock(
+    virtual C2Status allocateLinearBlock(
             uint32_t capacity,
             C2MemoryUsage usage,
             std::shared_ptr<C2LinearBlock> *block /* nonnull */) override;
@@ -45,7 +45,7 @@
 
     virtual ~C2DefaultGraphicBlockAllocator() = default;
 
-    virtual C2Error allocateGraphicBlock(
+    virtual C2Status allocateGraphicBlock(
             uint32_t width,
             uint32_t height,
             uint32_t format,
diff --git a/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h b/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h
index f834cdb..aea3a6f 100644
--- a/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h
+++ b/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h
@@ -23,32 +23,32 @@
 namespace android {
 
 // standard ERRNO mappings
-template<int N> constexpr C2Error _c2_errno2error_impl();
-template<> constexpr C2Error _c2_errno2error_impl<0>()       { return C2_OK; }
-template<> constexpr C2Error _c2_errno2error_impl<EINVAL>()  { return C2_BAD_VALUE; }
-template<> constexpr C2Error _c2_errno2error_impl<EACCES>()  { return C2_NO_PERMISSION; }
-template<> constexpr C2Error _c2_errno2error_impl<EPERM>()   { return C2_NO_PERMISSION; }
-template<> constexpr C2Error _c2_errno2error_impl<ENOMEM>()  { return C2_NO_MEMORY; }
+template<int N> constexpr C2Status _c2_errno2status_impl();
+template<> constexpr C2Status _c2_errno2status_impl<0>()       { return C2_OK; }
+template<> constexpr C2Status _c2_errno2status_impl<EINVAL>()  { return C2_BAD_VALUE; }
+template<> constexpr C2Status _c2_errno2status_impl<EACCES>()  { return C2_REFUSED; }
+template<> constexpr C2Status _c2_errno2status_impl<EPERM>()   { return C2_REFUSED; }
+template<> constexpr C2Status _c2_errno2status_impl<ENOMEM>()  { return C2_NO_MEMORY; }
 
-// map standard errno-s to the equivalent C2Error
+// map standard errno-s to the equivalent C2Status
 template<int... N> struct _c2_map_errno_impl;
 template<int E, int ... N> struct _c2_map_errno_impl<E, N...> {
-    static C2Error map(int result) {
+    static C2Status map(int result) {
         if (result == E) {
-            return _c2_errno2error_impl<E>();
+            return _c2_errno2status_impl <E>();
         } else {
             return _c2_map_errno_impl<N...>::map(result);
         }
     }
 };
 template<> struct _c2_map_errno_impl<> {
-    static C2Error map(int result) {
+    static C2Status map(int result) {
         return result == 0 ? C2_OK : C2_CORRUPTED;
     }
 };
 
 template<int... N>
-C2Error c2_map_errno(int result) {
+C2Status c2_map_errno(int result) {
     return _c2_map_errno_impl<N...>::map(result);
 }
 
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
index 5f55e1e..77db255 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
@@ -94,11 +94,15 @@
     bool validateField(
             const C2FieldSupportedValues &supportedValues, const T &value) {
         switch (supportedValues.type) {
+        case C2FieldSupportedValues::EMPTY:
+            {
+                return false;
+            }
         case C2FieldSupportedValues::RANGE:
             {
                 // TODO: handle step, nom, denom
-                return Getter<T>::get(supportedValues.range.min) < value
-                        && value < Getter<T>::get(supportedValues.range.max);
+                return Getter<T>::get(supportedValues.range.min) <= value
+                        && value <= Getter<T>::get(supportedValues.range.max);
             }
         case C2FieldSupportedValues::VALUES:
             {
@@ -153,7 +157,7 @@
         const C2FieldSupportedValues &supportedValues = mSupportedValues.at(field).supported;
         if (!validateField(supportedValues, param->mValue)) {
             return std::unique_ptr<C2SettingResult>(
-                    new C2SettingResult {field, C2SettingResult::BAD_VALUE, nullptr, {}});
+                    new C2SettingResult {C2SettingResult::BAD_VALUE, {field, nullptr}, {}});
         }
         return nullptr;
     }
@@ -171,13 +175,13 @@
         const C2FieldSupportedValues &supportedWidth = mSupportedValues.at(field).supported;
         if (!validateField(supportedWidth, param->mWidth)) {
             return std::unique_ptr<C2SettingResult>(
-                    new C2SettingResult {field, C2SettingResult::BAD_VALUE, nullptr, {}});
+                    new C2SettingResult {C2SettingResult::BAD_VALUE, {field, nullptr}, {}});
         }
         field = C2ParamField(param, &T::mHeight);
         const C2FieldSupportedValues &supportedHeight = mSupportedValues.at(field).supported;
         if (!validateField(supportedHeight, param->mHeight)) {
             return std::unique_ptr<C2SettingResult>(
-                    new C2SettingResult {field, C2SettingResult::BAD_VALUE, nullptr, {}});
+                    new C2SettingResult {C2SettingResult::BAD_VALUE, {field, nullptr}, {}});
         }
         return nullptr;
     }
@@ -191,7 +195,7 @@
         T* param = (T*)c2param;
         if (strncmp(param->m.mValue, mExpected, param->flexCount()) != 0) {
             return std::unique_ptr<C2SettingResult>(
-                    new C2SettingResult {C2ParamField(param, &T::m), C2SettingResult::BAD_VALUE, nullptr, {}});
+                    new C2SettingResult {C2SettingResult::BAD_VALUE, {C2ParamField(param, &T::m), nullptr}, {}});
         }
         return nullptr;
     }
@@ -428,7 +432,7 @@
     return mId;
 }
 
-status_t C2SoftAvcDecIntf::query_nb(
+C2Status C2SoftAvcDecIntf::query_nb(
         const std::vector<C2Param* const> & stackParams,
         const std::vector<C2Param::Index> & heapParamIndices,
         std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
@@ -461,10 +465,10 @@
     return C2_OK;
 }
 
-status_t C2SoftAvcDecIntf::config_nb(
+C2Status C2SoftAvcDecIntf::config_nb(
         const std::vector<C2Param* const> &params,
         std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
-    status_t err = C2_OK;
+    C2Status err = C2_OK;
     for (C2Param *param : params) {
         uint32_t index = restoreIndex(param);
         if (mParams.count(index) == 0) {
@@ -485,45 +489,48 @@
     return err;
 }
 
-status_t C2SoftAvcDecIntf::commit_sm(
+C2Status C2SoftAvcDecIntf::commit_sm(
         const std::vector<C2Param* const> &params,
         std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
     // TODO
     return config_nb(params, failures);
 }
 
-status_t C2SoftAvcDecIntf::createTunnel_sm(node_id targetComponent) {
+C2Status C2SoftAvcDecIntf::createTunnel_sm(node_id targetComponent) {
     // Tunneling is not supported
     (void) targetComponent;
-    return C2_UNSUPPORTED;
+    return C2_OMITTED;
 }
 
-status_t C2SoftAvcDecIntf::releaseTunnel_sm(node_id targetComponent) {
+C2Status C2SoftAvcDecIntf::releaseTunnel_sm(node_id targetComponent) {
     // Tunneling is not supported
     (void) targetComponent;
-    return C2_UNSUPPORTED;
+    return C2_OMITTED;
 }
 
 std::shared_ptr<C2ParamReflector> C2SoftAvcDecIntf::getParamReflector() const {
     return mParamReflector;
 }
 
-status_t C2SoftAvcDecIntf::getSupportedParams(
+C2Status C2SoftAvcDecIntf::getSupportedParams(
         std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const {
     params->insert(params->begin(), mParamDescs.begin(), mParamDescs.end());
     return C2_OK;
 }
 
-status_t C2SoftAvcDecIntf::getSupportedValues(
-        const std::vector<const C2ParamField> &fields,
-        std::vector<C2FieldSupportedValues>* const values) const {
-    for (const auto &field : fields) {
-        if (mSupportedValues.count(field) == 0) {
-            return BAD_VALUE;
+C2Status C2SoftAvcDecIntf::getSupportedValues(
+        std::vector<C2FieldSupportedValuesQuery> &fields) const {
+    C2Status res = C2_OK;
+    for (C2FieldSupportedValuesQuery &query : fields) {
+        if (mSupportedValues.count(query.field) == 0) {
+            query.status = C2_BAD_INDEX;
+            res = C2_BAD_INDEX;
+        } else {
+            query.status = C2_OK;
+            query.values = mSupportedValues.at(query.field).supported;
         }
-        values->push_back(mSupportedValues.at(field).supported);
     }
-    return C2_OK;
+    return res;
 }
 
 void C2SoftAvcDecIntf::updateSupportedValues() {
@@ -644,7 +651,7 @@
     CHECK_EQ(deInitDecoder(), (status_t)OK);
 }
 
-status_t C2SoftAvcDec::queue_nb(
+C2Status C2SoftAvcDec::queue_nb(
         std::list<std::unique_ptr<C2Work>>* const items) {
     if (!mThread->isRunning()) {
         return C2_CORRUPTED;
@@ -659,13 +666,13 @@
     return C2_OK;
 }
 
-status_t C2SoftAvcDec::announce_nb(const std::vector<C2WorkOutline> &items) {
+C2Status C2SoftAvcDec::announce_nb(const std::vector<C2WorkOutline> &items) {
     // Tunneling is not supported
     (void) items;
-    return C2_UNSUPPORTED;
+    return C2_OMITTED;
 }
 
-status_t C2SoftAvcDec::flush_sm(
+C2Status C2SoftAvcDec::flush_sm(
         bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) {
     // Tunneling is not supported
     (void) flushThrough;
@@ -691,7 +698,7 @@
     return C2_OK;
 }
 
-status_t C2SoftAvcDec::drain_nb(bool drainThrough) {
+C2Status C2SoftAvcDec::drain_nb(bool drainThrough) {
     // Tunneling is not supported
     (void) drainThrough;
 
@@ -707,14 +714,14 @@
     return C2_OK;
 }
 
-status_t C2SoftAvcDec::start() {
+C2Status C2SoftAvcDec::start() {
     if (!mThread->isRunning()) {
         mThread->start(shared_from_this());
     }
     return C2_OK;
 }
 
-status_t C2SoftAvcDec::stop() {
+C2Status C2SoftAvcDec::stop() {
     ALOGV("stop");
     std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
     std::chrono::system_clock::time_point deadline = now + std::chrono::milliseconds(500);
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
index 6a83d1d..cc33083 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
@@ -85,24 +85,23 @@
     // From C2ComponentInterface
     virtual C2String getName() const override;
     virtual node_id getId() const override;
-    virtual status_t query_nb(
+    virtual C2Status query_nb(
             const std::vector<C2Param* const> &stackParams,
             const std::vector<C2Param::Index> &heapParamIndices,
             std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
-    virtual status_t config_nb(
+    virtual C2Status config_nb(
             const std::vector<C2Param* const> &params,
             std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
-    virtual status_t commit_sm(
+    virtual C2Status commit_sm(
             const std::vector<C2Param* const> &params,
             std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
-    virtual status_t createTunnel_sm(node_id targetComponent) override;
-    virtual status_t releaseTunnel_sm(node_id targetComponent) override;
+    virtual C2Status createTunnel_sm(node_id targetComponent) override;
+    virtual C2Status releaseTunnel_sm(node_id targetComponent) override;
     virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override;
-    virtual status_t getSupportedParams(
+    virtual C2Status getSupportedParams(
             std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const override;
-    virtual status_t getSupportedValues(
-            const std::vector<const C2ParamField> &fields,
-            std::vector<C2FieldSupportedValues>* const values) const override;
+    virtual C2Status getSupportedValues(
+            std::vector<C2FieldSupportedValuesQuery> &fields) const override;
 
 private:
     class ParamReflector;
@@ -150,13 +149,13 @@
     virtual ~C2SoftAvcDec();
 
     // From C2Component
-    virtual status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override;
-    virtual status_t announce_nb(const std::vector<C2WorkOutline> &items) override;
-    virtual status_t flush_sm(
+    virtual C2Status queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override;
+    virtual C2Status announce_nb(const std::vector<C2WorkOutline> &items) override;
+    virtual C2Status flush_sm(
             bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) override;
-    virtual status_t drain_nb(bool drainThrough) override;
-    virtual status_t start() override;
-    virtual status_t stop() override;
+    virtual C2Status drain_nb(bool drainThrough) override;
+    virtual C2Status start() override;
+    virtual C2Status stop() override;
     virtual void reset() override;
     virtual void release() override;
     virtual std::shared_ptr<C2ComponentInterface> intf() override;
@@ -228,9 +227,9 @@
     bool mChangingResolution;
     bool mFlushNeeded;
     bool mSignalledError;
-    int32_t mWidth;
-    int32_t mHeight;
-    int32_t mStride;
+    uint32_t mWidth;
+    uint32_t mHeight;
+    uint32_t mStride;
     size_t mInputOffset;
 
     void processQueue();
diff --git a/media/libstagefright/filters/Android.bp b/media/libstagefright/filters/Android.bp
index a0af4f6..e944224 100644
--- a/media/libstagefright/filters/Android.bp
+++ b/media/libstagefright/filters/Android.bp
@@ -13,12 +13,8 @@
         "ZeroFilter.cpp",
     ],
 
-    header_libs: [
-        "media_plugin_headers",
-    ],
-
-    export_header_lib_headers: [
-        "media_plugin_headers",
+    include_dirs: [
+        "frameworks/native/include/media/openmax",
     ],
 
     cflags: [
diff --git a/media/libstagefright/include/OmxNodeOwner.h b/media/libstagefright/include/OmxNodeOwner.h
new file mode 100644
index 0000000..64ec7f7
--- /dev/null
+++ b/media/libstagefright/include/OmxNodeOwner.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef OMX_NODE_OWNER_H_
+
+#define OMX_NODE_OWNER_H_
+
+namespace android {
+
+struct OMXNodeInstance;
+
+/**
+ * This struct is needed to separate OMX from OMXNodeInstance.
+ *
+ * TODO: This might not be needed after Treble transition is complete.
+ */
+struct OmxNodeOwner {
+    virtual status_t freeNode(const sp<OMXNodeInstance> &instance) = 0;
+    virtual ~OmxNodeOwner() {}
+};
+
+}
+
+#endif  // OMX_NODE_OWNER_H_
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index d1a9d25..424246d 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -95,6 +95,11 @@
 
     static status_t getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]);
 
+    // Save the flag.
+    void setTrebleFlag(bool trebleFlag);
+    // Return the saved flag.
+    bool getTrebleFlag() const;
+
 protected:
     virtual ~ACodec();
 
@@ -228,7 +233,9 @@
     sp<IOMX> mOMX;
     sp<IOMXNode> mOMXNode;
     int32_t mNodeGeneration;
+    bool mTrebleFlag;
     sp<TAllocator> mAllocator[2];
+    sp<MemoryDealer> mDealer[2];
 
     bool mUsingNativeWindow;
     sp<ANativeWindow> mNativeWindow;
diff --git a/media/libstagefright/include/media/stagefright/OMXClient.h b/media/libstagefright/include/media/stagefright/OMXClient.h
index e7b9be5..b1864b8 100644
--- a/media/libstagefright/include/media/stagefright/OMXClient.h
+++ b/media/libstagefright/include/media/stagefright/OMXClient.h
@@ -18,19 +18,25 @@
 
 #define OMX_CLIENT_H_
 
-namespace android {
+#include <media/IOMX.h>
 
-class IOMX;
+namespace android {
 
 class OMXClient {
 public:
     OMXClient();
 
-    status_t connect(const char* name = "default");
+    status_t connect();
+    status_t connect(bool* trebleFlag);
+    status_t connect(const char* name, bool* trebleFlag = nullptr);
 
+    status_t connectLegacy();
+    status_t connectTreble(const char* name = "default");
     void disconnect();
 
-    sp<IOMX> interface();
+    sp<IOMX> interface() {
+        return mOMX;
+    }
 
 private:
     sp<IOMX> mOMX;
diff --git a/media/libstagefright/omx/Android.bp b/media/libstagefright/omx/Android.bp
index 8539864..f388a48 100644
--- a/media/libstagefright/omx/Android.bp
+++ b/media/libstagefright/omx/Android.bp
@@ -9,6 +9,8 @@
         "FrameDropper.cpp",
         "GraphicBufferSource.cpp",
         "BWGraphicBufferSource.cpp",
+        "OMX.cpp",
+        "OMXStore.cpp",
         "OMXMaster.cpp",
         "OMXNodeInstance.cpp",
         "OMXUtils.cpp",
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
new file mode 100644
index 0000000..09c4019
--- /dev/null
+++ b/media/libstagefright/omx/OMX.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#include <inttypes.h>
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "OMX"
+#include <utils/Log.h>
+
+#include <dlfcn.h>
+
+#include <media/stagefright/omx/OMX.h>
+#include <media/stagefright/omx/OMXNodeInstance.h>
+#include <media/stagefright/omx/BWGraphicBufferSource.h>
+#include <media/stagefright/omx/OMXMaster.h>
+#include <media/stagefright/omx/OMXUtils.h>
+#include <media/stagefright/foundation/ADebug.h>
+
+namespace android {
+
+// node ids are created by concatenating the pid with a 16-bit counter
+static size_t kMaxNodeInstances = (1 << 16);
+
+OMX::OMX() : mMaster(new OMXMaster), mParser() {
+}
+
+OMX::~OMX() {
+    delete mMaster;
+    mMaster = NULL;
+}
+
+void OMX::binderDied(const wp<IBinder> &the_late_who) {
+    sp<OMXNodeInstance> instance;
+
+    {
+        Mutex::Autolock autoLock(mLock);
+
+        ssize_t index = mLiveNodes.indexOfKey(the_late_who);
+
+        if (index < 0) {
+            ALOGE("b/27597103, nonexistent observer on binderDied");
+            android_errorWriteLog(0x534e4554, "27597103");
+            return;
+        }
+
+        instance = mLiveNodes.editValueAt(index);
+        mLiveNodes.removeItemsAt(index);
+    }
+
+    instance->onObserverDied();
+}
+
+status_t OMX::listNodes(List<ComponentInfo> *list) {
+    list->clear();
+
+    OMX_U32 index = 0;
+    char componentName[256];
+    while (mMaster->enumerateComponents(
+                componentName, sizeof(componentName), index) == OMX_ErrorNone) {
+        list->push_back(ComponentInfo());
+        ComponentInfo &info = *--list->end();
+
+        info.mName = componentName;
+
+        Vector<String8> roles;
+        OMX_ERRORTYPE err =
+            mMaster->getRolesOfComponent(componentName, &roles);
+
+        if (err == OMX_ErrorNone) {
+            for (OMX_U32 i = 0; i < roles.size(); ++i) {
+                info.mRoles.push_back(roles[i]);
+            }
+        }
+
+        ++index;
+    }
+
+    return OK;
+}
+
+status_t OMX::allocateNode(
+        const char *name, const sp<IOMXObserver> &observer,
+        sp<IOMXNode> *omxNode) {
+    Mutex::Autolock autoLock(mLock);
+
+    omxNode->clear();
+
+    if (mLiveNodes.size() == kMaxNodeInstances) {
+        return NO_MEMORY;
+    }
+
+    sp<OMXNodeInstance> instance = new OMXNodeInstance(this, observer, name);
+
+    OMX_COMPONENTTYPE *handle;
+    OMX_ERRORTYPE err = mMaster->makeComponentInstance(
+            name, &OMXNodeInstance::kCallbacks,
+            instance.get(), &handle);
+
+    if (err != OMX_ErrorNone) {
+        ALOGE("FAILED to allocate omx component '%s' err=%s(%#x)", name, asString(err), err);
+
+        return StatusFromOMXError(err);
+    }
+    instance->setHandle(handle);
+
+    // Find quirks from mParser
+    const auto& codec = mParser.getCodecMap().find(name);
+    if (codec == mParser.getCodecMap().cend()) {
+        ALOGW("Failed to obtain quirks for omx component '%s' from XML files",
+                name);
+    } else {
+        uint32_t quirks = 0;
+        for (const auto& quirk : codec->second.quirkSet) {
+            if (quirk == "requires-allocate-on-input-ports") {
+                quirks |= OMXNodeInstance::
+                        kRequiresAllocateBufferOnInputPorts;
+            }
+            if (quirk == "requires-allocate-on-output-ports") {
+                quirks |= OMXNodeInstance::
+                        kRequiresAllocateBufferOnOutputPorts;
+            }
+        }
+        instance->setQuirks(quirks);
+    }
+
+    mLiveNodes.add(IInterface::asBinder(observer), instance);
+    IInterface::asBinder(observer)->linkToDeath(this);
+
+    *omxNode = instance;
+
+    return OK;
+}
+
+status_t OMX::freeNode(const sp<OMXNodeInstance> &instance) {
+    if (instance == NULL) {
+        return OK;
+    }
+
+    {
+        Mutex::Autolock autoLock(mLock);
+        ssize_t index = mLiveNodes.indexOfKey(IInterface::asBinder(instance->observer()));
+        if (index < 0) {
+            // This could conceivably happen if the observer dies at roughly the
+            // same time that a client attempts to free the node explicitly.
+
+            // NOTE: it's guaranteed that this method is called at most once per
+            //       instance.
+            ALOGV("freeNode: instance already removed from book-keeping.");
+        } else {
+            mLiveNodes.removeItemsAt(index);
+            IInterface::asBinder(instance->observer())->unlinkToDeath(this);
+        }
+    }
+
+    CHECK(instance->handle() != NULL);
+    OMX_ERRORTYPE err = mMaster->destroyComponentInstance(
+            static_cast<OMX_COMPONENTTYPE *>(instance->handle()));
+    ALOGV("freeNode: handle destroyed: %p", instance->handle());
+
+    return StatusFromOMXError(err);
+}
+
+status_t OMX::createInputSurface(
+        sp<IGraphicBufferProducer> *bufferProducer,
+        sp<IGraphicBufferSource> *bufferSource) {
+    if (bufferProducer == NULL || bufferSource == NULL) {
+        ALOGE("b/25884056");
+        return BAD_VALUE;
+    }
+
+    sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource();
+    status_t err = graphicBufferSource->initCheck();
+    if (err != OK) {
+        ALOGE("Failed to create persistent input surface: %s (%d)",
+                strerror(-err), err);
+        return err;
+    }
+
+    *bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
+    *bufferSource = new BWGraphicBufferSource(graphicBufferSource);
+
+    return OK;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index ff58eb6..015a148 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -344,7 +344,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 OMXNodeInstance::OMXNodeInstance(
-        Omx *owner, const sp<IOMXObserver> &observer, const char *name)
+        OmxNodeOwner *owner, const sp<IOMXObserver> &observer, const char *name)
     : mOwner(owner),
       mHandle(NULL),
       mObserver(observer),
diff --git a/media/libstagefright/omx/OMXStore.cpp b/media/libstagefright/omx/OMXStore.cpp
new file mode 100644
index 0000000..345336d
--- /dev/null
+++ b/media/libstagefright/omx/OMXStore.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "OMXStore"
+#include <utils/Log.h>
+
+#include <media/stagefright/omx/OMXUtils.h>
+#include <media/stagefright/omx/OMX.h>
+#include <media/stagefright/omx/OMXStore.h>
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
+
+#include <map>
+#include <string>
+
+namespace android {
+
+namespace {
+    struct RoleProperties {
+        std::string type;
+        bool isEncoder;
+        bool preferPlatformNodes;
+        std::multimap<size_t, IOMXStore::NodeInfo> nodeList;
+    };
+}  // Unnamed namespace
+
+OMXStore::OMXStore(
+        const char* owner,
+        const char* const* searchDirs,
+        const char* mainXmlName,
+        const char* performanceXmlName,
+        const char* profilingResultsXmlPath) {
+    MediaCodecsXmlParser parser(
+            searchDirs,
+            mainXmlName,
+            performanceXmlName,
+            profilingResultsXmlPath);
+    mParsingStatus = parser.getParsingStatus();
+
+    const auto& serviceAttributeMap = parser.getServiceAttributeMap();
+    mServiceAttributeList.reserve(serviceAttributeMap.size());
+    for (const auto& attributePair : serviceAttributeMap) {
+        Attribute attribute;
+        attribute.key = attributePair.first;
+        attribute.value = attributePair.second;
+        mServiceAttributeList.push_back(std::move(attribute));
+    }
+
+    const auto& roleMap = parser.getRoleMap();
+    mRoleList.reserve(roleMap.size());
+    for (const auto& rolePair : roleMap) {
+        RoleInfo role;
+        role.role = rolePair.first;
+        role.type = rolePair.second.type;
+        role.isEncoder = rolePair.second.isEncoder;
+        // TODO: Currently, preferPlatformNodes information is not available in
+        // the xml file. Once we have a way to provide this information, it
+        // should be parsed properly.
+        role.preferPlatformNodes = rolePair.first.compare(0, 5, "audio") == 0;
+        std::vector<NodeInfo>& nodeList = role.nodes;
+        nodeList.reserve(rolePair.second.nodeList.size());
+        for (const auto& nodePair : rolePair.second.nodeList) {
+            NodeInfo node;
+            node.name = nodePair.second.name;
+            node.owner = owner;
+            std::vector<Attribute>& attributeList = node.attributes;
+            attributeList.reserve(nodePair.second.attributeList.size());
+            for (const auto& attributePair : nodePair.second.attributeList) {
+                Attribute attribute;
+                attribute.key = attributePair.first;
+                attribute.value = attributePair.second;
+                attributeList.push_back(std::move(attribute));
+            }
+            nodeList.push_back(std::move(node));
+        }
+        mRoleList.push_back(std::move(role));
+    }
+
+    mPrefix = parser.getCommonPrefix();
+}
+
+status_t OMXStore::listServiceAttributes(std::vector<Attribute>* attributes) {
+    *attributes = mServiceAttributeList;
+    return mParsingStatus;
+}
+
+status_t OMXStore::getNodePrefix(std::string* prefix) {
+    *prefix = mPrefix;
+    return mParsingStatus;
+}
+
+status_t OMXStore::listRoles(std::vector<RoleInfo>* roleList) {
+    *roleList = mRoleList;
+    return mParsingStatus;
+}
+
+status_t OMXStore::getOmx(const std::string& name, sp<IOMX>* omx) {
+    *omx = new OMX();
+    return NO_ERROR;
+}
+
+OMXStore::~OMXStore() {
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h b/media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h
index baa7b81..a6a9d3e 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h
@@ -20,13 +20,13 @@
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
 
+#include <media/stagefright/omx/OMXNodeInstance.h>
 #include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
 #include <android/hardware/media/omx/1.0/IOmx.h>
 
 namespace android {
 
 struct OMXMaster;
-struct OMXNodeInstance;
 
 namespace hardware {
 namespace media {
@@ -50,9 +50,10 @@
 using ::android::wp;
 
 using ::android::OMXMaster;
+using ::android::OmxNodeOwner;
 using ::android::OMXNodeInstance;
 
-struct Omx : public IOmx, public hidl_death_recipient {
+struct Omx : public IOmx, public hidl_death_recipient, public OmxNodeOwner {
     Omx();
     virtual ~Omx();
 
@@ -67,8 +68,8 @@
     // Method from hidl_death_recipient
     void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
 
-    // Method for OMXNodeInstance
-    status_t freeNode(sp<OMXNodeInstance> const& instance);
+    // Method from OmxNodeOwner
+    virtual status_t freeNode(sp<OMXNodeInstance> const& instance) override;
 
 protected:
     OMXMaster* mMaster;
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/OMX.h b/media/libstagefright/omx/include/media/stagefright/omx/OMX.h
new file mode 100644
index 0000000..594b4c0
--- /dev/null
+++ b/media/libstagefright/omx/include/media/stagefright/omx/OMX.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef ANDROID_OMX_H_
+#define ANDROID_OMX_H_
+
+#include <media/IOMX.h>
+#include <utils/threads.h>
+#include <utils/KeyedVector.h>
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
+#include "OmxNodeOwner.h"
+
+namespace android {
+
+struct OMXMaster;
+struct OMXNodeInstance;
+
+class OMX : public BnOMX,
+            public OmxNodeOwner,
+            public IBinder::DeathRecipient {
+public:
+    OMX();
+
+    virtual status_t listNodes(List<ComponentInfo> *list);
+
+    virtual status_t allocateNode(
+            const char *name, const sp<IOMXObserver> &observer,
+            sp<IOMXNode> *omxNode);
+
+    virtual status_t createInputSurface(
+            sp<IGraphicBufferProducer> *bufferProducer,
+            sp<IGraphicBufferSource> *bufferSource);
+
+    virtual void binderDied(const wp<IBinder> &the_late_who);
+
+    virtual status_t freeNode(const sp<OMXNodeInstance>& instance);
+
+protected:
+    virtual ~OMX();
+
+private:
+    Mutex mLock;
+    OMXMaster *mMaster;
+    MediaCodecsXmlParser mParser;
+
+    KeyedVector<wp<IBinder>, sp<OMXNodeInstance> > mLiveNodes;
+
+    OMX(const OMX &);
+    OMX &operator=(const OMX &);
+};
+
+}  // namespace android
+
+#endif  // ANDROID_OMX_H_
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h b/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
index c436121..1065ca5 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
@@ -25,9 +25,9 @@
 #include <utils/threads.h>
 #include <utils/KeyedVector.h>
 #include <utils/SortedVector.h>
+#include "OmxNodeOwner.h"
 
 #include <android/hidl/memory/1.0/IMemory.h>
-#include <media/stagefright/omx/1.0/Omx.h>
 
 namespace android {
 class GraphicBuffer;
@@ -35,12 +35,11 @@
 class IOMXObserver;
 struct OMXMaster;
 class OMXBuffer;
-using IHidlMemory = hidl::memory::V1_0::IMemory;
-using hardware::media::omx::V1_0::implementation::Omx;
+typedef hidl::memory::V1_0::IMemory IHidlMemory;
 
 struct OMXNodeInstance : public BnOMXNode {
     OMXNodeInstance(
-            Omx *owner, const sp<IOMXObserver> &observer, const char *name);
+            OmxNodeOwner *owner, const sp<IOMXObserver> &observer, const char *name);
 
     void setHandle(OMX_HANDLETYPE handle);
 
@@ -123,7 +122,7 @@
 
     Mutex mLock;
 
-    Omx *mOwner;
+    OmxNodeOwner *mOwner;
     OMX_HANDLETYPE mHandle;
     sp<IOMXObserver> mObserver;
     sp<CallbackDispatcher> mDispatcher;
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/OMXStore.h b/media/libstagefright/omx/include/media/stagefright/omx/OMXStore.h
new file mode 100644
index 0000000..e00d713
--- /dev/null
+++ b/media/libstagefright/omx/include/media/stagefright/omx/OMXStore.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef ANDROID_OMXSTORE_H_
+#define ANDROID_OMXSTORE_H_
+
+#include <media/IOMXStore.h>
+#include <media/IOMX.h>
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
+
+#include <vector>
+#include <string>
+
+namespace android {
+
+class OMXStore : public BnOMXStore {
+public:
+    OMXStore(
+            const char* owner = "default",
+            const char* const* searchDirs
+                = MediaCodecsXmlParser::defaultSearchDirs,
+            const char* mainXmlName
+                = MediaCodecsXmlParser::defaultMainXmlName,
+            const char* performanceXmlName
+                = MediaCodecsXmlParser::defaultPerformanceXmlName,
+            const char* profilingResultsXmlPath
+                = MediaCodecsXmlParser::defaultProfilingResultsXmlPath);
+
+    status_t listServiceAttributes(
+            std::vector<Attribute>* attributes) override;
+
+    status_t getNodePrefix(std::string* prefix) override;
+
+    status_t listRoles(std::vector<RoleInfo>* roleList) override;
+
+    status_t getOmx(const std::string& name, sp<IOMX>* omx) override;
+
+    ~OMXStore() override;
+
+protected:
+    status_t mParsingStatus;
+    std::string mPrefix;
+    std::vector<Attribute> mServiceAttributeList;
+    std::vector<RoleInfo> mRoleList;
+};
+
+}  // namespace android
+
+#endif  // ANDROID_OMXSTORE_H_
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 86c7211..8092887 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -25,9 +25,11 @@
 
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
+#include <binder/MemoryDealer.h>
 #include <cutils/properties.h>
 #include <media/DataSource.h>
 #include <media/IMediaHTTPService.h>
+#include <media/IMediaCodecService.h>
 #include <media/MediaExtractor.h>
 #include <media/MediaSource.h>
 #include <media/OMXBuffer.h>
@@ -69,7 +71,7 @@
 /////////////////////////////////////////////////////////////////////
 
 Harness::Harness()
-    : mInitCheck(NO_INIT) {
+    : mInitCheck(NO_INIT), mUseTreble(false) {
     mInitCheck = initOMX();
 }
 
@@ -81,12 +83,21 @@
 }
 
 status_t Harness::initOMX() {
-    using namespace ::android::hardware::media::omx::V1_0;
-    sp<IOmx> tOmx = IOmx::getService();
-    if (tOmx == nullptr) {
-        return NO_INIT;
+    if (property_get_bool("persist.media.treble_omx", true)) {
+        using namespace ::android::hardware::media::omx::V1_0;
+        sp<IOmx> tOmx = IOmx::getService();
+        if (tOmx == nullptr) {
+            return NO_INIT;
+        }
+        mOMX = new utils::LWOmx(tOmx);
+        mUseTreble = true;
+    } else {
+        sp<IServiceManager> sm = defaultServiceManager();
+        sp<IBinder> binder = sm->getService(String16("media.codec"));
+        sp<IMediaCodecService> service = interface_cast<IMediaCodecService>(binder);
+        mOMX = service->getOMX();
+        mUseTreble = false;
     }
-    mOMX = new utils::LWOmx(tOmx);
 
     return mOMX != 0 ? OK : NO_INIT;
 }
@@ -214,19 +225,25 @@
     for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
         Buffer buffer;
         buffer.mFlags = 0;
-        bool success;
-        auto transStatus = mAllocator->allocate(def.nBufferSize,
-                [&success, &buffer](
-                        bool s,
-                        hidl_memory const& m) {
-                    success = s;
-                    buffer.mHidlMemory = m;
-                });
-        EXPECT(transStatus.isOk(),
-                "Cannot call allocator");
-        EXPECT(success,
-                "Cannot allocate memory");
-        err = mOMXNode->useBuffer(portIndex, buffer.mHidlMemory, &buffer.mID);
+        if (mUseTreble) {
+            bool success;
+            auto transStatus = mAllocator->allocate(def.nBufferSize,
+                    [&success, &buffer](
+                            bool s,
+                            hidl_memory const& m) {
+                        success = s;
+                        buffer.mHidlMemory = m;
+                    });
+            EXPECT(transStatus.isOk(),
+                    "Cannot call allocator");
+            EXPECT(success,
+                    "Cannot allocate memory");
+            err = mOMXNode->useBuffer(portIndex, buffer.mHidlMemory, &buffer.mID);
+        } else {
+            buffer.mMemory = mDealer->allocate(def.nBufferSize);
+            CHECK(buffer.mMemory != NULL);
+            err = mOMXNode->useBuffer(portIndex, buffer.mMemory, &buffer.mID);
+        }
 
         EXPECT_SUCCESS(err, "useBuffer");
 
@@ -295,11 +312,13 @@
         return OK;
     }
 
-    mAllocator = IAllocator::getService("ashmem");
-    EXPECT(mAllocator != nullptr,
-            "Cannot obtain hidl AshmemAllocator");
-    // TODO: When Treble has MemoryHeap/MemoryDealer, we should specify the heap
-    // size to be 16 * 1024 * 1024.
+    if (mUseTreble) {
+        mAllocator = IAllocator::getService("ashmem");
+        EXPECT(mAllocator != nullptr,
+                "Cannot obtain hidl AshmemAllocator");
+    } else {
+        mDealer = new MemoryDealer(16 * 1024 * 1024, "OMXHarness");
+    }
 
     sp<CodecObserver> observer = new CodecObserver(this, ++mCurGeneration);
 
diff --git a/media/libstagefright/omx/tests/OMXHarness.h b/media/libstagefright/omx/tests/OMXHarness.h
index dca787c..4fc0f79 100644
--- a/media/libstagefright/omx/tests/OMXHarness.h
+++ b/media/libstagefright/omx/tests/OMXHarness.h
@@ -93,6 +93,8 @@
     Condition mMessageAddedCondition;
     int32_t mLastMsgGeneration;
     int32_t mCurGeneration;
+    bool mUseTreble;
+    sp<MemoryDealer> mDealer;
     sp<IAllocator> mAllocator;
 
     status_t initOMX();
diff --git a/media/ndk/NdkImage.cpp b/media/ndk/NdkImage.cpp
index c4ff537..20b1667 100644
--- a/media/ndk/NdkImage.cpp
+++ b/media/ndk/NdkImage.cpp
@@ -37,8 +37,8 @@
         mTimestamp(timestamp), mWidth(width), mHeight(height), mNumPlanes(numPlanes) {
 }
 
-// Can only be called by free() with mLock hold
 AImage::~AImage() {
+    Mutex::Autolock _l(mLock);
     if (!mIsClosed) {
         LOG_ALWAYS_FATAL(
                 "Error: AImage %p is deleted before returning buffer to AImageReader!", this);
@@ -78,7 +78,6 @@
         ALOGE("Cannot free AImage before close!");
         return;
     }
-    Mutex::Autolock _l(mLock);
     delete this;
 }
 
diff --git a/media/ndk/OWNERS b/media/ndk/OWNERS
index 43e4bb3..11e8340 100644
--- a/media/ndk/OWNERS
+++ b/media/ndk/OWNERS
@@ -1 +1,5 @@
 marcone@google.com
+# For AImage/AImageReader
+etalvala@google.com
+yinchiayeh@google.com
+zhijunhe@google.com
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 31f0550..9bd68e1 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -35,7 +35,8 @@
  * A device mask for all audio input devices that are considered "virtual" when evaluating
  * active inputs in getActiveInputs()
  */
-#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL  (AUDIO_DEVICE_IN_REMOTE_SUBMIX)
+#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX|\
+        AUDIO_DEVICE_IN_BUS|AUDIO_DEVICE_IN_FM_TUNER)
 
 
 /**
diff --git a/services/mediaanalytics/MediaAnalyticsService.cpp b/services/mediaanalytics/MediaAnalyticsService.cpp
index f08be50..83992aa 100644
--- a/services/mediaanalytics/MediaAnalyticsService.cpp
+++ b/services/mediaanalytics/MediaAnalyticsService.cpp
@@ -318,6 +318,7 @@
                 saveItem(mFinalized, oitem, 0);
             }
             // new record could itself be marked finalized...
+            id = item->getSessionID();
             if (finalizing) {
                 summarize(item);
                 saveItem(mFinalized, item, 0);
@@ -325,16 +326,15 @@
             } else {
                 saveItem(mOpen, item, 1);
             }
-            id = item->getSessionID();
         } else {
             // combine the records, send it to finalized if appropriate
             oitem->merge(item);
+            id = oitem->getSessionID();
             if (finalizing) {
                 summarize(oitem);
                 saveItem(mFinalized, oitem, 0);
                 mItemsFinalized++;
             }
-            id = oitem->getSessionID();
 
             // we're responsible for disposing of the dead record
             delete item;
@@ -614,17 +614,28 @@
 // caller should hold mLock
 void MediaAnalyticsService::saveItem(List<MediaAnalyticsItem *> *l, MediaAnalyticsItem * item, int front) {
 
-    // adding at back of queue (fifo order)
     if (front)  {
+        // for non-finalized stuff, since we expect to reference it again soon,
+        // make it quicker to find (nearer the front of our list)
         l->push_front(item);
     } else {
+        // for finalized records, which we want to dump 'in sequence order'
         l->push_back(item);
     }
 
+    // our reclaim process is for oldest-first queues
+    if (front) {
+        return;
+    }
+
+
     // keep removing old records the front until we're in-bounds (count)
     if (mMaxRecords > 0) {
         while (l->size() > (size_t) mMaxRecords) {
             MediaAnalyticsItem * oitem = *(l->begin());
+            if (oitem == item) {
+                break;
+            }
             l->erase(l->begin());
             delete oitem;
             mItemsDiscarded++;
@@ -638,6 +649,9 @@
         while (l->size() > 0) {
             MediaAnalyticsItem * oitem = *(l->begin());
             nsecs_t when = oitem->getTimestamp();
+            if (oitem == item) {
+                break;
+            }
             // careful about timejumps too
             if ((now > when) && (now-when) <= mMaxRecordAgeNs) {
                 // this (and the rest) are recent enough to keep
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index 9348ecd..faeb0a7 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -1,11 +1,28 @@
 LOCAL_PATH := $(call my-dir)
 
+# service library
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := MediaCodecService.cpp
+LOCAL_SHARED_LIBRARIES := \
+    libmedia_omx \
+    libbinder \
+    libgui \
+    libutils \
+    liblog \
+    libstagefright_omx \
+    libstagefright_xmlparser
+LOCAL_MODULE:= libmediacodecservice
+LOCAL_VENDOR_MODULE := true
+LOCAL_32_BIT_ONLY := true
+include $(BUILD_SHARED_LIBRARY)
+
 # service executable
 include $(CLEAR_VARS)
 LOCAL_REQUIRED_MODULES_arm := mediacodec.policy
 LOCAL_SRC_FILES := main_codecservice.cpp
 LOCAL_SHARED_LIBRARIES := \
     libmedia_omx \
+    libmediacodecservice \
     libbinder \
     libutils \
     libgui \
@@ -25,11 +42,6 @@
 LOCAL_VENDOR_MODULE := true
 LOCAL_32_BIT_ONLY := true
 LOCAL_INIT_RC := android.hardware.media.omx@1.0-service.rc
-
-ifeq ($(PRODUCT_FULL_TREBLE),true)
-LOCAL_CFLAGS += -DUSE_VNDBINDER
-endif
-
 include $(BUILD_EXECUTABLE)
 
 # service seccomp policy
diff --git a/services/mediacodec/MediaCodecService.cpp b/services/mediacodec/MediaCodecService.cpp
new file mode 100644
index 0000000..6b510c6
--- /dev/null
+++ b/services/mediacodec/MediaCodecService.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#define LOG_TAG "MediaCodecService"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include "MediaCodecService.h"
+
+namespace android {
+
+sp<IOMX> MediaCodecService::getOMX() {
+
+    Mutex::Autolock autoLock(mOMXLock);
+
+    if (mOMX.get() == NULL) {
+        mOMX = new OMX();
+    }
+
+    return mOMX;
+}
+
+sp<IOMXStore> MediaCodecService::getOMXStore() {
+
+    Mutex::Autolock autoLock(mOMXStoreLock);
+
+    if (mOMXStore.get() == NULL) {
+        mOMXStore = new OMXStore();
+    }
+
+    return mOMXStore;
+}
+
+status_t MediaCodecService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+        uint32_t flags)
+{
+    return BnMediaCodecService::onTransact(code, data, reply, flags);
+}
+
+}   // namespace android
diff --git a/services/mediacodec/MediaCodecService.h b/services/mediacodec/MediaCodecService.h
new file mode 100644
index 0000000..9301135
--- /dev/null
+++ b/services/mediacodec/MediaCodecService.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ANDROID_MEDIA_CODEC_SERVICE_H
+#define ANDROID_MEDIA_CODEC_SERVICE_H
+
+#include <binder/BinderService.h>
+#include <media/IMediaCodecService.h>
+#include <media/stagefright/omx/OMX.h>
+#include <media/stagefright/omx/OMXStore.h>
+
+namespace android {
+
+class MediaCodecService : public BinderService<MediaCodecService>,
+        public BnMediaCodecService
+{
+    friend class BinderService<MediaCodecService>;    // for MediaCodecService()
+public:
+    MediaCodecService() : BnMediaCodecService() { }
+    virtual ~MediaCodecService() { }
+    virtual void onFirstRef() { }
+
+    static const char*    getServiceName() { return "media.codec"; }
+
+    virtual sp<IOMX>      getOMX();
+
+    virtual sp<IOMXStore> getOMXStore();
+
+    virtual status_t      onTransact(uint32_t code, const Parcel& data,
+                                     Parcel* reply, uint32_t flags);
+
+private:
+    Mutex                 mOMXLock;
+    sp<IOMX>              mOMX;
+    Mutex                 mOMXStoreLock;
+    sp<IOMXStore>         mOMXStore;
+};
+
+}   // namespace android
+
+#endif  // ANDROID_MEDIA_CODEC_SERVICE_H
diff --git a/services/mediacodec/main_codecservice.cpp b/services/mediacodec/main_codecservice.cpp
index 6bb3fa2..79d6da5 100644
--- a/services/mediacodec/main_codecservice.cpp
+++ b/services/mediacodec/main_codecservice.cpp
@@ -15,12 +15,22 @@
 ** limitations under the License.
 */
 
+#include <fcntl.h>
+#include <sys/prctl.h>
+#include <sys/wait.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <cutils/properties.h>
+
+#include <string>
+
 #include <android-base/logging.h>
 
 // from LOCAL_C_INCLUDES
+#include "MediaCodecService.h"
 #include "minijail.h"
 
-#include <binder/ProcessState.h>
 #include <hidl/HidlTransportSupport.h>
 #include <media/stagefright/omx/1.0/Omx.h>
 #include <media/stagefright/omx/1.0/OmxStore.h>
@@ -36,11 +46,10 @@
 int main(int argc __unused, char** argv)
 {
     LOG(INFO) << "mediacodecservice starting";
-
-#ifdef USE_VNDBINDER
-    android::ProcessState::initWithDriver("/dev/vndbinder");
-    android::ProcessState::self()->startThreadPool();
-#endif // USE_VNDBINDER
+    bool treble = property_get_bool("persist.media.treble_omx", true);
+    if (treble) {
+      android::ProcessState::initWithDriver("/dev/vndbinder");
+    }
 
     signal(SIGPIPE, SIG_IGN);
     SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);
@@ -48,22 +57,29 @@
     strcpy(argv[0], "media.codec");
 
     ::android::hardware::configureRpcThreadpool(64, false);
+    sp<ProcessState> proc(ProcessState::self());
 
-    using namespace ::android::hardware::media::omx::V1_0;
-    sp<IOmxStore> omxStore = new implementation::OmxStore();
-    if (omxStore == nullptr) {
-        LOG(ERROR) << "Cannot create IOmxStore HAL service.";
-    } else if (omxStore->registerAsService() != OK) {
-        LOG(ERROR) << "Cannot register IOmxStore HAL service.";
-    }
-    sp<IOmx> omx = new implementation::Omx();
-    if (omx == nullptr) {
-        LOG(ERROR) << "Cannot create IOmx HAL service.";
-    } else if (omx->registerAsService() != OK) {
-        LOG(ERROR) << "Cannot register IOmx HAL service.";
+    if (treble) {
+        using namespace ::android::hardware::media::omx::V1_0;
+        sp<IOmxStore> omxStore = new implementation::OmxStore();
+        if (omxStore == nullptr) {
+            LOG(ERROR) << "Cannot create IOmxStore HAL service.";
+        } else if (omxStore->registerAsService() != OK) {
+            LOG(ERROR) << "Cannot register IOmxStore HAL service.";
+        }
+        sp<IOmx> omx = new implementation::Omx();
+        if (omx == nullptr) {
+            LOG(ERROR) << "Cannot create IOmx HAL service.";
+        } else if (omx->registerAsService() != OK) {
+            LOG(ERROR) << "Cannot register IOmx HAL service.";
+        } else {
+            LOG(INFO) << "Treble OMX service created.";
+        }
     } else {
-        LOG(INFO) << "IOmx HAL service created.";
+        MediaCodecService::instantiate();
+        LOG(INFO) << "Non-Treble OMX service created.";
     }
 
-    ::android::hardware::joinRpcThreadpool();
+    ProcessState::self()->startThreadPool();
+    IPCThreadState::self()->joinThreadPool();
 }
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index 6d833aa..a7d6e83 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -313,7 +313,7 @@
 }
 
 
-sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent_l(sound_trigger_service_state_t state)
+sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent(sound_trigger_service_state_t state)
 {
     AutoMutex lock(mMemoryDealerLock);
     sp<IMemory> eventMemory;
@@ -328,34 +328,23 @@
     return eventMemory;
 }
 
-// call with mServiceLock held
-void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
+void SoundTriggerHwService::sendServiceStateEvent(sound_trigger_service_state_t state,
                                                   Module *module)
 {
-    sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
+    sp<IMemory> eventMemory = prepareServiceStateEvent(state);
     if (eventMemory == 0) {
         return;
     }
-    sp<Module> strongModule;
-    for (size_t i = 0; i < mModules.size(); i++) {
-        if (mModules.valueAt(i).get() == module) {
-            strongModule = mModules.valueAt(i);
-            break;
-        }
-    }
-    if (strongModule == 0) {
-        return;
-    }
     sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
                                                         eventMemory);
-    callbackEvent->setModule(strongModule);
+    callbackEvent->setModule(module);
     sendCallbackEvent(callbackEvent);
 }
 
-void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
-                                                    ModuleClient *moduleClient)
+void SoundTriggerHwService::sendServiceStateEvent(sound_trigger_service_state_t state,
+                                                  ModuleClient *moduleClient)
 {
-    sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
+    sp<IMemory> eventMemory = prepareServiceStateEvent(state);
     if (eventMemory == 0) {
         return;
     }
@@ -906,7 +895,7 @@
     }
 
 exit:
-    service->sendServiceStateEvent_l(state, this);
+    service->sendServiceStateEvent(state, this);
 }
 
 
@@ -1051,7 +1040,7 @@
             return;
         }
     }
-    service->sendServiceStateEvent_l(state, this);
+    service->sendServiceStateEvent(state, this);
 }
 
 void SoundTriggerHwService::ModuleClient::onCallbackEvent(const sp<CallbackEvent>& event)
diff --git a/services/soundtrigger/SoundTriggerHwService.h b/services/soundtrigger/SoundTriggerHwService.h
index a955f40..708fc98 100644
--- a/services/soundtrigger/SoundTriggerHwService.h
+++ b/services/soundtrigger/SoundTriggerHwService.h
@@ -221,10 +221,10 @@
            sp<IMemory> prepareSoundModelEvent(struct sound_trigger_model_event *event);
            void sendSoundModelEvent(struct sound_trigger_model_event *event, Module *module);
 
-           sp<IMemory> prepareServiceStateEvent_l(sound_trigger_service_state_t state);
-           void sendServiceStateEvent_l(sound_trigger_service_state_t state, Module *module);
-           void sendServiceStateEvent_l(sound_trigger_service_state_t state,
-                                        ModuleClient *moduleClient);
+           sp<IMemory> prepareServiceStateEvent(sound_trigger_service_state_t state);
+           void sendServiceStateEvent(sound_trigger_service_state_t state, Module *module);
+           void sendServiceStateEvent(sound_trigger_service_state_t state,
+                                      ModuleClient *moduleClient);
 
            void sendCallbackEvent(const sp<CallbackEvent>& event);
            void onCallbackEvent(const sp<CallbackEvent>& event);