Merge "media: add new MediaCodec Callback onCodecReleased."
diff --git a/api/current.txt b/api/current.txt
index a13ff67..14ae0c0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -14993,6 +14993,7 @@
     field public static final java.lang.String PARAMETER_KEY_REQUEST_SYNC_FRAME = "request-sync";
     field public static final java.lang.String PARAMETER_KEY_SUSPEND = "drop-input-frames";
     field public static final java.lang.String PARAMETER_KEY_VIDEO_BITRATE = "video-bitrate";
+    field public static final int REASON_RECLAIMED = 1; // 0x1
     field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT = 1; // 0x1
     field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2; // 0x2
   }
@@ -15008,6 +15009,7 @@
 
   public static abstract class MediaCodec.Callback {
     ctor public MediaCodec.Callback();
+    method public void onCodecReleased(android.media.MediaCodec, int);
     method public abstract void onError(android.media.MediaCodec, android.media.MediaCodec.CodecException);
     method public abstract void onInputBufferAvailable(android.media.MediaCodec, int);
     method public abstract void onOutputBufferAvailable(android.media.MediaCodec, int, android.media.MediaCodec.BufferInfo);
diff --git a/api/system-current.txt b/api/system-current.txt
index 310de53..c86dfb9 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -16202,6 +16202,7 @@
     field public static final java.lang.String PARAMETER_KEY_REQUEST_SYNC_FRAME = "request-sync";
     field public static final java.lang.String PARAMETER_KEY_SUSPEND = "drop-input-frames";
     field public static final java.lang.String PARAMETER_KEY_VIDEO_BITRATE = "video-bitrate";
+    field public static final int REASON_RECLAIMED = 1; // 0x1
     field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT = 1; // 0x1
     field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2; // 0x2
   }
@@ -16217,6 +16218,7 @@
 
   public static abstract class MediaCodec.Callback {
     ctor public MediaCodec.Callback();
+    method public void onCodecReleased(android.media.MediaCodec, int);
     method public abstract void onError(android.media.MediaCodec, android.media.MediaCodec.CodecException);
     method public abstract void onInputBufferAvailable(android.media.MediaCodec, int);
     method public abstract void onOutputBufferAvailable(android.media.MediaCodec, int, android.media.MediaCodec.BufferInfo);
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index fd7fca6..e028e3f 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -325,6 +325,13 @@
      */
     public static final int BUFFER_FLAG_END_OF_STREAM = 4;
 
+    /**
+     * This indicates that the codec is released because the media resources used by the codec
+     * have been reclaimed, for example by the resource manager.
+     * This is used by the {@link Callback#onCodecReleased} callback.
+     */
+    public static final int REASON_RECLAIMED = 1;
+
     private EventHandler mEventHandler;
     private Callback mCallback;
 
@@ -335,6 +342,7 @@
     private static final int CB_OUTPUT_AVAILABLE = 2;
     private static final int CB_ERROR = 3;
     private static final int CB_OUTPUT_FORMAT_CHANGE = 4;
+    private static final int CB_CODEC_RELEASED = 5;
 
     private class EventHandler extends Handler {
         private MediaCodec mCodec;
@@ -405,6 +413,13 @@
                     break;
                 }
 
+                case CB_CODEC_RELEASED:
+                {
+                    int reason = msg.arg2;
+                    mCallback.onCodecReleased(mCodec, reason);
+                    break;
+                }
+
                 default:
                 {
                     break;
@@ -720,6 +735,7 @@
         }
 
         /* Must be in sync with android_media_MediaCodec.cpp */
+        private final static int ACTION_FATAL = 0;
         private final static int ACTION_TRANSIENT = 1;
         private final static int ACTION_RECOVERABLE = 2;
 
@@ -1654,6 +1670,22 @@
          * @param format The new output format.
          */
         public abstract void onOutputFormatChanged(MediaCodec codec, MediaFormat format);
+
+        /**
+         * Called when the underlying codec component has been released.
+         * <p>
+         * At this point the MediaCodec must be released, as it has moved to terminal
+         * Uninitialized state.
+         *
+         * @param codec The MediaCodec object.
+         * @param reason The reason of the release.
+         */
+        public void onCodecReleased(MediaCodec codec, int reason) {
+            int errorCode = -1;
+            String detailMessage = "resources reclaimed";
+            onError(codec,
+                    new CodecException(errorCode, CodecException.ACTION_FATAL, detailMessage));
+        }
     }
 
     private void postEventFromNative(
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 16758d0..71457b7 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -669,6 +669,14 @@
             break;
         }
 
+        case MediaCodec::CB_CODEC_RELEASED:
+        {
+            if (!msg->findInt32("reason", &arg2)) {
+                arg2 = MediaCodec::REASON_UNKNOWN;
+            }
+            break;
+        }
+
         default:
             TRESPASS();
     }