Add the ability to query the amount of cached data to MediaExtractor.

Change-Id: I47ae60bc6fb8d88979c1f0d650b6ac528e811371
related-to-bug: 6364341
diff --git a/api/current.txt b/api/current.txt
index 0e8a926..0020d88 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11063,11 +11063,13 @@
     ctor public MediaExtractor();
     method public boolean advance();
     method public int countTracks();
+    method public long getCachedDuration();
     method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
     method public int getSampleFlags();
     method public long getSampleTime();
     method public int getSampleTrackIndex();
     method public java.util.Map<java.lang.String, java.lang.Object> getTrackFormat(int);
+    method public boolean hasCacheReachedEndOfStream();
     method public int readSampleData(java.nio.ByteBuffer, int);
     method public final void release();
     method public void seekTo(long);
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 3b17a7d..9fdb81f 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -245,6 +245,20 @@
     */
     public native boolean getSampleCryptoInfo(MediaCodec.CryptoInfo info);
 
+    /** Returns an estimate of how much data is presently cached in memory
+        expressed in microseconds. Returns -1 if that information is unavailable
+        or not applicable (no cache).
+     */
+    public native long getCachedDuration();
+
+    /** Returns true iff we are caching data and the cache has reached the
+     *  end of the data stream (for now, a future seek may of course restart
+     *  the fetching of data).
+     *  This API only returns a meaningful result if {link #getCachedDuration}
+     *  indicates the presence of a cache, i.e. does NOT return -1.
+    */
+    public native boolean hasCacheReachedEndOfStream();
+
     private static native final void native_init();
     private native final void native_setup();
     private native final void native_finalize();
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index bf3d44a..0518331 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -198,6 +198,10 @@
     return mImpl->getSampleMeta(sampleMeta);
 }
 
+bool JMediaExtractor::getCachedDuration(int64_t *durationUs, bool *eos) const {
+    return mImpl->getCachedDuration(durationUs, eos);
+}
+
 }  // namespace android
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -593,6 +597,42 @@
     }
 }
 
+static jlong android_media_MediaExtractor_getCachedDurationUs(
+        JNIEnv *env, jobject thiz) {
+    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
+
+    if (extractor == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return -1ll;
+    }
+
+    int64_t cachedDurationUs;
+    bool eos;
+    if (!extractor->getCachedDuration(&cachedDurationUs, &eos)) {
+        return -1ll;
+    }
+
+    return cachedDurationUs;
+}
+
+static jboolean android_media_MediaExtractor_hasCacheReachedEOS(
+        JNIEnv *env, jobject thiz) {
+    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
+
+    if (extractor == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return true;
+    }
+
+    int64_t cachedDurationUs;
+    bool eos;
+    if (!extractor->getCachedDuration(&cachedDurationUs, &eos)) {
+        return true;
+    }
+
+    return eos;
+}
+
 static void android_media_MediaExtractor_native_finalize(
         JNIEnv *env, jobject thiz) {
     android_media_MediaExtractor_release(env, thiz);
@@ -641,6 +681,12 @@
 
     { "setDataSource", "(Ljava/io/FileDescriptor;JJ)V",
       (void *)android_media_MediaExtractor_setDataSourceFd },
+
+    { "getCachedDuration", "()J",
+      (void *)android_media_MediaExtractor_getCachedDurationUs },
+
+    { "hasCacheReachedEndOfStream", "()Z",
+      (void *)android_media_MediaExtractor_hasCacheReachedEOS },
 };
 
 int register_android_media_MediaExtractor(JNIEnv *env) {
diff --git a/media/jni/android_media_MediaExtractor.h b/media/jni/android_media_MediaExtractor.h
index f7ce2ff..ef0c48b 100644
--- a/media/jni/android_media_MediaExtractor.h
+++ b/media/jni/android_media_MediaExtractor.h
@@ -53,6 +53,8 @@
     status_t getSampleFlags(uint32_t *sampleFlags);
     status_t getSampleMeta(sp<MetaData> *sampleMeta);
 
+    bool getCachedDuration(int64_t *durationUs, bool *eos) const;
+
 protected:
     virtual ~JMediaExtractor();