Integrate API Council feedback into Media Metrics APIs

Integrates the API Council's feedback into the Media Metrics
related APIs.
-- return types for the getMetrics() calls
-- definition of keys in the set of data that comes back

Bug: 35811992
Test: booted, CTS subset, checked dumpsys media.metrics output
Change-Id: Ib750f9631bd3453be3132760273ccfff0a891f88
diff --git a/api/current.txt b/api/current.txt
index d68610e..ca95051 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -21787,7 +21787,7 @@
     method public deprecated java.nio.ByteBuffer[] getInputBuffers();
     method public final android.media.MediaFormat getInputFormat();
     method public android.media.Image getInputImage(int);
-    method public android.os.Bundle getMetrics();
+    method public android.media.MediaMetricsSet getMetrics();
     method public final java.lang.String getName();
     method public java.nio.ByteBuffer getOutputBuffer(int);
     method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
@@ -22339,7 +22339,7 @@
     method public boolean advance();
     method public long getCachedDuration();
     method public android.media.DrmInitData getDrmInitData();
-    method public android.os.Bundle getMetrics();
+    method public android.media.MediaMetricsSet getMetrics();
     method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
     method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
     method public int getSampleFlags();
@@ -22594,6 +22594,69 @@
     field public static final int OPTION_PREVIOUS_SYNC = 0; // 0x0
   }
 
+  public final class MediaMetricsSet {
+    method public double getDouble(java.lang.String, double);
+    method public int getInt(java.lang.String, int);
+    method public long getLong(java.lang.String, long);
+    method public java.lang.String getString(java.lang.String, java.lang.String);
+    method public boolean isEmpty();
+    method public java.util.Set<java.lang.String> keySet();
+    method public int size();
+  }
+
+  public static final class MediaMetricsSet.MediaCodec {
+    field public static final java.lang.String KEY_CODEC = "android.media.mediacodec.codec";
+    field public static final java.lang.String KEY_ENCODER = "android.media.mediacodec.encoder";
+    field public static final java.lang.String KEY_HEIGHT = "android.media.mediacodec.height";
+    field public static final java.lang.String KEY_MIME = "android.media.mediacodec.mime";
+    field public static final java.lang.String KEY_MODE = "android.media.mediacodec.mode";
+    field public static final java.lang.String KEY_ROTATION = "android.media.mediacodec.rotation";
+    field public static final java.lang.String KEY_SECURE = "android.media.mediacodec.secure";
+    field public static final java.lang.String KEY_WIDTH = "android.media.mediacodec.width";
+    field public static final java.lang.String MODE_AUDIO = "audio";
+    field public static final java.lang.String MODE_VIDEO = "video";
+  }
+
+  public static final class MediaMetricsSet.MediaExtractor {
+    field public static final java.lang.String KEY_FORMAT = "android.media.mediaextractor.fmt";
+    field public static final java.lang.String KEY_MIME = "android.media.mediaextractor.mime";
+    field public static final java.lang.String KEY_TRACKS = "android.media.mediaextractor.ntrk";
+  }
+
+  public static final class MediaMetricsSet.MediaPlayer {
+    field public static final java.lang.String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
+    field public static final java.lang.String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec";
+    field public static final java.lang.String KEY_DURATION = "android.media.mediaplayer.durationMs";
+    field public static final java.lang.String KEY_ERRORS = "android.media.mediaplayer.err";
+    field public static final java.lang.String KEY_ERROR_CODE = "android.media.mediaplayer.errcode";
+    field public static final java.lang.String KEY_FRAMES = "android.media.mediaplayer.frames";
+    field public static final java.lang.String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped";
+    field public static final java.lang.String KEY_HEIGHT = "android.media.mediaplayer.height";
+    field public static final java.lang.String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime";
+    field public static final java.lang.String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime";
+    field public static final java.lang.String KEY_PLAYING = "android.media.mediaplayer.playingMs";
+    field public static final java.lang.String KEY_WIDTH = "android.media.mediaplayer.width";
+  }
+
+  public static final class MediaMetricsSet.MediaRecorder {
+    field public static final java.lang.String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
+    field public static final java.lang.String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
+    field public static final java.lang.String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
+    field public static final java.lang.String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
+    field public static final java.lang.String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
+    field public static final java.lang.String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
+    field public static final java.lang.String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate";
+    field public static final java.lang.String KEY_HEIGHT = "android.media.mediarecorder.height";
+    field public static final java.lang.String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
+    field public static final java.lang.String KEY_ROTATION = "android.media.mediarecorder.rotation";
+    field public static final java.lang.String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
+    field public static final java.lang.String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
+    field public static final java.lang.String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
+    field public static final java.lang.String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
+    field public static final java.lang.String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
+    field public static final java.lang.String KEY_WIDTH = "android.media.mediarecorder.width";
+  }
+
   public final class MediaMuxer {
     ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
     ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException;
@@ -22634,7 +22697,7 @@
     method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
     method public int getDuration();
     method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
-    method public android.os.Bundle getMetrics();
+    method public android.media.MediaMetricsSet getMetrics();
     method public android.media.PlaybackParams getPlaybackParams();
     method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
     method public android.media.SyncParams getSyncParams();
@@ -22802,7 +22865,7 @@
     ctor public MediaRecorder();
     method public static final int getAudioSourceMax();
     method public int getMaxAmplitude() throws java.lang.IllegalStateException;
-    method public android.os.Bundle getMetrics();
+    method public android.media.MediaMetricsSet getMetrics();
     method public android.view.Surface getSurface();
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
diff --git a/api/system-current.txt b/api/system-current.txt
index cb0d7b1..132ebf4 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -23579,7 +23579,7 @@
     method public deprecated java.nio.ByteBuffer[] getInputBuffers();
     method public final android.media.MediaFormat getInputFormat();
     method public android.media.Image getInputImage(int);
-    method public android.os.Bundle getMetrics();
+    method public android.media.MediaMetricsSet getMetrics();
     method public final java.lang.String getName();
     method public java.nio.ByteBuffer getOutputBuffer(int);
     method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
@@ -24131,7 +24131,7 @@
     method public boolean advance();
     method public long getCachedDuration();
     method public android.media.DrmInitData getDrmInitData();
-    method public android.os.Bundle getMetrics();
+    method public android.media.MediaMetricsSet getMetrics();
     method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
     method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
     method public int getSampleFlags();
@@ -24386,6 +24386,69 @@
     field public static final int OPTION_PREVIOUS_SYNC = 0; // 0x0
   }
 
