MediaPlayer2: change getVideoWidth and getVideoHeight to getVideoSize

Test: cts
Bug: 112549021
Change-Id: I9b68b7ada3f60db7eccc0eb919515ba6308dddea
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index 7470192..0b3c973 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -325,18 +325,6 @@
     public abstract Object skipToNext();
 
     /**
-     * Moves the media to specified time position.
-     * Same as {@link #seekTo(long, int)} with {@code mode = SEEK_PREVIOUS_SYNC}.
-     *
-     * @param msec the offset in milliseconds from the start to seek to
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
-     */
-    // This is an asynchronous call.
-    public Object seekTo(long msec) {
-        return seekTo(msec, SEEK_PREVIOUS_SYNC /* mode */);
-    }
-
-    /**
      * Gets the current playback position.
      *
      * @return the current position in milliseconds
@@ -661,28 +649,16 @@
             AudioRouting.OnRoutingChangedListener listener);
 
     /**
-     * Returns the width of the video.
+     * Returns the size of the video.
      *
-     * @return the width of the video, or 0 if there is no video,
-     * no display surface was set, or the width has not been determined
-     * yet. The {@code EventCallback} can be registered via
+     * @return the size of the video. The width and height of size could be 0 if there is no video,
+     * no display surface was set, or the size has not been determined yet.
+     * The {@code EventCallback} can be registered via
      * {@link #setEventCallback(Executor, EventCallback)} to provide a
-     * notification {@code EventCallback.onVideoSizeChanged} when the width
+     * notification {@code EventCallback.onVideoSizeChanged} when the size
      * is available.
      */
