Merge "FINAL ATTEMPT: HTTP services are now provided from JAVA and made available to media code"

This commit is contained in:
Andreas Huber
2014-02-05 17:13:07 +00:00
committed by Android (Google) Code Review
16 changed files with 705 additions and 21 deletions

View File

@@ -260,6 +260,8 @@ LOCAL_SRC_FILES += \
media/java/android/media/IAudioService.aidl \
media/java/android/media/IAudioFocusDispatcher.aidl \
media/java/android/media/IAudioRoutesObserver.aidl \
media/java/android/media/IMediaHTTPConnection.aidl \
media/java/android/media/IMediaHTTPService.aidl \
media/java/android/media/IMediaRouterClient.aidl \
media/java/android/media/IMediaRouterService.aidl \
media/java/android/media/IMediaScannerListener.aidl \

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) 2013 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.IBinder;
/** MUST STAY IN SYNC WITH NATIVE CODE at libmedia/IMediaHTTPConnection.{cpp,h} */
/** @hide */
interface IMediaHTTPConnection
{
IBinder connect(in String uri, in String headers);
void disconnect();
int readAt(long offset, int size);
long getSize();
String getMIMEType();
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright (C) 2013 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.media.IMediaHTTPConnection;
/** MUST STAY IN SYNC WITH NATIVE CODE at libmedia/IMediaHTTPService.{cpp,h} */
/** @hide */
interface IMediaHTTPService
{
IMediaHTTPConnection makeHTTPConnection();
}

View File

@@ -21,7 +21,9 @@ import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.media.MediaHTTPService;
import android.net.Uri;
import android.os.IBinder;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -137,11 +139,19 @@ final public class MediaExtractor {
++i;
}
}
setDataSource(path, keys, values);
nativeSetDataSource(
MediaHTTPService.createHttpServiceBinderIfNecessary(path),
path,
keys,
values);
}
private native final void setDataSource(
String path, String[] keys, String[] values) throws IOException;
private native final void nativeSetDataSource(
IBinder httpServiceBinder,
String path,
String[] keys,
String[] values) throws IOException;
/**
* Sets the data source (file-path or http URL) to use.
@@ -156,7 +166,11 @@ final public class MediaExtractor {
* and then use the file descriptor form {@link #setDataSource(FileDescriptor)}.
*/
public final void setDataSource(String path) throws IOException {
setDataSource(path, null, null);
nativeSetDataSource(
MediaHTTPService.createHttpServiceBinderIfNecessary(path),
path,
null,
null);
}
/**

View File

@@ -0,0 +1,263 @@
/*
* Copyright (C) 2013 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.net.Uri;
import android.os.IBinder;
import android.os.StrictMode;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.URL;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;
/** @hide */
public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
private static final String TAG = "MediaHTTPConnection";
private static final boolean VERBOSE = false;
private long mCurrentOffset = -1;
private URL mURL = null;
private Map<String, String> mHeaders = null;
private HttpURLConnection mConnection = null;
private long mTotalSize = -1;
private InputStream mInputStream = null;
public MediaHTTPConnection() {
if (CookieHandler.getDefault() == null) {
CookieHandler.setDefault(new CookieManager());
}
native_setup();
}
public IBinder connect(String uri, String headers) {
if (VERBOSE) {
Log.d(TAG, "connect: uri=" + uri + ", headers=" + headers);
}
try {
disconnect();
mURL = new URL(uri);
mHeaders = convertHeaderStringToMap(headers);
} catch (MalformedURLException e) {
return null;
}
return native_getIMemory();
}
private Map<String, String> convertHeaderStringToMap(String headers) {
HashMap<String, String> map = new HashMap<String, String>();
String[] pairs = headers.split("\r\n");
for (String pair : pairs) {
int colonPos = pair.indexOf(":");
if (colonPos >= 0) {
String key = pair.substring(0, colonPos);
String val = pair.substring(colonPos + 1);
map.put(key, val);
}
}
return map;
}
public void disconnect() {
teardownConnection();
mHeaders = null;
mURL = null;
}
private void teardownConnection() {
if (mConnection != null) {
mInputStream = null;
mConnection.disconnect();
mConnection = null;
mCurrentOffset = -1;
}
}
private void seekTo(long offset) throws IOException {
teardownConnection();
try {
mConnection = (HttpURLConnection)mURL.openConnection();
if (mHeaders != null) {
for (Map.Entry<String, String> entry : mHeaders.entrySet()) {
mConnection.setRequestProperty(
entry.getKey(), entry.getValue());
}
}
if (offset > 0) {
mConnection.setRequestProperty(
"Range", "bytes=" + offset + "-");
}
if (mConnection.getResponseCode() == HttpURLConnection.HTTP_PARTIAL) {
// Partial content, we cannot just use getContentLength
// because what we want is not just the length of the range
// returned but the size of the full content if available.
String contentRange =
mConnection.getHeaderField("Content-Range");
mTotalSize = -1;
if (contentRange != null) {
// format is "bytes xxx-yyy/zzz
// where "zzz" is the total number of bytes of the
// content or '*' if unknown.
int lastSlashPos = contentRange.lastIndexOf('/');
if (lastSlashPos >= 0) {
String total =
contentRange.substring(lastSlashPos + 1);
try {
mTotalSize = Long.parseLong(total);
} catch (NumberFormatException e) {
}
}
}
} else if (mConnection.getResponseCode()
!= HttpURLConnection.HTTP_OK) {
throw new IOException();
} else {
mTotalSize = mConnection.getContentLength();
}
if (offset > 0
&& mConnection.getResponseCode()
!= HttpURLConnection.HTTP_PARTIAL) {
// Some servers simply ignore "Range" requests and serve
// data from the start of the content.
throw new IOException();
}
mInputStream =
new BufferedInputStream(mConnection.getInputStream());
mCurrentOffset = offset;
} catch (IOException e) {
mTotalSize = -1;
mInputStream = null;
mConnection = null;
mCurrentOffset = -1;
throw e;
}
}
public int readAt(long offset, int size) {
return native_readAt(offset, size);
}
private int readAt(long offset, byte[] data, int size) {
StrictMode.ThreadPolicy policy =
new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
try {
if (offset != mCurrentOffset) {
seekTo(offset);
}
int n = mInputStream.read(data, 0, size);
if (n == -1) {
// InputStream signals EOS using a -1 result, our semantics
// are to return a 0-length read.
n = 0;
}
mCurrentOffset += n;
if (VERBOSE) {
Log.d(TAG, "readAt " + offset + " / " + size + " => " + n);
}
return n;
} catch (IOException e) {
if (VERBOSE) {
Log.d(TAG, "readAt " + offset + " / " + size + " => -1");
}
return -1;
} catch (Exception e) {
if (VERBOSE) {
Log.d(TAG, "unknown exception " + e);
Log.d(TAG, "readAt " + offset + " / " + size + " => -1");
}
return -1;
}
}
public long getSize() {
if (mConnection == null) {
try {
seekTo(0);
} catch (IOException e) {
return -1;
}
}
return mTotalSize;
}
public String getMIMEType() {
if (mConnection == null) {
try {
seekTo(0);
} catch (IOException e) {
return "application/octet-stream";
}
}
return mConnection.getContentType();
}
@Override
protected void finalize() {
native_finalize();
}
private static native final void native_init();
private native final void native_setup();
private native final void native_finalize();
private native final IBinder native_getIMemory();
private native final int native_readAt(long offset, int size);
static {
System.loadLibrary("media_jni");
native_init();
}
private int mNativeContext;
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2013 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.Binder;
import android.os.IBinder;
import android.util.Log;
/** @hide */
public class MediaHTTPService extends IMediaHTTPService.Stub {
private static final String TAG = "MediaHTTPService";
public MediaHTTPService() {
}
public IMediaHTTPConnection makeHTTPConnection() {
return new MediaHTTPConnection();
}
/* package private */static IBinder createHttpServiceBinderIfNecessary(
String path) {
if (path.startsWith("http://")
|| path.startsWith("https://")
|| path.startsWith("widevine://")) {
return (new MediaHTTPService()).asBinder();
}
return null;
}
}

