Merge "Require INTERNET permission for network-based content. Bug #1870981"
This commit is contained in:
@@ -10668,7 +10668,7 @@ package android.media {
|
|||||||
method public void setAuxEffectSendLevel(float);
|
method public void setAuxEffectSendLevel(float);
|
||||||
method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
|
method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
|
||||||
method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
|
method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
|
||||||
method public void setDataSource(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
|
method public void setDataSource(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
|
||||||
method public void setDataSource(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
|
method public void setDataSource(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
|
||||||
method public void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
|
method public void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
|
||||||
method public void setDisplay(android.view.SurfaceHolder);
|
method public void setDisplay(android.view.SurfaceHolder);
|
||||||
|
|||||||
@@ -357,9 +357,9 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sp<IMediaPlayer> player =
|
sp<IMediaPlayer> player =
|
||||||
service->create(getpid(), client, source, 0);
|
service->create(getpid(), client, 0);
|
||||||
|
|
||||||
if (player != NULL) {
|
if (player != NULL && player->setDataSource(source) == NO_ERROR) {
|
||||||
player->setVideoSurface(surface);
|
player->setVideoSurface(surface);
|
||||||
player->start();
|
player->start();
|
||||||
|
|
||||||
|
|||||||
@@ -20,11 +20,13 @@
|
|||||||
#include <utils/RefBase.h>
|
#include <utils/RefBase.h>
|
||||||
#include <binder/IInterface.h>
|
#include <binder/IInterface.h>
|
||||||
#include <binder/Parcel.h>
|
#include <binder/Parcel.h>
|
||||||
|
#include <utils/KeyedVector.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
class Parcel;
|
class Parcel;
|
||||||
class Surface;
|
class Surface;
|
||||||
|
class IStreamSource;
|
||||||
class ISurfaceTexture;
|
class ISurfaceTexture;
|
||||||
|
|
||||||
class IMediaPlayer: public IInterface
|
class IMediaPlayer: public IInterface
|
||||||
@@ -34,6 +36,10 @@ public:
|
|||||||
|
|
||||||
virtual void disconnect() = 0;
|
virtual void disconnect() = 0;
|
||||||
|
|
||||||
|
virtual status_t setDataSource(const char *url,
|
||||||
|
const KeyedVector<String8, String8>* headers) = 0;
|
||||||
|
virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0;
|
||||||
|
virtual status_t setDataSource(const sp<IStreamSource>& source) = 0;
|
||||||
virtual status_t setVideoSurface(const sp<Surface>& surface) = 0;
|
virtual status_t setVideoSurface(const sp<Surface>& surface) = 0;
|
||||||
virtual status_t setVideoSurfaceTexture(
|
virtual status_t setVideoSurfaceTexture(
|
||||||
const sp<ISurfaceTexture>& surfaceTexture) = 0;
|
const sp<ISurfaceTexture>& surfaceTexture) = 0;
|
||||||
|
|||||||
@@ -39,17 +39,9 @@ class IMediaPlayerService: public IInterface
|
|||||||
public:
|
public:
|
||||||
DECLARE_META_INTERFACE(MediaPlayerService);
|
DECLARE_META_INTERFACE(MediaPlayerService);
|
||||||
|
|
||||||
virtual sp<IMediaRecorder> createMediaRecorder(pid_t pid) = 0;
|
virtual sp<IMediaRecorder> createMediaRecorder(pid_t pid) = 0;
|
||||||
virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid) = 0;
|
virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid) = 0;
|
||||||
virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client,
|
virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int audioSessionId = 0) = 0;
|
||||||
const char* url, const KeyedVector<String8, String8> *headers = NULL,
|
|
||||||
int audioSessionId = 0) = 0;
|
|
||||||
virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client,
|
|
||||||
int fd, int64_t offset, int64_t length, int audioSessionId) = 0;
|
|
||||||
|
|
||||||
virtual sp<IMediaPlayer> create(
|
|
||||||
pid_t pid, const sp<IMediaPlayerClient> &client,
|
|
||||||
const sp<IStreamSource> &source, int audioSessionId) = 0;
|
|
||||||
|
|
||||||
virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
|
virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
|
||||||
virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
|
virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include <media/IMediaPlayerClient.h>
|
#include <media/IMediaPlayerClient.h>
|
||||||
#include <media/IMediaPlayer.h>
|
#include <media/IMediaPlayer.h>
|
||||||
#include <media/IMediaDeathNotifier.h>
|
#include <media/IMediaDeathNotifier.h>
|
||||||
|
#include <media/IStreamSource.h>
|
||||||
|
|
||||||
#include <utils/KeyedVector.h>
|
#include <utils/KeyedVector.h>
|
||||||
#include <utils/String8.h>
|
#include <utils/String8.h>
|
||||||
@@ -168,6 +169,7 @@ public:
|
|||||||
const KeyedVector<String8, String8> *headers);
|
const KeyedVector<String8, String8> *headers);
|
||||||
|
|
||||||
status_t setDataSource(int fd, int64_t offset, int64_t length);
|
status_t setDataSource(int fd, int64_t offset, int64_t length);
|
||||||
|
status_t setDataSource(const sp<IStreamSource> &source);
|
||||||
status_t setVideoSurface(const sp<Surface>& surface);
|
status_t setVideoSurface(const sp<Surface>& surface);
|
||||||
status_t setVideoSurfaceTexture(
|
status_t setVideoSurfaceTexture(
|
||||||
const sp<ISurfaceTexture>& surfaceTexture);
|
const sp<ISurfaceTexture>& surfaceTexture);
|
||||||
@@ -206,7 +208,7 @@ private:
|
|||||||
status_t seekTo_l(int msec);
|
status_t seekTo_l(int msec);
|
||||||
status_t prepareAsync_l();
|
status_t prepareAsync_l();
|
||||||
status_t getDuration_l(int *msec);
|
status_t getDuration_l(int *msec);
|
||||||
status_t setDataSource(const sp<IMediaPlayer>& player);
|
status_t attachNewPlayer(const sp<IMediaPlayer>& player);
|
||||||
void disconnectNativeWindow();
|
void disconnectNativeWindow();
|
||||||
status_t reset_l();
|
status_t reset_l();
|
||||||
|
|
||||||
|
|||||||
@@ -459,6 +459,9 @@ import java.lang.ref.WeakReference;
|
|||||||
* android.R.styleable#AndroidManifestUsesPermission <uses-permission>}
|
* android.R.styleable#AndroidManifestUsesPermission <uses-permission>}
|
||||||
* element.
|
* element.
|
||||||
*
|
*
|
||||||
|
* <p>This class requires the {@link android.Manifest.permission#INTERNET} permission
|
||||||
|
* when used with network-based content.
|
||||||
|
*
|
||||||
* <a name="Callbacks"></a>
|
* <a name="Callbacks"></a>
|
||||||
* <h3>Callbacks</h3>
|
* <h3>Callbacks</h3>
|
||||||
* <p>Applications may want to register for informational and error
|
* <p>Applications may want to register for informational and error
|
||||||
@@ -828,6 +831,7 @@ public class MediaPlayer
|
|||||||
fd.close();
|
fd.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(TAG, "Couldn't open file on client side, trying server side");
|
Log.d(TAG, "Couldn't open file on client side, trying server side");
|
||||||
setDataSource(uri.toString(), headers);
|
setDataSource(uri.toString(), headers);
|
||||||
return;
|
return;
|
||||||
@@ -839,7 +843,8 @@ public class MediaPlayer
|
|||||||
* @param path the path of the file, or the http/rtsp URL of the stream you want to play
|
* @param path the path of the file, or the http/rtsp URL of the stream you want to play
|
||||||
* @throws IllegalStateException if it is called in an invalid state
|
* @throws IllegalStateException if it is called in an invalid state
|
||||||
*/
|
*/
|
||||||
public native void setDataSource(String path) throws IOException, IllegalArgumentException, IllegalStateException;
|
public native void setDataSource(String path)
|
||||||
|
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the data source (file-path or http/rtsp URL) to use.
|
* Sets the data source (file-path or http/rtsp URL) to use.
|
||||||
@@ -850,7 +855,7 @@ public class MediaPlayer
|
|||||||
* @hide pending API council
|
* @hide pending API council
|
||||||
*/
|
*/
|
||||||
public void setDataSource(String path, Map<String, String> headers)
|
public void setDataSource(String path, Map<String, String> headers)
|
||||||
throws IOException, IllegalArgumentException, IllegalStateException
|
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException
|
||||||
{
|
{
|
||||||
String[] keys = null;
|
String[] keys = null;
|
||||||
String[] values = null;
|
String[] values = null;
|
||||||
@@ -871,7 +876,7 @@ public class MediaPlayer
|
|||||||
|
|
||||||
private native void _setDataSource(
|
private native void _setDataSource(
|
||||||
String path, String[] keys, String[] values)
|
String path, String[] keys, String[] values)
|
||||||
throws IOException, IllegalArgumentException, IllegalStateException;
|
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the data source (FileDescriptor) to use. It is the caller's responsibility
|
* Sets the data source (FileDescriptor) to use. It is the caller's responsibility
|
||||||
|
|||||||
@@ -155,6 +155,8 @@ static void process_media_player_call(JNIEnv *env, jobject thiz, status_t opStat
|
|||||||
} else { // Throw exception!
|
} else { // Throw exception!
|
||||||
if ( opStatus == (status_t) INVALID_OPERATION ) {
|
if ( opStatus == (status_t) INVALID_OPERATION ) {
|
||||||
jniThrowException(env, "java/lang/IllegalStateException", NULL);
|
jniThrowException(env, "java/lang/IllegalStateException", NULL);
|
||||||
|
} else if ( opStatus == (status_t) PERMISSION_DENIED ) {
|
||||||
|
jniThrowException(env, "java/lang/SecurityException", NULL);
|
||||||
} else if ( opStatus != (status_t) OK ) {
|
} else if ( opStatus != (status_t) OK ) {
|
||||||
if (strlen(message) > 230) {
|
if (strlen(message) > 230) {
|
||||||
// if the message is too long, don't bother displaying the status code
|
// if the message is too long, don't bother displaying the status code
|
||||||
|
|||||||
@@ -21,14 +21,20 @@
|
|||||||
#include <binder/Parcel.h>
|
#include <binder/Parcel.h>
|
||||||
|
|
||||||
#include <media/IMediaPlayer.h>
|
#include <media/IMediaPlayer.h>
|
||||||
|
#include <media/IStreamSource.h>
|
||||||
|
|
||||||
#include <surfaceflinger/ISurface.h>
|
#include <surfaceflinger/ISurface.h>
|
||||||
#include <surfaceflinger/Surface.h>
|
#include <surfaceflinger/Surface.h>
|
||||||
#include <gui/ISurfaceTexture.h>
|
#include <gui/ISurfaceTexture.h>
|
||||||
|
#include <utils/String8.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
|
DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
|
||||||
|
SET_DATA_SOURCE_URL,
|
||||||
|
SET_DATA_SOURCE_FD,
|
||||||
|
SET_DATA_SOURCE_STREAM,
|
||||||
SET_VIDEO_SURFACE,
|
SET_VIDEO_SURFACE,
|
||||||
PREPARE_ASYNC,
|
PREPARE_ASYNC,
|
||||||
START,
|
START,
|
||||||
@@ -68,6 +74,43 @@ public:
|
|||||||
remote()->transact(DISCONNECT, data, &reply);
|
remote()->transact(DISCONNECT, data, &reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t setDataSource(const char* url,
|
||||||
|
const KeyedVector<String8, String8>* headers)
|
||||||
|
{
|
||||||
|
Parcel data, reply;
|
||||||
|
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||||||
|
data.writeCString(url);
|
||||||
|
if (headers == NULL) {
|
||||||
|
data.writeInt32(0);
|
||||||
|
} else {
|
||||||
|
// serialize the headers
|
||||||
|
data.writeInt32(headers->size());
|
||||||
|
for (size_t i = 0; i < headers->size(); ++i) {
|
||||||
|
data.writeString8(headers->keyAt(i));
|
||||||
|
data.writeString8(headers->valueAt(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
|
||||||
|
return reply.readInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t setDataSource(int fd, int64_t offset, int64_t length) {
|
||||||
|
Parcel data, reply;
|
||||||
|
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||||||
|
data.writeFileDescriptor(fd);
|
||||||
|
data.writeInt64(offset);
|
||||||
|
data.writeInt64(length);
|
||||||
|
remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
|
||||||
|
return reply.readInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t setDataSource(const sp<IStreamSource> &source) {
|
||||||
|
Parcel data, reply;
|
||||||
|
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||||||
|
data.writeStrongBinder(source->asBinder());
|
||||||
|
return reply.readInt32();
|
||||||
|
}
|
||||||
|
|
||||||
// pass the buffered Surface to the media player service
|
// pass the buffered Surface to the media player service
|
||||||
status_t setVideoSurface(const sp<Surface>& surface)
|
status_t setVideoSurface(const sp<Surface>& surface)
|
||||||
{
|
{
|
||||||
@@ -273,6 +316,34 @@ status_t BnMediaPlayer::onTransact(
|
|||||||
disconnect();
|
disconnect();
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
} break;
|
} break;
|
||||||
|
case SET_DATA_SOURCE_URL: {
|
||||||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||||||
|
const char* url = data.readCString();
|
||||||
|
KeyedVector<String8, String8> headers;
|
||||||
|
int32_t numHeaders = data.readInt32();
|
||||||
|
for (int i = 0; i < numHeaders; ++i) {
|
||||||
|
String8 key = data.readString8();
|
||||||
|
String8 value = data.readString8();
|
||||||
|
headers.add(key, value);
|
||||||
|
}
|
||||||
|
reply->writeInt32(setDataSource(url, numHeaders > 0 ? &headers : NULL));
|
||||||
|
return NO_ERROR;
|
||||||
|
} break;
|
||||||
|
case SET_DATA_SOURCE_FD: {
|
||||||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||||||
|
int fd = data.readFileDescriptor();
|
||||||
|
int64_t offset = data.readInt64();
|
||||||
|
int64_t length = data.readInt64();
|
||||||
|
reply->writeInt32(setDataSource(fd, offset, length));
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
case SET_DATA_SOURCE_STREAM: {
|
||||||
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||||||
|
sp<IStreamSource> source =
|
||||||
|
interface_cast<IStreamSource>(data.readStrongBinder());
|
||||||
|
reply->writeInt32(setDataSource(source));
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
case SET_VIDEO_SURFACE: {
|
case SET_VIDEO_SURFACE: {
|
||||||
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||||||
sp<Surface> surface = Surface::readFromParcel(data);
|
sp<Surface> surface = Surface::readFromParcel(data);
|
||||||
|
|||||||
@@ -30,9 +30,7 @@
|
|||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CREATE_URL = IBinder::FIRST_CALL_TRANSACTION,
|
CREATE = IBinder::FIRST_CALL_TRANSACTION,
|
||||||
CREATE_FD,
|
|
||||||
CREATE_STREAM,
|
|
||||||
DECODE_URL,
|
DECODE_URL,
|
||||||
DECODE_FD,
|
DECODE_FD,
|
||||||
CREATE_MEDIA_RECORDER,
|
CREATE_MEDIA_RECORDER,
|
||||||
@@ -60,28 +58,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual sp<IMediaPlayer> create(
|
virtual sp<IMediaPlayer> create(
|
||||||
pid_t pid, const sp<IMediaPlayerClient>& client,
|
pid_t pid, const sp<IMediaPlayerClient>& client, int audioSessionId) {
|
||||||
const char* url, const KeyedVector<String8, String8> *headers, int audioSessionId) {
|
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
|
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
|
||||||
data.writeInt32(pid);
|
data.writeInt32(pid);
|
||||||
data.writeStrongBinder(client->asBinder());
|
data.writeStrongBinder(client->asBinder());
|
||||||
data.writeCString(url);
|
|
||||||
|
|
||||||
if (headers == NULL) {
|
|
||||||
data.writeInt32(0);
|
|
||||||
} else {
|
|
||||||
// serialize the headers
|
|
||||||
data.writeInt32(headers->size());
|
|
||||||
for (size_t i = 0; i < headers->size(); ++i) {
|
|
||||||
data.writeString8(headers->keyAt(i));
|
|
||||||
data.writeString8(headers->valueAt(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data.writeInt32(audioSessionId);
|
data.writeInt32(audioSessionId);
|
||||||
|
|
||||||
remote()->transact(CREATE_URL, data, &reply);
|
remote()->transact(CREATE, data, &reply);
|
||||||
|
|
||||||
return interface_cast<IMediaPlayer>(reply.readStrongBinder());
|
return interface_cast<IMediaPlayer>(reply.readStrongBinder());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,38 +78,6 @@ public:
|
|||||||
return interface_cast<IMediaRecorder>(reply.readStrongBinder());
|
return interface_cast<IMediaRecorder>(reply.readStrongBinder());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd,
|
|
||||||
int64_t offset, int64_t length, int audioSessionId)
|
|
||||||
{
|
|
||||||
Parcel data, reply;
|
|
||||||
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
|
|
||||||
data.writeInt32(pid);
|
|
||||||
data.writeStrongBinder(client->asBinder());
|
|
||||||
data.writeFileDescriptor(fd);
|
|
||||||
data.writeInt64(offset);
|
|
||||||
data.writeInt64(length);
|
|
||||||
data.writeInt32(audioSessionId);
|
|
||||||
|
|
||||||
remote()->transact(CREATE_FD, data, &reply);
|
|
||||||
|
|
||||||
return interface_cast<IMediaPlayer>(reply.readStrongBinder());;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual sp<IMediaPlayer> create(
|
|
||||||
pid_t pid, const sp<IMediaPlayerClient> &client,
|
|
||||||
const sp<IStreamSource> &source, int audioSessionId) {
|
|
||||||
Parcel data, reply;
|
|
||||||
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
|
|
||||||
data.writeInt32(static_cast<int32_t>(pid));
|
|
||||||
data.writeStrongBinder(client->asBinder());
|
|
||||||
data.writeStrongBinder(source->asBinder());
|
|
||||||
data.writeInt32(static_cast<int32_t>(audioSessionId));
|
|
||||||
|
|
||||||
remote()->transact(CREATE_STREAM, data, &reply);
|
|
||||||
|
|
||||||
return interface_cast<IMediaPlayer>(reply.readStrongBinder());;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
|
virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
|
||||||
{
|
{
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
@@ -181,62 +133,16 @@ status_t BnMediaPlayerService::onTransact(
|
|||||||
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
||||||
{
|
{
|
||||||
switch(code) {
|
switch(code) {
|
||||||
case CREATE_URL: {
|
case CREATE: {
|
||||||
CHECK_INTERFACE(IMediaPlayerService, data, reply);
|
CHECK_INTERFACE(IMediaPlayerService, data, reply);
|
||||||
pid_t pid = data.readInt32();
|
pid_t pid = data.readInt32();
|
||||||
sp<IMediaPlayerClient> client =
|
sp<IMediaPlayerClient> client =
|
||||||
interface_cast<IMediaPlayerClient>(data.readStrongBinder());
|
interface_cast<IMediaPlayerClient>(data.readStrongBinder());
|
||||||
const char* url = data.readCString();
|
|
||||||
|
|
||||||
KeyedVector<String8, String8> headers;
|
|
||||||
int32_t numHeaders = data.readInt32();
|
|
||||||
for (int i = 0; i < numHeaders; ++i) {
|
|
||||||
String8 key = data.readString8();
|
|
||||||
String8 value = data.readString8();
|
|
||||||
headers.add(key, value);
|
|
||||||
}
|
|
||||||
int audioSessionId = data.readInt32();
|
int audioSessionId = data.readInt32();
|
||||||
|
sp<IMediaPlayer> player = create(pid, client, audioSessionId);
|
||||||
sp<IMediaPlayer> player = create(
|
|
||||||
pid, client, url, numHeaders > 0 ? &headers : NULL, audioSessionId);
|
|
||||||
|
|
||||||
reply->writeStrongBinder(player->asBinder());
|
reply->writeStrongBinder(player->asBinder());
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
} break;
|
} break;
|
||||||
case CREATE_FD: {
|
|
||||||
CHECK_INTERFACE(IMediaPlayerService, data, reply);
|
|
||||||
pid_t pid = data.readInt32();
|
|
||||||
sp<IMediaPlayerClient> client = interface_cast<IMediaPlayerClient>(data.readStrongBinder());
|
|
||||||
int fd = dup(data.readFileDescriptor());
|
|
||||||
int64_t offset = data.readInt64();
|
|
||||||
int64_t length = data.readInt64();
|
|
||||||
int audioSessionId = data.readInt32();
|
|
||||||
|
|
||||||
sp<IMediaPlayer> player = create(pid, client, fd, offset, length, audioSessionId);
|
|
||||||
reply->writeStrongBinder(player->asBinder());
|
|
||||||
return NO_ERROR;
|
|
||||||
} break;
|
|
||||||
case CREATE_STREAM:
|
|
||||||
{
|
|
||||||
CHECK_INTERFACE(IMediaPlayerService, data, reply);
|
|
||||||
|
|
||||||
pid_t pid = static_cast<pid_t>(data.readInt32());
|
|
||||||
|
|
||||||
sp<IMediaPlayerClient> client =
|
|
||||||
interface_cast<IMediaPlayerClient>(data.readStrongBinder());
|
|
||||||
|
|
||||||
sp<IStreamSource> source =
|
|
||||||
interface_cast<IStreamSource>(data.readStrongBinder());
|
|
||||||
|
|
||||||
int audioSessionId = static_cast<int>(data.readInt32());
|
|
||||||
|
|
||||||
sp<IMediaPlayer> player =
|
|
||||||
create(pid, client, source, audioSessionId);
|
|
||||||
|
|
||||||
reply->writeStrongBinder(player->asBinder());
|
|
||||||
return OK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DECODE_URL: {
|
case DECODE_URL: {
|
||||||
CHECK_INTERFACE(IMediaPlayerService, data, reply);
|
CHECK_INTERFACE(IMediaPlayerService, data, reply);
|
||||||
const char* url = data.readCString();
|
const char* url = data.readCString();
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t MediaPlayer::setDataSource(const sp<IMediaPlayer>& player)
|
status_t MediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player)
|
||||||
{
|
{
|
||||||
status_t err = UNKNOWN_ERROR;
|
status_t err = UNKNOWN_ERROR;
|
||||||
sp<IMediaPlayer> p;
|
sp<IMediaPlayer> p;
|
||||||
@@ -117,7 +117,7 @@ status_t MediaPlayer::setDataSource(const sp<IMediaPlayer>& player)
|
|||||||
|
|
||||||
if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) ||
|
if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) ||
|
||||||
(mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) {
|
(mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) {
|
||||||
LOGE("setDataSource called in state %d", mCurrentState);
|
LOGE("attachNewPlayer called in state %d", mCurrentState);
|
||||||
return INVALID_OPERATION;
|
return INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,9 +147,11 @@ status_t MediaPlayer::setDataSource(
|
|||||||
if (url != NULL) {
|
if (url != NULL) {
|
||||||
const sp<IMediaPlayerService>& service(getMediaPlayerService());
|
const sp<IMediaPlayerService>& service(getMediaPlayerService());
|
||||||
if (service != 0) {
|
if (service != 0) {
|
||||||
sp<IMediaPlayer> player(
|
sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
|
||||||
service->create(getpid(), this, url, headers, mAudioSessionId));
|
err = attachNewPlayer(player);
|
||||||
err = setDataSource(player);
|
if (err == NO_ERROR) {
|
||||||
|
err = mPlayer->setDataSource(url, headers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
@@ -161,8 +163,26 @@ status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
|
|||||||
status_t err = UNKNOWN_ERROR;
|
status_t err = UNKNOWN_ERROR;
|
||||||
const sp<IMediaPlayerService>& service(getMediaPlayerService());
|
const sp<IMediaPlayerService>& service(getMediaPlayerService());
|
||||||
if (service != 0) {
|
if (service != 0) {
|
||||||
sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length, mAudioSessionId));
|
sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
|
||||||
err = setDataSource(player);
|
err = attachNewPlayer(player);
|
||||||
|
if (err == NO_ERROR) {
|
||||||
|
err = mPlayer->setDataSource(fd, offset, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t MediaPlayer::setDataSource(const sp<IStreamSource> &source)
|
||||||
|
{
|
||||||
|
LOGV("setDataSource");
|
||||||
|
status_t err = UNKNOWN_ERROR;
|
||||||
|
const sp<IMediaPlayerService>& service(getMediaPlayerService());
|
||||||
|
if (service != 0) {
|
||||||
|
sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
|
||||||
|
err = attachNewPlayer(player);
|
||||||
|
if (err == NO_ERROR) {
|
||||||
|
err = mPlayer->setDataSource(source);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,6 +176,16 @@ bool findMetadata(const Metadata::Filter& filter, const int32_t val)
|
|||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
|
static bool checkPermission(const char* permissionString) {
|
||||||
|
#ifndef HAVE_ANDROID_OS
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
|
||||||
|
bool ok = checkCallingPermission(String16(permissionString));
|
||||||
|
if (!ok) LOGE("Request requires %s", permissionString);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Temp hack until we can register players
|
// TODO: Temp hack until we can register players
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *extension;
|
const char *extension;
|
||||||
@@ -245,31 +255,8 @@ sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever(pid_t pi
|
|||||||
return retriever;
|
return retriever;
|
||||||
}
|
}
|
||||||
|
|
||||||
sp<IMediaPlayer> MediaPlayerService::create(
|
|
||||||
pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,
|
|
||||||
const KeyedVector<String8, String8> *headers, int audioSessionId)
|
|
||||||
{
|
|
||||||
int32_t connId = android_atomic_inc(&mNextConnId);
|
|
||||||
|
|
||||||
sp<Client> c = new Client(
|
|
||||||
this, pid, connId, client, audioSessionId,
|
|
||||||
IPCThreadState::self()->getCallingUid());
|
|
||||||
|
|
||||||
LOGV("Create new client(%d) from pid %d, uid %d, url=%s, connId=%d, audioSessionId=%d",
|
|
||||||
connId, pid, IPCThreadState::self()->getCallingUid(), url, connId, audioSessionId);
|
|
||||||
if (NO_ERROR != c->setDataSource(url, headers))
|
|
||||||
{
|
|
||||||
c.clear();
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
wp<Client> w = c;
|
|
||||||
Mutex::Autolock lock(mLock);
|
|
||||||
mClients.add(w);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client,
|
sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client,
|
||||||
int fd, int64_t offset, int64_t length, int audioSessionId)
|
int audioSessionId)
|
||||||
{
|
{
|
||||||
int32_t connId = android_atomic_inc(&mNextConnId);
|
int32_t connId = android_atomic_inc(&mNextConnId);
|
||||||
|
|
||||||
@@ -277,40 +264,14 @@ sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClie
|
|||||||
this, pid, connId, client, audioSessionId,
|
this, pid, connId, client, audioSessionId,
|
||||||
IPCThreadState::self()->getCallingUid());
|
IPCThreadState::self()->getCallingUid());
|
||||||
|
|
||||||
LOGV("Create new client(%d) from pid %d, uid %d, fd=%d, offset=%lld, "
|
LOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
|
||||||
"length=%lld, audioSessionId=%d", connId, pid,
|
IPCThreadState::self()->getCallingUid());
|
||||||
IPCThreadState::self()->getCallingUid(), fd, offset, length, audioSessionId);
|
|
||||||
if (NO_ERROR != c->setDataSource(fd, offset, length)) {
|
wp<Client> w = c;
|
||||||
c.clear();
|
{
|
||||||
} else {
|
|
||||||
wp<Client> w = c;
|
|
||||||
Mutex::Autolock lock(mLock);
|
Mutex::Autolock lock(mLock);
|
||||||
mClients.add(w);
|
mClients.add(w);
|
||||||
}
|
}
|
||||||
::close(fd);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
sp<IMediaPlayer> MediaPlayerService::create(
|
|
||||||
pid_t pid, const sp<IMediaPlayerClient> &client,
|
|
||||||
const sp<IStreamSource> &source, int audioSessionId) {
|
|
||||||
int32_t connId = android_atomic_inc(&mNextConnId);
|
|
||||||
|
|
||||||
sp<Client> c = new Client(
|
|
||||||
this, pid, connId, client, audioSessionId,
|
|
||||||
IPCThreadState::self()->getCallingUid());
|
|
||||||
|
|
||||||
LOGV("Create new client(%d) from pid %d, audioSessionId=%d",
|
|
||||||
connId, pid, audioSessionId);
|
|
||||||
|
|
||||||
if (OK != c->setDataSource(source)) {
|
|
||||||
c.clear();
|
|
||||||
} else {
|
|
||||||
wp<Client> w = c;
|
|
||||||
Mutex::Autolock lock(mLock);
|
|
||||||
mClients.add(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -701,6 +662,14 @@ status_t MediaPlayerService::Client::setDataSource(
|
|||||||
if (url == NULL)
|
if (url == NULL)
|
||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
|
|
||||||
|
if ((strncmp(url, "http://", 7) == 0) ||
|
||||||
|
(strncmp(url, "https://", 8) == 0) ||
|
||||||
|
(strncmp(url, "rtsp://", 7) == 0)) {
|
||||||
|
if (!checkPermission("android.permission.INTERNET")) {
|
||||||
|
return PERMISSION_DENIED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (strncmp(url, "content://", 10) == 0) {
|
if (strncmp(url, "content://", 10) == 0) {
|
||||||
// get a filedescriptor for the content Uri and
|
// get a filedescriptor for the content Uri and
|
||||||
// pass it to the setDataSource(fd) method
|
// pass it to the setDataSource(fd) method
|
||||||
@@ -781,6 +750,7 @@ status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64
|
|||||||
// now set data source
|
// now set data source
|
||||||
mStatus = p->setDataSource(fd, offset, length);
|
mStatus = p->setDataSource(fd, offset, length);
|
||||||
if (mStatus == NO_ERROR) mPlayer = p;
|
if (mStatus == NO_ERROR) mPlayer = p;
|
||||||
|
|
||||||
return mStatus;
|
return mStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -188,16 +188,7 @@ public:
|
|||||||
void removeMediaRecorderClient(wp<MediaRecorderClient> client);
|
void removeMediaRecorderClient(wp<MediaRecorderClient> client);
|
||||||
virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid);
|
virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid);
|
||||||
|
|
||||||
// House keeping for media player clients
|
virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int audioSessionId);
|
||||||
virtual sp<IMediaPlayer> create(
|
|
||||||
pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,
|
|
||||||
const KeyedVector<String8, String8> *headers, int audioSessionId);
|
|
||||||
|
|
||||||
virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length, int audioSessionId);
|
|
||||||
|
|
||||||
virtual sp<IMediaPlayer> create(
|
|
||||||
pid_t pid, const sp<IMediaPlayerClient> &client,
|
|
||||||
const sp<IStreamSource> &source, int audioSessionId);
|
|
||||||
|
|
||||||
virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
|
virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
|
||||||
virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
|
virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
|
||||||
@@ -284,13 +275,13 @@ private:
|
|||||||
|
|
||||||
sp<MediaPlayerBase> createPlayer(player_type playerType);
|
sp<MediaPlayerBase> createPlayer(player_type playerType);
|
||||||
|
|
||||||
status_t setDataSource(
|
virtual status_t setDataSource(
|
||||||
const char *url,
|
const char *url,
|
||||||
const KeyedVector<String8, String8> *headers);
|
const KeyedVector<String8, String8> *headers);
|
||||||
|
|
||||||
status_t setDataSource(int fd, int64_t offset, int64_t length);
|
virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
|
||||||
|
|
||||||
status_t setDataSource(const sp<IStreamSource> &source);
|
virtual status_t setDataSource(const sp<IStreamSource> &source);
|
||||||
|
|
||||||
static void notify(void* cookie, int msg,
|
static void notify(void* cookie, int msg,
|
||||||
int ext1, int ext2, const Parcel *obj);
|
int ext1, int ext2, const Parcel *obj);
|
||||||
|
|||||||
Reference in New Issue
Block a user