-    public abstract int getVideoWidth();
-
-    /**
-     * Returns the height of the video.
-     *
-     * @return the height of the video, or 0 if there is no video,
-     * no display surface was set, or the height has not been determined
-     * yet. The {@code EventCallback} can be registered via
-     * {@link #setEventCallback(Executor, EventCallback)} to provide a
-     * notification {@code EventCallback.onVideoSizeChanged} when the height is
-     * available.
-     */
-    public abstract int getVideoHeight();
+    public abstract VideoSize getVideoSize();
 
     /**
      * Return Metrics data about the current player.
@@ -842,6 +818,18 @@
     public abstract SyncParams getSyncParams();
 
     /**
+     * Moves the media to specified time position.
+     * Same as {@link #seekTo(long, int)} with {@code mode = SEEK_PREVIOUS_SYNC}.
+     *
+     * @param msec the offset in milliseconds from the start to seek to
+     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     */
+    // This is an asynchronous call.
+    public Object seekTo(long msec) {
+        return seekTo(msec, SEEK_PREVIOUS_SYNC /* mode */);
+    }
+
+    /**
      * Seek modes used in method seekTo(long, int) to move media position
      * to a specified location.
      *
@@ -1171,11 +1159,10 @@
          *
          * @param mp the MediaPlayer2 associated with this callback
          * @param dsd the DataSourceDesc of this data source
-         * @param width the width of the video
-         * @param height the height of the video
+         * @param size the size of the video
          */
         public void onVideoSizeChanged(
-                MediaPlayer2 mp, DataSourceDesc dsd, int width, int height) { }
+                MediaPlayer2 mp, DataSourceDesc dsd, VideoSize size) { }
 
         /**
          * Called to indicate an avaliable timed text
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 6697a4f..2b5dea1 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -107,6 +107,7 @@
     private AtomicInteger mBufferedPercentageCurrent = new AtomicInteger(0);
     private AtomicInteger mBufferedPercentageNext = new AtomicInteger(0);
     private volatile float mVolume = 1.0f;
+    private VideoSize mVideoSize = new VideoSize(0, 0);
 
     // Modular DRM
     private final Object mDrmLock = new Object();
@@ -949,10 +950,9 @@
     }
 
     @Override
-    public native int getVideoWidth();
-
-    @Override
-    public native int getVideoHeight();
+    public VideoSize getVideoSize() {
+        return mVideoSize;
+    }
 
     @Override
     public PersistableBundle getMetrics() {
@@ -1653,80 +1653,175 @@
             }
 
             switch(msg.what) {
-            case MEDIA_PREPARED:
-            {
-                if (dsd != null) {
+                case MEDIA_PREPARED:
+                {
+                    if (dsd != null) {
+                        sendEvent(new EventNotifier() {
+                            @Override
+                            public void notify(EventCallback callback) {
+                                callback.onInfo(
+                                        mMediaPlayer, dsd, MEDIA_INFO_PREPARED, 0);
+                            }
+                        });
+                    }
+
+                    synchronized (mSrcLock) {
+                        Log.i(TAG, "MEDIA_PREPARED: srcId=" + srcId
+                                + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId);
+
+                        if (isCurrentSrcId) {
+                            prepareNextDataSource();
+                        } else if (isNextSrcId) {
+                            mNextSourceState = NEXT_SOURCE_STATE_PREPARED;
+                            if (mNextSourcePlayPending) {
+                                playNextDataSource();
+                            }
+                        }
+                    }
+
+                    synchronized (mTaskLock) {
+                        if (mCurrentTask != null
+                                && mCurrentTask.mMediaCallType == CALL_COMPLETED_PREPARE
+                                && mCurrentTask.mDSD == dsd
+                                && mCurrentTask.mNeedToWaitForEventToComplete) {
+                            mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR);
+                            mCurrentTask = null;
+                            processPendingTask_l();
+                        }
+                    }
+                    return;
+                }
+
+                case MEDIA_DRM_INFO:
+                {
+                    if (msg.obj == null) {
+                        Log.w(TAG, "MEDIA_DRM_INFO msg.obj=NULL");
+                    } else if (msg.obj instanceof byte[]) {
+                        // The PlayerMessage was parsed already in postEventFromNative
+                        final DrmInfoImpl drmInfo;
+
+                        synchronized (mDrmLock) {
+                            if (mDrmInfoImpl != null) {
+                                drmInfo = mDrmInfoImpl.makeCopy();
+                            } else {
+                                drmInfo = null;
+                            }
+                        }
+
+                        // notifying the client outside the lock
+                        if (drmInfo != null) {
+                            sendDrmEvent(new DrmEventNotifier() {
+                                @Override
+                                public void notify(DrmEventCallback callback) {
+                                    callback.onDrmInfo(
+                                            mMediaPlayer, dsd, drmInfo);
+                                }
+                            });
+                        }
+                    } else {
+                        Log.w(TAG, "MEDIA_DRM_INFO msg.obj of unexpected type " + msg.obj);
+                    }
+                    return;
+                }
+
+                case MEDIA_PLAYBACK_COMPLETE:
+                {
+                    if (isCurrentSrcId) {
+                        sendEvent(new EventNotifier() {
+                            @Override
+                            public void notify(EventCallback callback) {
+                                callback.onInfo(
+                                        mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0);
+                            }
+                        });
+                        stayAwake(false);
+
+                        synchronized (mSrcLock) {
+                            mNextSourcePlayPending = true;
+
+                            Log.i(TAG, "MEDIA_PLAYBACK_COMPLETE: srcId=" + srcId
+                                    + ", currentSrcId=" + mCurrentSrcId
+                                    + ", nextSrcId=" + mNextSrcId);
+                        }
+
+                        playNextDataSource();
+                    }
+
+                    return;
+                }
+
+                case MEDIA_STOPPED:
+                case MEDIA_STARTED:
+                case MEDIA_PAUSED:
+                case MEDIA_SKIPPED:
+                case MEDIA_NOTIFY_TIME:
+                {
+                    // Do nothing. The client should have enough information with
+                    // {@link EventCallback#onMediaTimeDiscontinuity}.
+                    break;
+                }
+
+                case MEDIA_BUFFERING_UPDATE:
+                {
+                    final int percent = msg.arg1;
                     sendEvent(new EventNotifier() {
                         @Override
                         public void notify(EventCallback callback) {
                             callback.onInfo(
-                                    mMediaPlayer, dsd, MEDIA_INFO_PREPARED, 0);
+                                    mMediaPlayer, dsd, MEDIA_INFO_BUFFERING_UPDATE, percent);
                         }
                     });
-                }
 
-                synchronized (mSrcLock) {
-                    Log.i(TAG, "MEDIA_PREPARED: srcId=" + srcId
-                            + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId);
-
-                    if (isCurrentSrcId) {
-                        prepareNextDataSource();
-                    } else if (isNextSrcId) {
-                        mNextSourceState = NEXT_SOURCE_STATE_PREPARED;
-                        if (mNextSourcePlayPending) {
-                            playNextDataSource();
+                    synchronized (mSrcLock) {
+                        if (isCurrentSrcId) {
+                            mBufferedPercentageCurrent.set(percent);
+                        } else if (isNextSrcId) {
+                            mBufferedPercentageNext.set(percent);
                         }
                     }
+                    return;
                 }
 
-                synchronized (mTaskLock) {
-                    if (mCurrentTask != null
-                            && mCurrentTask.mMediaCallType == CALL_COMPLETED_PREPARE
-                            && mCurrentTask.mDSD == dsd
-                            && mCurrentTask.mNeedToWaitForEventToComplete) {
-                        mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR);
-                        mCurrentTask = null;
-                        processPendingTask_l();
-                    }
-                }
-                return;
-            }
-
-            case MEDIA_DRM_INFO:
-            {
-                if (msg.obj == null) {
-                    Log.w(TAG, "MEDIA_DRM_INFO msg.obj=NULL");
-                } else if (msg.obj instanceof byte[]) {
-                    // The PlayerMessage was parsed already in postEventFromNative
-                    final DrmInfoImpl drmInfo;
-
-                    synchronized (mDrmLock) {
-                        if (mDrmInfoImpl != null) {
-                            drmInfo = mDrmInfoImpl.makeCopy();
-                        } else {
-                            drmInfo = null;
+                case MEDIA_SEEK_COMPLETE:
+                {
+                    synchronized (mTaskLock) {
+                        if (mCurrentTask != null
+                                && mCurrentTask.mMediaCallType == CALL_COMPLETED_SEEK_TO
+                                && mCurrentTask.mNeedToWaitForEventToComplete) {
+                            mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR);
+                            mCurrentTask = null;
+                            processPendingTask_l();
                         }
                     }
-
-                    // notifying the client outside the lock
-                    if (drmInfo != null) {
-                        sendDrmEvent(new DrmEventNotifier() {
-                            @Override
-                            public void notify(DrmEventCallback callback) {
-                                callback.onDrmInfo(
-                                        mMediaPlayer, dsd, drmInfo);
-                            }
-                        });
-                    }
-                } else {
-                    Log.w(TAG, "MEDIA_DRM_INFO msg.obj of unexpected type " + msg.obj);
+                    return;
                 }
-                return;
-            }
 
-            case MEDIA_PLAYBACK_COMPLETE:
-            {
-                if (isCurrentSrcId) {
+                case MEDIA_SET_VIDEO_SIZE:
+                {
+                    final int width = msg.arg1;
+                    final int height = msg.arg2;
+
+                    mVideoSize = new VideoSize(width, height);
+                    sendEvent(new EventNotifier() {
+                        @Override
+                        public void notify(EventCallback callback) {
+                            callback.onVideoSizeChanged(
+                                    mMediaPlayer, dsd, mVideoSize);
+                        }
+                    });
+                    return;
+                }
+
+                case MEDIA_ERROR:
+                {
+                    Log.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")");
+                    sendEvent(new EventNotifier() {
+                        @Override
+                        public void notify(EventCallback callback) {
+                            callback.onError(
+                                    mMediaPlayer, dsd, what, extra);
+                        }
+                    });
                     sendEvent(new EventNotifier() {
                         @Override
                         public void notify(EventCallback callback) {
@@ -1735,231 +1830,139 @@
                         }
                     });
                     stayAwake(false);
-
-                    synchronized (mSrcLock) {
-                        mNextSourcePlayPending = true;
-
-                        Log.i(TAG, "MEDIA_PLAYBACK_COMPLETE: srcId=" + srcId
-                                + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId);
-                    }
-
-                    playNextDataSource();
+                    return;
                 }
 
-                return;
-            }
-
-            case MEDIA_STOPPED:
-            case MEDIA_STARTED:
-            case MEDIA_PAUSED:
-            case MEDIA_SKIPPED:
-            case MEDIA_NOTIFY_TIME:
-            {
-                // Do nothing. The client should have enough information with
-                // {@link EventCallback#onMediaTimeDiscontinuity}.
-                break;
-            }
-
-            case MEDIA_BUFFERING_UPDATE:
-            {
-                final int percent = msg.arg1;
-                sendEvent(new EventNotifier() {
-                    @Override
-                    public void notify(EventCallback callback) {
-                        callback.onInfo(
-                                mMediaPlayer, dsd, MEDIA_INFO_BUFFERING_UPDATE, percent);
+                case MEDIA_INFO:
+                {
+                    switch (msg.arg1) {
+                        case MEDIA_INFO_VIDEO_TRACK_LAGGING:
+                            Log.i(TAG, "Info (" + msg.arg1 + "," + msg.arg2 + ")");
+                            break;
                     }
-                });
 
-                synchronized (mSrcLock) {
-                    if (isCurrentSrcId) {
-                        mBufferedPercentageCurrent.set(percent);
-                    } else if (isNextSrcId) {
-                        mBufferedPercentageNext.set(percent);
-                    }
-                }
-                return;
-            }
-
-            case MEDIA_SEEK_COMPLETE:
-            {
-                synchronized (mTaskLock) {
-                    if (mCurrentTask != null
-                            && mCurrentTask.mMediaCallType == CALL_COMPLETED_SEEK_TO
-                            && mCurrentTask.mNeedToWaitForEventToComplete) {
-                        mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR);
-                        mCurrentTask = null;
-                        processPendingTask_l();
-                    }
-                }
-                return;
-            }
-
-            case MEDIA_SET_VIDEO_SIZE:
-            {
-                final int width = msg.arg1;
-                final int height = msg.arg2;
-                sendEvent(new EventNotifier() {
-                    @Override
-                    public void notify(EventCallback callback) {
-                        callback.onVideoSizeChanged(
-                                mMediaPlayer, dsd, width, height);
-                    }
-                });
-                return;
-            }
-
-            case MEDIA_ERROR:
-            {
-                Log.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")");
-                sendEvent(new EventNotifier() {
-                    @Override
-                    public void notify(EventCallback callback) {
-                        callback.onError(
-                                mMediaPlayer, dsd, what, extra);
-                    }
-                });
-                sendEvent(new EventNotifier() {
-                    @Override
-                    public void notify(EventCallback callback) {
-                        callback.onInfo(
-                                mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0);
-                    }
-                });
-                stayAwake(false);
-                return;
-            }
-
-            case MEDIA_INFO:
-            {
-                switch (msg.arg1) {
-                    case MEDIA_INFO_VIDEO_TRACK_LAGGING:
-                        Log.i(TAG, "Info (" + msg.arg1 + "," + msg.arg2 + ")");
-                        break;
-                }
-
-                sendEvent(new EventNotifier() {
-                    @Override
-                    public void notify(EventCallback callback) {
-                        callback.onInfo(
-                                mMediaPlayer, dsd, what, extra);
-                    }
-                });
-
-                if (msg.arg1 == MEDIA_INFO_DATA_SOURCE_START) {
-                    if (isCurrentSrcId) {
-                        prepareNextDataSource();
-                    }
-                }
-
-                // No real default action so far.
-                return;
-            }
-
-            case MEDIA_TIMED_TEXT:
-            {
-                final TimedText text;
-                if (msg.obj instanceof byte[]) {
-                    PlayerMessage playerMsg;
-                    try {
-                        playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
-                    } catch (InvalidProtocolBufferException e) {
-                        Log.w(TAG, "Failed to parse timed text.", e);
-                        return;
-                    }
-                    text = TimedTextUtil.parsePlayerMessage(playerMsg);
-                } else {
-                    text = null;
-                }
-
-                sendEvent(new EventNotifier() {
-                    @Override
-                    public void notify(EventCallback callback) {
-                        callback.onTimedText(
-                                mMediaPlayer, dsd, text);
-                    }
-                });
-                return;
-            }
-
-            case MEDIA_SUBTITLE_DATA:
-            {
-                if (msg.obj instanceof byte[]) {
-                    PlayerMessage playerMsg;
-                    try {
-                        playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
-                    } catch (InvalidProtocolBufferException e) {
-                        Log.w(TAG, "Failed to parse subtitle data.", e);
-                        return;
-                    }
-                    Iterator<Value> in = playerMsg.getValuesList().iterator();
-                    SubtitleData data = new SubtitleData(
-                            in.next().getInt32Value(),  // trackIndex
-                            in.next().getInt64Value(),  // startTimeUs
-                            in.next().getInt64Value(),  // durationUs
-                            in.next().getBytesValue().toByteArray());  // data
                     sendEvent(new EventNotifier() {
                         @Override
                         public void notify(EventCallback callback) {
-                            callback.onSubtitleData(
+                            callback.onInfo(
+                                    mMediaPlayer, dsd, what, extra);
+                        }
+                    });
+
+                    if (msg.arg1 == MEDIA_INFO_DATA_SOURCE_START) {
+                        if (isCurrentSrcId) {
+                            prepareNextDataSource();
+                        }
+                    }
+
+                    // No real default action so far.
+                    return;
+                }
+
+                case MEDIA_TIMED_TEXT:
+                {
+                    final TimedText text;
+                    if (msg.obj instanceof byte[]) {
+                        PlayerMessage playerMsg;
+                        try {
+                            playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
+                        } catch (InvalidProtocolBufferException e) {
+                            Log.w(TAG, "Failed to parse timed text.", e);
+                            return;
+                        }
+                        text = TimedTextUtil.parsePlayerMessage(playerMsg);
+                    } else {
+                        text = null;
+                    }
+
+                    sendEvent(new EventNotifier() {
+                        @Override
+                        public void notify(EventCallback callback) {
+                            callback.onTimedText(
+                                    mMediaPlayer, dsd, text);
+                        }
+                    });
+                    return;
+                }
+
+                case MEDIA_SUBTITLE_DATA:
+                {
+                    if (msg.obj instanceof byte[]) {
+                        PlayerMessage playerMsg;
+                        try {
+                            playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
+                        } catch (InvalidProtocolBufferException e) {
+                            Log.w(TAG, "Failed to parse subtitle data.", e);
+                            return;
+                        }
+                        Iterator<Value> in = playerMsg.getValuesList().iterator();
+                        SubtitleData data = new SubtitleData(
+                                in.next().getInt32Value(),  // trackIndex
+                                in.next().getInt64Value(),  // startTimeUs
+                                in.next().getInt64Value(),  // durationUs
+                                in.next().getBytesValue().toByteArray());  // data
+                        sendEvent(new EventNotifier() {
+                            @Override
+                            public void notify(EventCallback callback) {
+                                callback.onSubtitleData(
+                                        mMediaPlayer, dsd, data);
+                            }
+                        });
+                    }
+                    return;
+                }
+
+                case MEDIA_META_DATA:
+                {
+                    final TimedMetaData data;
+                    if (msg.obj instanceof byte[]) {
+                        PlayerMessage playerMsg;
+                        try {
+                            playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
+                        } catch (InvalidProtocolBufferException e) {
+                            Log.w(TAG, "Failed to parse timed meta data.", e);
+                            return;
+                        }
+                        Iterator<Value> in = playerMsg.getValuesList().iterator();
+                        data = new TimedMetaData(
+                                in.next().getInt64Value(),  // timestampUs
+                                in.next().getBytesValue().toByteArray());  // metaData
+                    } else {
+                        data = null;
+                    }
+
+                    sendEvent(new EventNotifier() {
+                        @Override
+                        public void notify(EventCallback callback) {
+                            callback.onTimedMetaDataAvailable(
                                     mMediaPlayer, dsd, data);
                         }
                     });
-                }
-                return;
-            }
-
-            case MEDIA_META_DATA:
-            {
-                final TimedMetaData data;
-                if (msg.obj instanceof byte[]) {
-                    PlayerMessage playerMsg;
-                    try {
-                        playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
-                    } catch (InvalidProtocolBufferException e) {
-                        Log.w(TAG, "Failed to parse timed meta data.", e);
-                        return;
-                    }
-                    Iterator<Value> in = playerMsg.getValuesList().iterator();
-                    data = new TimedMetaData(
-                            in.next().getInt64Value(),  // timestampUs
-                            in.next().getBytesValue().toByteArray());  // metaData
-                } else {
-                    data = null;
+                    return;
                 }
 
-                sendEvent(new EventNotifier() {
-                    @Override
-                    public void notify(EventCallback callback) {
-                        callback.onTimedMetaDataAvailable(
-                                mMediaPlayer, dsd, data);
-                    }
-                });
-                return;
-            }
-
-            case MEDIA_NOP: // interface test message - ignore
-            {
-                break;
-            }
-
-            case MEDIA_AUDIO_ROUTING_CHANGED:
-            {
-                AudioManager.resetAudioPortGeneration();
-                synchronized (mRoutingChangeListeners) {
-                    for (NativeRoutingEventHandlerDelegate delegate
-                            : mRoutingChangeListeners.values()) {
-                        delegate.notifyClient();
-                    }
+                case MEDIA_NOP: // interface test message - ignore
+                {
+                    break;
                 }
-                return;
-            }
 
-            default:
-            {
-                Log.e(TAG, "Unknown message type " + msg.what);
-                return;
-            }
+                case MEDIA_AUDIO_ROUTING_CHANGED:
+                {
+                    AudioManager.resetAudioPortGeneration();
+                    synchronized (mRoutingChangeListeners) {
+                        for (NativeRoutingEventHandlerDelegate delegate
+                                : mRoutingChangeListeners.values()) {
+                            delegate.notifyClient();
+                        }
+                    }
+                    return;
+                }
+
+                default:
+                {
+                    Log.e(TAG, "Unknown message type " + msg.what);
+                    return;
+                }
             }
         }
     }
diff --git a/media/java/android/media/VideoSize.java b/media/java/android/media/VideoSize.java
new file mode 100644
index 0000000..7e5cb1f
--- /dev/null
+++ b/media/java/android/media/VideoSize.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2018 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;
+
+/**
+ * Immutable class for describing width and height dimensions.
+ *
+ * @hide
+ */
+public final class VideoSize {
+    /**
+     * Create a new immutable VideoSize instance.
+     *
+     * @param width The width of the video size
+     * @param height The height of the video size
+     */
+    public VideoSize(int width, int height) {
+        mWidth = width;
+        mHeight = height;
+    }
+
+    /**
+     * Get the width of the video size
+     * @return width
+     */
+    public int getWidth() {
+        return mWidth;
+    }
+
+    /**
+     * Get the height of the video size
+     * @return height
+     */
+    public int getHeight() {
+        return mHeight;
+    }
+
+    /**
+     * Check if this video size is equal to another video size.
+     * <p>
+     * Two video sizes are equal if and only if both their widths and heights are
+     * equal.
+     * </p>
+     * <p>
+     * A video size object is never equal to any other type of object.
+     * </p>
+     *
+     * @return {@code true} if the objects were equal, {@code false} otherwise
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof VideoSize) {
+            VideoSize other = (VideoSize) obj;
+            return mWidth == other.mWidth && mHeight == other.mHeight;
+        }
+        return false;
+    }
+
+    /**
+     * Return the video size represented as a string with the format {@code "WxH"}
+     *
+     * @return string representation of the video size
+     */
+    @Override
+    public String toString() {
+        return mWidth + "x" + mHeight;
+    }
+
+    private final int mWidth;
+    private final int mHeight;
+}
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index f60e7da..aa9e3d2 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -790,40 +790,6 @@
     return (jint)mp->getState();
 }
 