View File

@@ -21,6 +21,7 @@ import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.IBinder;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -100,11 +101,16 @@ public class MediaMetadataRetriever
values[i] = entry.getValue();
++i;
}
_setDataSource(uri, keys, values);
_setDataSource(
MediaHTTPService.createHttpServiceBinderIfNecessary(uri),
uri,
keys,
values);
}
private native void _setDataSource(
String uri, String[] keys, String[] values)
IBinder httpServiceBinder, String uri, String[] keys, String[] values)
throws IllegalArgumentException;
/**

View File

@@ -27,6 +27,7 @@ import android.net.ProxyProperties;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
@@ -989,8 +990,18 @@ public class MediaPlayer implements SubtitleController.Listener
}
}
private native void _setDataSource(
private void _setDataSource(
String path, String[] keys, String[] values)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
nativeSetDataSource(
MediaHTTPService.createHttpServiceBinderIfNecessary(path),
path,
keys,
values);
}
private native void nativeSetDataSource(
IBinder httpServiceBinder, String path, String[] keys, String[] values)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
/**

View File

@@ -8,6 +8,7 @@ LOCAL_SRC_FILES:= \
android_media_MediaCodecList.cpp \
android_media_MediaDrm.cpp \
android_media_MediaExtractor.cpp \
android_media_MediaHTTPConnection.cpp \
android_media_MediaMuxer.cpp \
android_media_MediaPlayer.cpp \
android_media_MediaRecorder.cpp \

View File

@@ -26,6 +26,7 @@
#include "jni.h"
#include "JNIHelp.h"
#include <media/IMediaHTTPService.h>
#include <media/hardware/CryptoAPI.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -35,6 +36,8 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/NuMediaExtractor.h>
#include "android_util_Binder.h"
namespace android {
struct fields_t {
@@ -135,8 +138,10 @@ JMediaExtractor::~JMediaExtractor() {
}
status_t JMediaExtractor::setDataSource(
const char *path, const KeyedVector<String8, String8> *headers) {
return mImpl->setDataSource(path, headers);
const sp<IMediaHTTPService> &httpService,
const char *path,
const KeyedVector<String8, String8> *headers) {
return mImpl->setDataSource(httpService, path, headers);
}
status_t JMediaExtractor::setDataSource(int fd, off64_t offset, off64_t size) {
@@ -661,7 +666,10 @@ static void android_media_MediaExtractor_native_setup(
static void android_media_MediaExtractor_setDataSource(
JNIEnv *env, jobject thiz,
jstring pathObj, jobjectArray keysArray, jobjectArray valuesArray) {
jobject httpServiceBinderObj,
jstring pathObj,
jobjectArray keysArray,
jobjectArray valuesArray) {
sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
if (extractor == NULL) {
@@ -686,7 +694,13 @@ static void android_media_MediaExtractor_setDataSource(
return;
}
status_t err = extractor->setDataSource(path, &headers);
sp<IMediaHTTPService> httpService;
if (httpServiceBinderObj != NULL) {
sp<IBinder> binder = ibinderForJavaObject(env, httpServiceBinderObj);
httpService = interface_cast<IMediaHTTPService>(binder);
}
status_t err = extractor->setDataSource(httpService, path, &headers);
env->ReleaseStringUTFChars(pathObj, path);
path = NULL;
@@ -839,8 +853,9 @@ static JNINativeMethod gMethods[] = {
{ "native_finalize", "()V",
(void *)android_media_MediaExtractor_native_finalize },
{ "setDataSource", "(Ljava/lang/String;[Ljava/lang/String;"
"[Ljava/lang/String;)V",
{ "nativeSetDataSource",
"(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;"
"[Ljava/lang/String;)V",
(void *)android_media_MediaExtractor_setDataSource },
{ "setDataSource", "(Ljava/io/FileDescriptor;JJ)V",

View File

@@ -29,6 +29,7 @@
namespace android {
struct IMediaHTTPService;
struct MetaData;
struct NuMediaExtractor;
@@ -36,6 +37,7 @@ struct JMediaExtractor : public RefBase {
JMediaExtractor(JNIEnv *env, jobject thiz);
status_t setDataSource(
const sp<IMediaHTTPService> &httpService,
const char *path,
const KeyedVector<String8, String8> *headers);

View File

@@ -0,0 +1,179 @@
/*
* Copyright 2013, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//#define LOG_NDEBUG 0
#define LOG_TAG "MediaHTTPConnection-JNI"
#include <utils/Log.h>
#include <binder/MemoryDealer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <nativehelper/ScopedLocalRef.h>
#include "android_media_MediaHTTPConnection.h"
#include "android_util_Binder.h"
#include "android_runtime/AndroidRuntime.h"
#include "jni.h"
#include "JNIHelp.h"
namespace android {
JMediaHTTPConnection::JMediaHTTPConnection(JNIEnv *env, jobject thiz)
: mClass(NULL),
mObject(NULL),
mByteArrayObj(NULL) {
jclass clazz = env->GetObjectClass(thiz);
CHECK(clazz != NULL);
mClass = (jclass)env->NewGlobalRef(clazz);
mObject = env->NewWeakGlobalRef(thiz);
mDealer = new MemoryDealer(kBufferSize, "MediaHTTPConnection");
mMemory = mDealer->allocate(kBufferSize);
ScopedLocalRef<jbyteArray> tmp(
env, env->NewByteArray(JMediaHTTPConnection::kBufferSize));
mByteArrayObj = (jbyteArray)env->NewGlobalRef(tmp.get());
}
JMediaHTTPConnection::~JMediaHTTPConnection() {
JNIEnv *env = AndroidRuntime::getJNIEnv();
env->DeleteGlobalRef(mByteArrayObj);
mByteArrayObj = NULL;
env->DeleteWeakGlobalRef(mObject);
mObject = NULL;
env->DeleteGlobalRef(mClass);
mClass = NULL;
}
sp<IMemory> JMediaHTTPConnection::getIMemory() {
return mMemory;
}
jbyteArray JMediaHTTPConnection::getByteArrayObj() {
return mByteArrayObj;
}
} // namespace android
using namespace android;
struct fields_t {
jfieldID context;
jmethodID readAtMethodID;
};
static fields_t gFields;
static sp<JMediaHTTPConnection> setObject(
JNIEnv *env, jobject thiz, const sp<JMediaHTTPConnection> &conn) {
sp<JMediaHTTPConnection> old =
(JMediaHTTPConnection *)env->GetIntField(thiz, gFields.context);
if (conn != NULL) {
conn->incStrong(thiz);
}
if (old != NULL) {
old->decStrong(thiz);
}
env->SetIntField(thiz, gFields.context, (int)conn.get());
return old;
}
static sp<JMediaHTTPConnection> getObject(JNIEnv *env, jobject thiz) {
return (JMediaHTTPConnection *)env->GetIntField(thiz, gFields.context);
}
static void android_media_MediaHTTPConnection_native_init(JNIEnv *env) {
ScopedLocalRef<jclass> clazz(
env, env->FindClass("android/media/MediaHTTPConnection"));
CHECK(clazz.get() != NULL);
gFields.context = env->GetFieldID(clazz.get(), "mNativeContext", "I");
CHECK(gFields.context != NULL);
gFields.readAtMethodID = env->GetMethodID(clazz.get(), "readAt", "(J[BI)I");
}
static void android_media_MediaHTTPConnection_native_setup(
JNIEnv *env, jobject thiz) {
sp<JMediaHTTPConnection> conn = new JMediaHTTPConnection(env, thiz);
setObject(env, thiz, conn);
}
static void android_media_MediaHTTPConnection_native_finalize(
JNIEnv *env, jobject thiz) {
setObject(env, thiz, NULL);
}
static jobject android_media_MediaHTTPConnection_native_getIMemory(
JNIEnv *env, jobject thiz) {
sp<JMediaHTTPConnection> conn = getObject(env, thiz);
return javaObjectForIBinder(env, conn->getIMemory()->asBinder());
}
static jint android_media_MediaHTTPConnection_native_readAt(
JNIEnv *env, jobject thiz, jlong offset, jint size) {
sp<JMediaHTTPConnection> conn = getObject(env, thiz);
if (size > JMediaHTTPConnection::kBufferSize) {
size = JMediaHTTPConnection::kBufferSize;
}
jbyteArray byteArrayObj = conn->getByteArrayObj();
jint n = env->CallIntMethod(
thiz, gFields.readAtMethodID, offset, byteArrayObj, size);
if (n > 0) {
env->GetByteArrayRegion(
byteArrayObj,
0,
n,
(jbyte *)conn->getIMemory()->pointer());
}
return n;
}
static JNINativeMethod gMethods[] = {
{ "native_getIMemory", "()Landroid/os/IBinder;",
(void *)android_media_MediaHTTPConnection_native_getIMemory },
{ "native_readAt", "(JI)I",
(void *)android_media_MediaHTTPConnection_native_readAt },
{ "native_init", "()V",
(void *)android_media_MediaHTTPConnection_native_init },
{ "native_setup", "()V",
(void *)android_media_MediaHTTPConnection_native_setup },
{ "native_finalize", "()V",
(void *)android_media_MediaHTTPConnection_native_finalize },
};
int register_android_media_MediaHTTPConnection(JNIEnv *env) {
return AndroidRuntime::registerNativeMethods(env,
"android/media/MediaHTTPConnection", gMethods, NELEM(gMethods));
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2013, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _ANDROID_MEDIA_MEDIAHTTPCONNECTION_H_
#define _ANDROID_MEDIA_MEDIAHTTPCONNECTION_H_
#include "jni.h"
#include <media/stagefright/foundation/ABase.h>
#include <utils/RefBase.h>
namespace android {
struct IMemory;
struct MemoryDealer;
struct JMediaHTTPConnection : public RefBase {
enum {
kBufferSize = 32768,
};
JMediaHTTPConnection(JNIEnv *env, jobject thiz);
sp<IMemory> getIMemory();
jbyteArray getByteArrayObj();
protected:
virtual ~JMediaHTTPConnection();
private:
jclass mClass;
jweak mObject;
jbyteArray mByteArrayObj;
sp<MemoryDealer> mDealer;
sp<IMemory> mMemory;
DISALLOW_EVIL_CONSTRUCTORS(JMediaHTTPConnection);
};
} // namespace android
#endif // _ANDROID_MEDIA_MEDIAHTTPCONNECTION_H_

View File

@@ -22,6 +22,7 @@
#include <utils/Log.h>
#include <utils/threads.h>
#include <core/SkBitmap.h>
#include <media/IMediaHTTPService.h>
#include <media/mediametadataretriever.h>
#include <private/media/VideoFrame.h>
@@ -29,6 +30,7 @@
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include "android_media_Utils.h"
#include "android_util_Binder.h"
using namespace android;
@@ -80,7 +82,7 @@ static void setRetriever(JNIEnv* env, jobject thiz, MediaMetadataRetriever* retr
static void
android_media_MediaMetadataRetriever_setDataSourceAndHeaders(
JNIEnv *env, jobject thiz, jstring path,
JNIEnv *env, jobject thiz, jobject httpServiceBinderObj, jstring path,
jobjectArray keys, jobjectArray values) {
ALOGV("setDataSource");
@@ -122,10 +124,19 @@ android_media_MediaMetadataRetriever_setDataSourceAndHeaders(
env, keys, values, &headersVector)) {
return;
}
sp<IMediaHTTPService> httpService;
if (httpServiceBinderObj != NULL) {
sp<IBinder> binder = ibinderForJavaObject(env, httpServiceBinderObj);
httpService = interface_cast<IMediaHTTPService>(binder);
}
process_media_retriever_call(
env,
retriever->setDataSource(
pathStr.string(), headersVector.size() > 0 ? &headersVector : NULL),
httpService,
pathStr.string(),
headersVector.size() > 0 ? &headersVector : NULL),
"java/lang/RuntimeException",
"setDataSource failed");
@@ -442,7 +453,7 @@ static void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobje
static JNINativeMethod nativeMethods[] = {
{
"_setDataSource",
"(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V",
"(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V",
(void *)android_media_MediaMetadataRetriever_setDataSourceAndHeaders
},

View File

@@ -20,6 +20,7 @@
#include "utils/Log.h"
#include <media/mediaplayer.h>
#include <media/IMediaHTTPService.h>
#include <media/MediaPlayerInterface.h>
#include <stdio.h>
#include <assert.h>
@@ -45,6 +46,7 @@
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include "android_util_Binder.h"
// ----------------------------------------------------------------------------
using namespace android;
@@ -183,7 +185,7 @@ static void process_media_player_call(JNIEnv *env, jobject thiz, status_t opStat
static void
android_media_MediaPlayer_setDataSourceAndHeaders(
JNIEnv *env, jobject thiz, jstring path,
JNIEnv *env, jobject thiz, jobject httpServiceBinderObj, jstring path,
jobjectArray keys, jobjectArray values) {
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
@@ -214,8 +216,15 @@ android_media_MediaPlayer_setDataSourceAndHeaders(
return;
}
sp<IMediaHTTPService> httpService;
if (httpServiceBinderObj != NULL) {
sp<IBinder> binder = ibinderForJavaObject(env, httpServiceBinderObj);
httpService = interface_cast<IMediaHTTPService>(binder);
}
status_t opStatus =
mp->setDataSource(
httpService,
pathStr,
headersVector.size() > 0? &headersVector : NULL);
@@ -726,7 +735,8 @@ static void android_media_MediaPlayer_attachAuxEffect(JNIEnv *env, jobject thiz
}
static jint
android_media_MediaPlayer_pullBatteryData(JNIEnv *env, jobject thiz, jobject java_reply)
android_media_MediaPlayer_pullBatteryData(
JNIEnv *env, jobject /* thiz */, jobject java_reply)
{
sp<IBinder> binder = defaultServiceManager()->getService(String16("media.player"));
sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
@@ -856,8 +866,9 @@ android_media_MediaPlayer_updateProxyConfig(
static JNINativeMethod gMethods[] = {
{
"_setDataSource",
"(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V",
"nativeSetDataSource",
"(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;"
"[Ljava/lang/String;)V",
(void *)android_media_MediaPlayer_setDataSourceAndHeaders
},
@@ -911,6 +922,7 @@ extern int register_android_media_Drm(JNIEnv *env);
extern int register_android_media_MediaCodec(JNIEnv *env);
extern int register_android_media_MediaExtractor(JNIEnv *env);
extern int register_android_media_MediaCodecList(JNIEnv *env);
extern int register_android_media_MediaHTTPConnection(JNIEnv *env);
extern int register_android_media_MediaMetadataRetriever(JNIEnv *env);
extern int register_android_media_MediaMuxer(JNIEnv *env);
extern int register_android_media_MediaRecorder(JNIEnv *env);
@@ -922,7 +934,7 @@ extern int register_android_mtp_MtpDatabase(JNIEnv *env);
extern int register_android_mtp_MtpDevice(JNIEnv *env);
extern int register_android_mtp_MtpServer(JNIEnv *env);
jint JNI_OnLoad(JavaVM* vm, void* reserved)
jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
JNIEnv* env = NULL;
jint result = -1;
@@ -1018,6 +1030,11 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved)
goto bail;
}
if (register_android_media_MediaHTTPConnection(env) < 0) {
ALOGE("ERROR: MediaHTTPConnection native registration failed");
goto bail;
}
/* success -- return valid version number */
result = JNI_VERSION_1_4;

View File

@@ -27,6 +27,7 @@
using android::INVALID_OPERATION;
using android::Surface;
using android::IGraphicBufferProducer;
using android::IMediaHTTPService;
using android::MediaPlayerBase;
using android::OK;
using android::Parcel;
@@ -57,6 +58,7 @@ class Player: public MediaPlayerBase
virtual bool hardwareOutput() {return true;}
virtual status_t setDataSource(
const sp<IMediaHTTPService> &httpService,
const char *url,
const KeyedVector<String8, String8> *) {
ALOGV("setDataSource %s", url);