+  public final class MediaMetricsSet {
+    method public double getDouble(java.lang.String, double);
+    method public int getInt(java.lang.String, int);
+    method public long getLong(java.lang.String, long);
+    method public java.lang.String getString(java.lang.String, java.lang.String);
+    method public boolean isEmpty();
+    method public java.util.Set<java.lang.String> keySet();
+    method public int size();
+  }
+
+  public static final class MediaMetricsSet.MediaCodec {
+    field public static final java.lang.String KEY_CODEC = "android.media.mediacodec.codec";
+    field public static final java.lang.String KEY_ENCODER = "android.media.mediacodec.encoder";
+    field public static final java.lang.String KEY_HEIGHT = "android.media.mediacodec.height";
+    field public static final java.lang.String KEY_MIME = "android.media.mediacodec.mime";
+    field public static final java.lang.String KEY_MODE = "android.media.mediacodec.mode";
+    field public static final java.lang.String KEY_ROTATION = "android.media.mediacodec.rotation";
+    field public static final java.lang.String KEY_SECURE = "android.media.mediacodec.secure";
+    field public static final java.lang.String KEY_WIDTH = "android.media.mediacodec.width";
+    field public static final java.lang.String MODE_AUDIO = "audio";
+    field public static final java.lang.String MODE_VIDEO = "video";
+  }
+
+  public static final class MediaMetricsSet.MediaExtractor {
+    field public static final java.lang.String KEY_FORMAT = "android.media.mediaextractor.fmt";
+    field public static final java.lang.String KEY_MIME = "android.media.mediaextractor.mime";
+    field public static final java.lang.String KEY_TRACKS = "android.media.mediaextractor.ntrk";
+  }
+
+  public static final class MediaMetricsSet.MediaPlayer {
+    field public static final java.lang.String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
+    field public static final java.lang.String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec";
+    field public static final java.lang.String KEY_DURATION = "android.media.mediaplayer.durationMs";
+    field public static final java.lang.String KEY_ERRORS = "android.media.mediaplayer.err";
+    field public static final java.lang.String KEY_ERROR_CODE = "android.media.mediaplayer.errcode";
+    field public static final java.lang.String KEY_FRAMES = "android.media.mediaplayer.frames";
+    field public static final java.lang.String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped";
+    field public static final java.lang.String KEY_HEIGHT = "android.media.mediaplayer.height";
+    field public static final java.lang.String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime";
+    field public static final java.lang.String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime";
+    field public static final java.lang.String KEY_PLAYING = "android.media.mediaplayer.playingMs";
+    field public static final java.lang.String KEY_WIDTH = "android.media.mediaplayer.width";
+  }
+
+  public static final class MediaMetricsSet.MediaRecorder {
+    field public static final java.lang.String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
+    field public static final java.lang.String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
+    field public static final java.lang.String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
+    field public static final java.lang.String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
+    field public static final java.lang.String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
+    field public static final java.lang.String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
+    field public static final java.lang.String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate";
+    field public static final java.lang.String KEY_HEIGHT = "android.media.mediarecorder.height";
+    field public static final java.lang.String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
+    field public static final java.lang.String KEY_ROTATION = "android.media.mediarecorder.rotation";
+    field public static final java.lang.String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
+    field public static final java.lang.String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
+    field public static final java.lang.String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
+    field public static final java.lang.String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
+    field public static final java.lang.String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
+    field public static final java.lang.String KEY_WIDTH = "android.media.mediarecorder.width";
+  }
+
   public final class MediaMuxer {
     ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
     ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException;
@@ -24426,7 +24489,7 @@
     method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
     method public int getDuration();
     method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
-    method public android.os.Bundle getMetrics();
+    method public android.media.MediaMetricsSet getMetrics();
     method public android.media.PlaybackParams getPlaybackParams();
     method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
     method public android.media.SyncParams getSyncParams();
@@ -24594,7 +24657,7 @@
     ctor public MediaRecorder();
     method public static final int getAudioSourceMax();
     method public int getMaxAmplitude() throws java.lang.IllegalStateException;
-    method public android.os.Bundle getMetrics();
+    method public android.media.MediaMetricsSet getMetrics();
     method public android.view.Surface getSurface();
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
diff --git a/api/test-current.txt b/api/test-current.txt
index f8e6785..04dfe80 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -21888,7 +21888,7 @@
     method public deprecated java.nio.ByteBuffer[] getInputBuffers();
     method public final android.media.MediaFormat getInputFormat();
     method public android.media.Image getInputImage(int);
-    method public android.os.Bundle getMetrics();
+    method public android.media.MediaMetricsSet getMetrics();
     method public final java.lang.String getName();
     method public java.nio.ByteBuffer getOutputBuffer(int);
     method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
@@ -22440,7 +22440,7 @@
     method public boolean advance();
     method public long getCachedDuration();
     method public android.media.DrmInitData getDrmInitData();
-    method public android.os.Bundle getMetrics();
+    method public android.media.MediaMetricsSet getMetrics();
     method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
     method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
     method public int getSampleFlags();
@@ -22695,6 +22695,69 @@
     field public static final int OPTION_PREVIOUS_SYNC = 0; // 0x0
   }
 