-static jint
-android_media_MediaPlayer2_getVideoWidth(JNIEnv *env, jobject thiz)
-{
-    sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
-    if (mp == NULL ) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return 0;
-    }
-    int w;
-    if (0 != mp->getVideoWidth(&w)) {
-        ALOGE("getVideoWidth failed");
-        w = 0;
-    }
-    ALOGV("getVideoWidth: %d", w);
-    return (jint) w;
-}
-
-static jint
-android_media_MediaPlayer2_getVideoHeight(JNIEnv *env, jobject thiz)
-{
-    sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
-    if (mp == NULL ) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return 0;
-    }
-    int h;
-    if (0 != mp->getVideoHeight(&h)) {
-        ALOGE("getVideoHeight failed");
-        h = 0;
-    }
-    ALOGV("getVideoHeight: %d", h);
-    return (jint) h;
-}
-
 static jobject
 android_media_MediaPlayer2_native_getMetrics(JNIEnv *env, jobject thiz)
 {
@@ -1459,8 +1425,6 @@
     {"_prepare",            "()V",                              (void *)android_media_MediaPlayer2_prepare},
     {"_start",              "()V",                              (void *)android_media_MediaPlayer2_start},
     {"native_getState",     "()I",                              (void *)android_media_MediaPlayer2_getState},
-    {"getVideoWidth",       "()I",                              (void *)android_media_MediaPlayer2_getVideoWidth},
-    {"getVideoHeight",      "()I",                              (void *)android_media_MediaPlayer2_getVideoHeight},
     {"native_getMetrics",   "()Landroid/os/PersistableBundle;", (void *)android_media_MediaPlayer2_native_getMetrics},
     {"_setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer2_setPlaybackParams},
     {"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer2_getPlaybackParams},