+  public final class MediaMetricsSet {
+    method public double getDouble(java.lang.String, double);
+    method public int getInt(java.lang.String, int);
+    method public long getLong(java.lang.String, long);
+    method public java.lang.String getString(java.lang.String, java.lang.String);
+    method public boolean isEmpty();
+    method public java.util.Set<java.lang.String> keySet();
+    method public int size();
+  }
+
+  public static final class MediaMetricsSet.MediaCodec {
+    field public static final java.lang.String KEY_CODEC = "android.media.mediacodec.codec";
+    field public static final java.lang.String KEY_ENCODER = "android.media.mediacodec.encoder";
+    field public static final java.lang.String KEY_HEIGHT = "android.media.mediacodec.height";
+    field public static final java.lang.String KEY_MIME = "android.media.mediacodec.mime";
+    field public static final java.lang.String KEY_MODE = "android.media.mediacodec.mode";
+    field public static final java.lang.String KEY_ROTATION = "android.media.mediacodec.rotation";
+    field public static final java.lang.String KEY_SECURE = "android.media.mediacodec.secure";
+    field public static final java.lang.String KEY_WIDTH = "android.media.mediacodec.width";
+    field public static final java.lang.String MODE_AUDIO = "audio";
+    field public static final java.lang.String MODE_VIDEO = "video";
+  }
+
+  public static final class MediaMetricsSet.MediaExtractor {
+    field public static final java.lang.String KEY_FORMAT = "android.media.mediaextractor.fmt";
+    field public static final java.lang.String KEY_MIME = "android.media.mediaextractor.mime";
+    field public static final java.lang.String KEY_TRACKS = "android.media.mediaextractor.ntrk";
+  }
+
+  public static final class MediaMetricsSet.MediaPlayer {
+    field public static final java.lang.String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
+    field public static final java.lang.String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec";
+    field public static final java.lang.String KEY_DURATION = "android.media.mediaplayer.durationMs";
+    field public static final java.lang.String KEY_ERRORS = "android.media.mediaplayer.err";
+    field public static final java.lang.String KEY_ERROR_CODE = "android.media.mediaplayer.errcode";
+    field public static final java.lang.String KEY_FRAMES = "android.media.mediaplayer.frames";
+    field public static final java.lang.String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped";
+    field public static final java.lang.String KEY_HEIGHT = "android.media.mediaplayer.height";
+    field public static final java.lang.String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime";
+    field public static final java.lang.String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime";
+    field public static final java.lang.String KEY_PLAYING = "android.media.mediaplayer.playingMs";
+    field public static final java.lang.String KEY_WIDTH = "android.media.mediaplayer.width";
+  }
+
+  public static final class MediaMetricsSet.MediaRecorder {
+    field public static final java.lang.String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
+    field public static final java.lang.String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
+    field public static final java.lang.String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
+    field public static final java.lang.String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
+    field public static final java.lang.String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
+    field public static final java.lang.String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
+    field public static final java.lang.String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate";
+    field public static final java.lang.String KEY_HEIGHT = "android.media.mediarecorder.height";
+    field public static final java.lang.String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
+    field public static final java.lang.String KEY_ROTATION = "android.media.mediarecorder.rotation";
+    field public static final java.lang.String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
+    field public static final java.lang.String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
+    field public static final java.lang.String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
+    field public static final java.lang.String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
+    field public static final java.lang.String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
+    field public static final java.lang.String KEY_WIDTH = "android.media.mediarecorder.width";
+  }
+
   public final class MediaMuxer {
     ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
     ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException;
@@ -22735,7 +22798,7 @@
     method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
     method public int getDuration();
     method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
-    method public android.os.Bundle getMetrics();
+    method public android.media.MediaMetricsSet getMetrics();
     method public android.media.PlaybackParams getPlaybackParams();
     method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
     method public android.media.SyncParams getSyncParams();
@@ -22903,7 +22966,7 @@
     ctor public MediaRecorder();
     method public static final int getAudioSourceMax();
     method public int getMaxAmplitude() throws java.lang.IllegalStateException;
-    method public android.os.Bundle getMetrics();
+    method public android.media.MediaMetricsSet getMetrics();
     method public android.view.Surface getSurface();
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index d264127..13a22b4 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -23,6 +23,7 @@
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
 import android.media.MediaCodecInfo.CodecCapabilities;
+import android.media.MediaMetricsSet;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -3186,59 +3187,22 @@
     public native final String getName();
 
     /**
-     *  Returns Analytics/Metrics data about the current content being
+     *  Return Metrics data about the current codec instance.
      *
-     * @return a Bundle containing the set of attributes and values available
-     * for the media being handled by this instance of MediaCodec
+     * @return a MediaMetricsSet containing the set of attributes and values
+     * available for the media being handled by this instance of MediaCodec
+     * The attributes are descibed in {@link MediaMetricsSet.MediaCodec}.
      *
-     *  <table style="width: 0%">
-     *   <thead>
-     *    <tr>
-     *     <th>Key</th>
-     *     <th>Type</th>
-     *     <th>Description</th>
-     *    </tr>
-     *   </thead>
-     *   <tbody>
-     *    <tr>
-     *     <td>{@code "codec"}</td>
-     *     <td>String</td>
-     *     <td>Identifies the particular codec in use</td>
-     *    </tr><tr>
-     *     <td>{@code "mime"}</td>
-     *     <td>String</td>
-     *     <td>Mime type of the media being encoded/decoded</td>
-     *    </tr><tr>
-     *     <td>{@code "mode"}</td>
-     *     <td>String</td>
-     *     <td>"Audio" or "Video"</td>
-     *    </tr><tr>
-     *     <td>{@code "secure"}</td>
-     *     <td>Integer</td>
-     *     <td>Indicates whether the code is operating on secure content and
-     *         may also use capabilities in android.media.MediaCrypto</td>
-     *    </tr><tr>
-     *     <td>{@code "height"}</td>
-     *     <td>Integer</td>
-     *     <td>Height (pixels); valid only when mode=video</td>
-     *    </tr><tr>
-     *     <td>{@code "width"}</td>
-     *     <td>Integer</td>
-     *     <td>Width (pixels); valid only when mode=video</td>
-     *    </tr><tr>
-     *     <td>{@code "rotation"}</td>
-     *     <td>Integer</td>
-     *     <td>rotation (degrees) to orient the video onto the target surface;
-     *         valid only when mode=video. Note there may be additional
-     *         rotations applied when the surface is mapped to the screen.</td>
-     *    </tr>
-     *   </tbody>
-     *  </table>
-     *
-     *  Additional fields specific to individual codecs will also appear in
+     *  Additional vendor-specific fields may also be present in
      *  the return value.
      */
-    public native Bundle getMetrics();
+    public MediaMetricsSet getMetrics() {
+        Bundle bundle = native_getMetrics();
+	MediaMetricsSet mSet = new MediaMetricsSet(bundle);
+	return mSet;
+    }
+
+    private native Bundle native_getMetrics();
 
     /**
      * Change a video encoder's target bitrate on the fly. The value is an
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index b9e409d..2ed6668 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -25,6 +25,7 @@
 import android.media.MediaCodec;
 import android.media.MediaFormat;
 import android.media.MediaHTTPService;
+import android.media.MediaMetricsSet;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -651,41 +652,24 @@
     public native boolean hasCacheReachedEndOfStream();
 
     /**
-     *  Returns Analytics/Metrics data about the current media container.
+     *  Return Metrics data about the current media container.
      *
-     * @return the set of keys and values available for the media being
-     * handled by this instance of MediaExtractor
+     * @return a MediaMetricsSet containing the set of attributes and values
+     * available for the media container being handled by this instance
+     * of MediaExtractor.
+     * The attributes are descibed in {@link MediaMetricsSet.MediaExtractor}.
      *
-     *  <table style="width: 0%">
-     *   <thead>
-     *    <tr>
-     *     <th>Key</th>
-     *     <th>Type</th>
-     *     <th>Description</th>
-     *    </tr>
-     *   </thead>
-     *   <tbody>
-     *    <tr>
-     *     <td>{@code "fmt"}</td>
-     *     <td>String</td>
-     *     <td>The container format (which determines the handler)</td>
-     *    </tr><tr>
-     *     <td>{@code "mime"}</td>
-     *     <td>String</td>
-     *     <td>Mime type of the container.</td>
-     *    </tr><tr>
-     *     <td>{@code "ntrk"}</td>
-     *     <td>Integer</td>
-     *     <td>Number of tracks in the container</td>
-     *    </tr>
-     *   </tbody>
-     *  </table>
-     *
-     *  Additional fields specific to individual codecs will also appear in
+     *  Additional vendor-specific fields may also be present in
      *  the return value.
      */
-    public native Bundle getMetrics();
 
+    public MediaMetricsSet getMetrics() {
+        Bundle bundle = native_getMetrics();
+	MediaMetricsSet mSet = new MediaMetricsSet(bundle);
+	return mSet;
+    }
+
+    private native Bundle native_getMetrics();
 
     private static native final void native_init();
     private native final void native_setup();
diff --git a/media/java/android/media/MediaMetricsSet.java b/media/java/android/media/MediaMetricsSet.java
new file mode 100644
index 0000000..5ecbee2
--- /dev/null
+++ b/media/java/android/media/MediaMetricsSet.java
@@ -0,0 +1,491 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.os.Bundle;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.Runnable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
+import java.net.HttpCookie;
+import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
+import java.net.URL;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.UUID;
+import java.util.Vector;
+
+
+/**
+ * MediaMetricsSet contains the results returned by the getMetrics()
+ * methods defined in other Media classes such as
+ * {@link MediaCodec}, {@link MediaExtractor}, {@link MediaPlayer},
+ * and {@link MediaRecorder}.
+ *
+ * MediaMetricsSet behaves similarly to a {@link Bundle}. It contains
+ * a set of keys and values.
+ * Methods such as {@link #getInt} and {@link #getString} are provided
+ * to extract values of the corresponding types.
+ * The {@link #keySet} method can be used to discover all of the keys
+ * that are present in the particular instance.
+ *
+ */
+public final class MediaMetricsSet
+{
+
+    /**
+     * This MediaCodec class holds the constants defining keys related to
+     * the metrics for a MediaCodec.
+     */
+    public final static class MediaCodec
+    {
+        private MediaCodec() {}
+
+        /**
+         * Key to extract the codec being used
+         * from the {@link MediaCodec#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String KEY_CODEC = "android.media.mediacodec.codec";
+
+        /**
+         * Key to extract the MIME type
+         * from the {@link MediaCodec#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String KEY_MIME = "android.media.mediacodec.mime";
+
+        /**
+         * Key to extract what the codec mode
+         * from the {@link MediaCodec#getMetrics} return value.
+         * The value is a String. Values will be one of the constants
+	 * MODE_AUDIO or MODE_VIDEO.
+         */
+        public static final String KEY_MODE = "android.media.mediacodec.mode";
+
+	/**
+	 * The value returned for the key {@link #KEY_MODE} when the
+	 * codec is a audio codec.
+	 */
+        public static final String MODE_AUDIO = "audio";
+
+	/**
+	 * The value returned for the key {@link #KEY_MODE} when the
+	 * codec is a video codec.
+	 */
+        public static final String MODE_VIDEO = "video";
+
+        /**
+         * Key to extract the flag indicating whether the codec is running
+         * as an encoder or decoder from the {@link MediaCodec#getMetrics} return value.
+         * The value is an integer.
+         * A 0 indicates decoder; 1 indicates encoder.
+         */
+        public static final String KEY_ENCODER = "android.media.mediacodec.encoder";
+
+        /**
+         * Key to extract the flag indicating whether the codec is running
+         * in secure (DRM) mode from the {@link MediaCodec#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String KEY_SECURE = "android.media.mediacodec.secure";
+
+        /**
+         * Key to extract the width (in pixels) of the video track
+         * from the {@link MediaCodec#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String KEY_WIDTH = "android.media.mediacodec.width";
+
+        /**
+         * Key to extract the height (in pixels) of the video track
+         * from the {@link MediaCodec#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String KEY_HEIGHT = "android.media.mediacodec.height";
+
+        /**
+         * Key to extract the rotation (in degrees) to properly orient the video
+         * from the {@link MediaCodec#getMetrics} return.
+         * The value is a integer.
+         */
+        public static final String KEY_ROTATION = "android.media.mediacodec.rotation";
+
+    }
+
+    /**
+     * This class holds the constants defining keys related to
+     * the metrics for a MediaExtractor.
+     */
+    public final static class MediaExtractor
+    {
+        private MediaExtractor() {}
+
+        /**
+         * Key to extract the container format
+         * from the {@link MediaExtractor#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String KEY_FORMAT = "android.media.mediaextractor.fmt";
+
+        /**
+         * Key to extract the container MIME type
+         * from the {@link MediaExtractor#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String KEY_MIME = "android.media.mediaextractor.mime";
+
+        /**
+         * Key to extract the number of tracks in the container
+         * from the {@link MediaExtractor#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String KEY_TRACKS = "android.media.mediaextractor.ntrk";
+
+    }
+
+    /**
+     * This class holds the constants defining keys related to
+     * the metrics for a MediaPlayer.
+     */
+    public final static class MediaPlayer
+    {
+        private MediaPlayer() {}
+
+        /**
+         * Key to extract the MIME type of the video track
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime";
+
+        /**
+         * Key to extract the codec being used to decode the video track
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec";
+
+        /**
+         * Key to extract the width (in pixels) of the video track
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String KEY_WIDTH = "android.media.mediaplayer.width";
+
+        /**
+         * Key to extract the height (in pixels) of the video track
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String KEY_HEIGHT = "android.media.mediaplayer.height";
+
+        /**
+         * Key to extract the count of video frames played
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String KEY_FRAMES = "android.media.mediaplayer.frames";
+
+        /**
+         * Key to extract the count of video frames dropped
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped";
+
+        /**
+         * Key to extract the MIME type of the audio track
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime";
+
+        /**
+         * Key to extract the codec being used to decode the audio track
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
+
+        /**
+         * Key to extract the duration (in milliseconds) of the
+         * media being played
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is a long.
+         */
+        public static final String KEY_DURATION = "android.media.mediaplayer.durationMs";
+
+        /**
+         * Key to extract the playing time (in milliseconds) of the
+         * media being played
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is a long.
+         */
+        public static final String KEY_PLAYING = "android.media.mediaplayer.playingMs";
+
+        /**
+         * Key to extract the count of errors encountered while
+         * playing the media
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String KEY_ERRORS = "android.media.mediaplayer.err";
+
+        /**
+         * Key to extract an (optional) error code detected while
+         * playing the media
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String KEY_ERROR_CODE = "android.media.mediaplayer.errcode";
+
+    }
+
+    /**
+     * This class holds the constants defining keys related to
+     * the metrics for a MediaRecorder.
+     */
+    public final static class MediaRecorder
+    {
+        private MediaRecorder() {}
+
+        /**
+         * Key to extract the audio bitrate
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
+
+        /**
+         * Key to extract the number of audio channels
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
+
+        /**
+         * Key to extract the audio samplerate
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
+
+        /**
+         * Key to extract the audio timescale
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
+
+        /**
+         * Key to extract the video capture frame rate
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is a double.
+         */
+        public static final String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
+
+        /**
+         * Key to extract the video capture framerate enable value
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
+
+        /**
+         * Key to extract the intended playback frame rate
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate";
+
+        /**
+         * Key to extract the height (in pixels) of the captured video
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String KEY_HEIGHT = "android.media.mediarecorder.height";
+
+        /**
+         * Key to extract the recorded movies time units
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         * A value of 1000 indicates that the movie's timing is in milliseconds.
+         */
+        public static final String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
+
+        /**
+         * Key to extract the rotation (in degrees) to properly orient the video
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String KEY_ROTATION = "android.media.mediarecorder.rotation";
+
+        /**
+         * Key to extract the video bitrate from being used
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
+
+        /**
+         * Key to extract the value for how often video iframes are generated
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
+
+        /**
+         * Key to extract the video encoding level
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
+
+        /**
+         * Key to extract the video encoding profile
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
+
+        /**
+         * Key to extract the recorded video time units
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         * A value of 1000 indicates that the video's timing is in milliseconds.
+         */
+        public static final String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
+
+        /**
+         * Key to extract the width (in pixels) of the captured video
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String KEY_WIDTH = "android.media.mediarecorder.width";
+
+    }
+
+    /*
+     * Methods that we want
+     */
+
+    private Bundle mBundle;
+
+    MediaMetricsSet(Bundle bundle) {
+        mBundle = bundle;
+    }
+
+    /**
+     * Returns the number of mappings contained in this Bundle.
+     *
+     * @return the number of mappings as an int.
+     */
+    public int size() {
+        return mBundle.size();
+    }
+
+    /**
+     * Returns true if the mapping of this MediaMetricsSet is empty,
+     * false otherwise.
+     */
+    public boolean isEmpty() {
+        return mBundle.isEmpty();
+    }
+
+    /**
+     * Returns the value associated with the given key, or defaultValue if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @param defaultValue Value to return if key does not exist
+     * @return a double value
+     */
+    public double getDouble(String key, double defaultValue) {
+        return mBundle.getDouble(key, defaultValue);
+    }
+
+    /**
+     * Returns the value associated with the given key, or defaultValue if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @param defaultValue Value to return if key does not exist
+     * @return an int value
+     */
+    public int getInt(String key, int defaultValue) {
+        return mBundle.getInt(key, defaultValue);
+    }
+
+    /**
+     * Returns the value associated with the given key, or defaultValue if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @param defaultValue Value to return if key does not exist
+     * @return a long value
+     */
+    public long getLong(String key, long defaultValue) {
+        return mBundle.getLong(key, defaultValue);
+    }
+
+    /**
+     * Returns the value associated with the given key, or defaultValue if
+     * no mapping of the desired type exists for the given key or if a null
+     * value is explicitly associated with the given key.
+     *
+     * @param key a String
+     * @param defaultValue Value to return if key does not exist or if a null
+     *     value is associated with the given key.
+     * @return the String value associated with the given key, or defaultValue
+     *     if no valid String object is currently mapped to that key.
+     */
+    public String getString(String key, String defaultValue) {
+        return mBundle.getString(key, defaultValue);
+    }
+
+    /**
+     * Returns a Set containing the Strings used as keys in this Bundle.
+     *
+     * @return a Set of String keys
+     */
+    public Set<String> keySet() {
+        return mBundle.keySet();
+    }
+
+
+
+    public String toString() {
+        return mBundle.toString();
+    }
+
+}
+
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index b85c911..1ee05b8 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -49,6 +49,7 @@
 import android.media.BufferingParams;
 import android.media.MediaDrm;
 import android.media.MediaFormat;
+import android.media.MediaMetricsSet;
 import android.media.MediaTimeProvider;
 import android.media.PlaybackParams;
 import android.media.SubtitleController;
@@ -1494,70 +1495,22 @@
     public native int getVideoHeight();
 
     /**
-     *  Returns Analytics/Metrics data about the current video in this player.
+     * Return Metrics data about the current player.
      *
-     * @return the a map of attributes and values available for this video
-     * player or null if no metrics are available.
+     * @return a MediaMetricsSet containing the set of attributes and values
+     * available for the media being handled by this instance of MediaPlayer
+     * The attributes are descibed in {@link MediaMetricsSet.MediaPlayer}.
      *
-     *  <table style="width: 0%">
-     *   <thead>
-     *    <tr>
-     *     <th>Key</th>
-     *     <th>Type</th>
-     *     <th>Description</th>
-     *    </tr>
-     *   </thead>
-     *   <tbody>
-     *    <tr>
-     *     <td>{@code "video/codec"}</td>
-     *     <td>String</td>
-     *     <td>Identifies the video codec in use</td>
-     *    </tr><tr>
-     *     <td>{@code "video/mime"}</td>
-     *     <td>String</td>
-     *     <td>Mime type of the video being encoded/decoded</td>
-     *    </tr><tr>
-     *     <td>{@code "audio/codec"}</td>
-     *     <td>String</td>
-     *     <td>Identifies the audio codec in use</td>
-     *    </tr><tr>
-     *     <td>{@code "audio/mime"}</td>
-     *     <td>String</td>
-     *     <td>Mime type of the audio being encoded/decoded</td>
-     *    </tr><tr>
-     *     <td>{@code "ht"}</td>
-     *     <td>Integer</td>
-     *     <td>Height (pixels); valid only when mode=video</td>
-     *    </tr><tr>
-     *     <td>{@code "wid"}</td>
-     *     <td>Integer</td>
-     *     <td>Width (pixels); valid only when mode=video</td>
-     *    </tr><tr>
-     *     <td>{@code "frame"}</td>
-     *     <td>Integer</td>
-     *     <td>Number of decoded video frames sent to the display</td>
-     *    </tr><tr>
-     *     <td>{@code "dropped"}</td>
-     *     <td>Integer</td>
-     *     <td>Number of decoded video frames that were not sent to display.
-     *         These frames were dropped by the player.</td>
-     *    </tr><tr>
-     *     <td>{@code "durationMs"}</td>
-     *     <td>Integer</td>
-     *     <td>The length of the media being played (in ms), e.g. "This video lasts for 30000 milliseconds". </td>
-     *    </tr><tr>
-     *     <td>{@code "playingMs"}</td>
-     *     <td>Integer</td>
-     *     <td>The time the media has been played (in ms). If you watch a
-     *         30 second twice through, this will report 60000 ms.</td>
-     *    </tr>
-     *   </tbody>
-     *  </table>
-     *
-     *  Additional fields specific to individual codecs will also appear in
+     *  Additional vendor-specific fields may also be present in
      *  the return value.
      */
-    public native Bundle getMetrics();
+    public MediaMetricsSet getMetrics() {
+        Bundle bundle = native_getMetrics();
+	MediaMetricsSet mSet = new MediaMetricsSet(bundle);
+	return mSet;
+    }
+
+    private native Bundle native_getMetrics();
 
     /**
      * Checks whether the MediaPlayer is playing.
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 075a84f..cdc1d60 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -20,6 +20,7 @@
 import android.annotation.SystemApi;
 import android.app.ActivityThread;
 import android.hardware.Camera;
+import android.media.MediaMetricsSet;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -1259,91 +1260,23 @@
     private native void setParameter(String nameValuePair);
 
     /**
-     * Returns Metrics data about the current media container.
+     *  Return Metrics data about the current Mediarecorder instance.
      *
-     * @return the set of keys and values available for the media being
-     * handled by this instance of MediaExtractor. The keys, data types,
-     * and meaning are described in the following table.
+     * @return a MediaMetricsSet containing the set of attributes and values
+     * available for the media being generated by this instance of
+     * MediaRecorder.
+     * The attributes are descibed in {@link MediaMetricsSet.MediaRecorder}.
      *
-     *  <table style="width: 0%">
-     *   <thead>
-     *    <tr>
-     *     <th>Key</th>
-     *     <th>Type</th>
-     *     <th>Description</th>
-     *    </tr>
-     *   </thead>
-     *   <tbody>
-     *    <tr>
-     *     <td>{@code "ht"}</td>
-     *     <td>Integer</td>
-     *     <td>Height of the recorded video (pixels)</td>
-     *    </tr><tr>
-     *     <td>{@code "wid"}</td>
-     *     <td>Integer</td>
-     *     <td>Width of the recorded video (pixels)</td>
-     *    </tr><tr>
-     *     <td>{@code "frame-rate"}</td>
-     *     <td>Integer</td>
-     *     <td>Framerate of captured Video (frames per second)</td>
-     *    </tr><tr>
-     *     <td>{@code "video-bitrate"}</td>
-     *     <td>Integer</td>
-     *     <td>Bit rate of encoded video (bits per second)</td>
-     *    </tr><tr>
-     *     <td>{@code "video-iframe-interval"}</td>
-     *     <td>Integer</td>
-     *     <td>Interval between encoded IFrames (seconds)</td>
-     *    </tr><tr>
-     *     <td>{@code "video-timescale"}</td>
-     *     <td>Integer</td>
-     *     <td></td>
-     *    </tr><tr>
-     *     <td>{@code "video-encoder-profile"}</td>
-     *     <td>Integer</td>
-     *     <td>Video Encoder Profile, as defined in OpenMAX IL</td>
-     *    </tr><tr>
-     *     <td>{@code "video-encoder-level"}</td>
-     *     <td>Integer</td>
-     *     <td>Video Encoder Level, as defined in OpenMAX IL</td>
-     *    </tr><tr>
-     *     <td>{@code "audio-bitrate"}</td>
-     *     <td>Integer</td>
-     *     <td>Bitrate of encoded audio (bits per second)</td>
-     *    </tr><tr>
-     *     <td>{@code "audio-samplerate"}</td>
-     *     <td>Integer</td>
-     *     <td></td>
-     *    </tr><tr>
-     *     <td>{@code "audio-channels"}</td>
-     *     <td>Integer</td>
-     *     <td>Number of Audio Channels Captured</td>
-     *    </tr><tr>
-     *     <td>{@code "audio-timescale"}</td>
-     *     <td>Integer</td>
-     *     <td></td>
-     *    </tr><tr>
-     *     <td>{@code "movie-timescale"}</td>
-     *     <td>Integer</td>
-     *     <td></td>
-     *    </tr><tr>
-     *     <td>{@code "movie-timescale"}</td>
-     *     <td>Integer</td>
-     *     <td></td>
-     *    </tr><tr>
-     *     <td>{@code "capture-fps"}</td>
-     *     <td>Integer</td>
-     *     <td></td>
-     *    </tr><tr>
-     *     <td>{@code "rotation"}</td>
-     *     <td>Integer</td>
-     *     <td>Orientation of the Video (degrees)</td>
-     *    </tr>
-     *   </tbody>
-     *  </table>
+     *  Additional vendor-specific fields may also be present in
+     *  the return value.
      */
+    public MediaMetricsSet getMetrics() {
+        Bundle bundle = native_getMetrics();
+	MediaMetricsSet mSet = new MediaMetricsSet(bundle);
+	return mSet;
+    }
 
-    public native Bundle getMetrics();
+    private native Bundle native_getMetrics();
 
     @Override
     protected void finalize() { native_finalize(); }
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 293e5dd..a8dd313 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -624,7 +624,7 @@
     return OK;
 }
 
-status_t JMediaCodec::getMetrics(JNIEnv *, Parcel *reply) const {
+status_t JMediaCodec::getMetrics(JNIEnv *, MediaAnalyticsItem * &reply) const {
 
     status_t status = mCodec->getMetrics(reply);
     return status;
@@ -1666,9 +1666,9 @@
 }
 
 static jobject
-android_media_MediaCodec_getMetrics(JNIEnv *env, jobject thiz)
+android_media_MediaCodec_native_getMetrics(JNIEnv *env, jobject thiz)
 {
-    ALOGV("android_media_MediaCodec_getMetrics");
+    ALOGV("android_media_MediaCodec_native_getMetrics");
 
     sp<JMediaCodec> codec = getMediaCodec(env, thiz);
     if (codec == NULL ) {
@@ -1677,16 +1677,14 @@
     }
 
     // get what we have for the metrics from the codec
-    Parcel reply;
-    status_t err = codec->getMetrics(env, &reply);
+    MediaAnalyticsItem *item = NULL;
+
+    status_t err = codec->getMetrics(env, item);
     if (err != OK) {
         ALOGE("getMetrics failed");
         return (jobject) NULL;
     }
 
-    // build and return the Bundle
-    MediaAnalyticsItem *item = new MediaAnalyticsItem;
-    item->readFromParcel(reply);
     jobject mybundle = MediaMetricsJNI::writeMetricsToBundle(env, item, NULL);
 
     // housekeeping
@@ -2004,8 +2002,8 @@
     { "getName", "()Ljava/lang/String;",
       (void *)android_media_MediaCodec_getName },
 
-    { "getMetrics", "()Landroid/os/Bundle;",
-      (void *)android_media_MediaCodec_getMetrics},
+    { "native_getMetrics", "()Landroid/os/Bundle;",
+      (void *)android_media_MediaCodec_native_getMetrics},
 
     { "setParameters", "([Ljava/lang/String;[Ljava/lang/Object;)V",
       (void *)android_media_MediaCodec_setParameters },
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index a8c76c5..c9a1700 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -19,6 +19,7 @@
 
 #include "jni.h"
 
+#include <media/MediaAnalyticsItem.h>
 #include <media/hardware/CryptoAPI.h>
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/foundation/AHandler.h>
@@ -116,7 +117,7 @@
 
     status_t getName(JNIEnv *env, jstring *name) const;
 
-    status_t getMetrics(JNIEnv *env, Parcel *reply) const;
+    status_t getMetrics(JNIEnv *env, MediaAnalyticsItem * &reply) const;
 
     status_t setParameters(const sp<AMessage> &params);
 
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 3c33493..c2cfed9 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -811,9 +811,9 @@
 }
 
 static jobject
-android_media_MediaExtractor_getMetrics(JNIEnv * env, jobject thiz)
+android_media_MediaExtractor_native_getMetrics(JNIEnv * env, jobject thiz)
 {
-    ALOGV("android_media_MediaExtractor_getMetrics");
+    ALOGV("android_media_MediaExtractor_native_getMetrics");
 
     sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
     if (extractor == NULL ) {
@@ -905,8 +905,8 @@
     { "hasCacheReachedEndOfStream", "()Z",
       (void *)android_media_MediaExtractor_hasCacheReachedEOS },
 
-    {"getMetrics",          "()Landroid/os/Bundle;",
-      (void *)android_media_MediaExtractor_getMetrics},
+    {"native_getMetrics",          "()Landroid/os/Bundle;",
+      (void *)android_media_MediaExtractor_native_getMetrics},
 };
 
 int register_android_media_MediaExtractor(JNIEnv *env) {
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 27724a1..1b52cf5 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -708,7 +708,7 @@
 }
 
 static jobject
-android_media_MediaPlayer_getMetrics(JNIEnv *env, jobject thiz)
+android_media_MediaPlayer_native_getMetrics(JNIEnv *env, jobject thiz)
 {
     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
@@ -1393,7 +1393,7 @@
     {"_stop",               "()V",                              (void *)android_media_MediaPlayer_stop},
     {"getVideoWidth",       "()I",                              (void *)android_media_MediaPlayer_getVideoWidth},
     {"getVideoHeight",      "()I",                              (void *)android_media_MediaPlayer_getVideoHeight},
-    {"getMetrics",          "()Landroid/os/Bundle;",            (void *)android_media_MediaPlayer_getMetrics},
+    {"native_getMetrics",          "()Landroid/os/Bundle;",            (void *)android_media_MediaPlayer_native_getMetrics},
     {"setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer_setPlaybackParams},
     {"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer_getPlaybackParams},
     {"setSyncParams",     "(Landroid/media/SyncParams;)V",  (void *)android_media_MediaPlayer_setSyncParams},
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 77544eb..7a63e00 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -628,9 +628,9 @@
 }
 
 static jobject
-android_media_MediaRecorder_getMetrics(JNIEnv *env, jobject thiz)
+android_media_MediaRecorder_native_getMetrics(JNIEnv *env, jobject thiz)
 {
-    ALOGV("android_media_MediaRecorder_getMetrics");
+    ALOGV("android_media_MediaRecorder_native_getMetrics");
 
     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
     if (mr == NULL) {
@@ -688,7 +688,7 @@
     {"native_finalize",      "()V",                             (void *)android_media_MediaRecorder_native_finalize},
     {"native_setInputSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaRecorder_setInputSurface },
 
-    {"getMetrics",          "()Landroid/os/Bundle;",            (void *)android_media_MediaRecorder_getMetrics},
+    {"native_getMetrics",          "()Landroid/os/Bundle;",            (void *)android_media_MediaRecorder_native_getMetrics},
 };
 
 // This function only registers the native methods, and is called from