Start support for XAAndroidBufferQueueItf in OpenMAX AL

Added an Android OpenMAX AL header for the Android interfaces
Registered the AndroidBufferQueueItf as an explicit
 interface on MediaPlayer.
Updated the Java+Native example to register a callback from
 which OpenMAX AL can retrieve the data to play
Started unifying the player object used by OpenMAX AL and
 OpenSL ES so they use a common class.

Change-Id: I73cec8c802f74767545c91278e5e73c8c7995218
diff --git a/libopensles/Android.mk b/libopensles/Android.mk
index 38639f2..82353d3 100644
--- a/libopensles/Android.mk
+++ b/libopensles/Android.mk
@@ -51,6 +51,7 @@
         locks.c                       \
         sles.c                        \
         sllog.c                       \
+        android_Player.cpp            \
         android_AVPlayer.cpp          \
         android_AudioPlayer.cpp       \
         android_AudioRecorder.cpp     \
diff --git a/libopensles/CMediaPlayer.c b/libopensles/CMediaPlayer.c
index 1c73497..c83b910 100644
--- a/libopensles/CMediaPlayer.c
+++ b/libopensles/CMediaPlayer.c
@@ -39,104 +39,27 @@
 #ifdef ANDROID
 using namespace android;
 
-struct MyStreamSource : public BnStreamSource {
-    // Caller retains ownership of fd.
-    MyStreamSource(int fd);
-
-    virtual void setListener(const sp<IStreamListener> &listener);
-    virtual void setBuffers(const Vector<sp<IMemory> > &buffers);
-
-    virtual void onBufferAvailable(size_t index);
-
-protected:
-    virtual ~MyStreamSource();
-
-private:
-    int mFd;
-
-    sp<IStreamListener> mListener;
-    Vector<sp<IMemory> > mBuffers;
-
-    DISALLOW_EVIL_CONSTRUCTORS(MyStreamSource);
-};
-
-MyStreamSource::MyStreamSource(int fd)
-    : mFd(fd) {
-    CHECK_GE(fd, 0);
-}
-
-MyStreamSource::~MyStreamSource() {
-}
-
-void MyStreamSource::setListener(const sp<IStreamListener> &listener) {
-    mListener = listener;
-}
-
-void MyStreamSource::setBuffers(const Vector<sp<IMemory> > &buffers) {
-    mBuffers = buffers;
-}
-
-void MyStreamSource::onBufferAvailable(size_t index) {
-    CHECK_LT(index, mBuffers.size());
-    sp<IMemory> mem = mBuffers.itemAt(index);
-
-    ssize_t n = read(mFd, mem->pointer(), mem->size());
-    if (n <= 0) {
-        mListener->issueCommand(IStreamListener::EOS, false /* synchronous */);
-    } else {
-        mListener->queueBuffer(index, n);
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-struct MyClient : public BnMediaPlayerClient {
-    MyClient()
-        : mEOS(false) {
-    }
-
-    virtual void notify(int msg, int ext1, int ext2) {
-        Mutex::Autolock autoLock(mLock);
-
-        if (msg == MEDIA_ERROR || msg == MEDIA_PLAYBACK_COMPLETE) {
-            mEOS = true;
-            mCondition.signal();
-        }
-    }
-
-    void waitForEOS() {
-        Mutex::Autolock autoLock(mLock);
-        while (!mEOS) {
-            mCondition.wait(mLock);
-        }
-    }
-
-protected:
-    virtual ~MyClient() {
-    }
-
-private:
-    Mutex mLock;
-    Condition mCondition;
-
-    bool mEOS;
-
-    DISALLOW_EVIL_CONSTRUCTORS(MyClient);
-};
 #endif
 
 
 XAresult CMediaPlayer_Realize(void *self, XAboolean async)
 {
-#ifdef ANDROID
     CMediaPlayer *thiz = (CMediaPlayer *) self;
 
+    SLresult result = XA_RESULT_SUCCESS;
+
+#ifdef ANDROID
+    result = android_Player_realize(thiz, async);
+#endif
+
+    // FIXME add support for display surface retrieval
+#if 0
     assert(XA_DATALOCATOR_URI == thiz->mDataSource.mLocator.mLocatorType);
     // assert(XA_FORMAT_NULL == this->mDataSource.mFormat.mFormatType);
     assert(XA_DATALOCATOR_NATIVEDISPLAY == thiz->mImageVideoSink.mLocator.mLocatorType);
     // assert(XA_FORMAT_NULL == this->mImageVideoSink.mFormat.mFormatType);
     // FIXME ignore the audio sink
-
+#ifdef ANDROID
     int fd = open((const char *) thiz->mDataSource.mLocator.mURI.URI, O_RDONLY);
     if (0 >= fd) {
         return err_to_result(errno);
@@ -165,8 +88,8 @@
         player->setVideoSurface(surface);
     }
 #endif
-
-    return XA_RESULT_SUCCESS;
+#endif
+    return result;
 }
 
 
diff --git a/libopensles/IAndroidBufferQueue.c b/libopensles/IAndroidBufferQueue.c
index f9f74ad..f01be23 100644
--- a/libopensles/IAndroidBufferQueue.c
+++ b/libopensles/IAndroidBufferQueue.c
@@ -28,14 +28,28 @@
     interface_lock_exclusive(this);
 
     // verify pre-condition that media object is in the SL_PLAYSTATE_STOPPED state
-    if (SL_PLAYSTATE_STOPPED == ((CAudioPlayer*) this->mThis)->mPlay.mState) {
+    // FIXME PRIORITY 1 check play state
+    //if (SL_PLAYSTATE_STOPPED == ((CAudioPlayer*) this->mThis)->mPlay.mState) {
         this->mCallback = callback;
         this->mContext = pContext;
-        result = SL_RESULT_SUCCESS;
-        android_audioPlayer_androidBufferQueue_registerCallback_l((CAudioPlayer*) this->mThis);
-    } else {
-        result = SL_RESULT_PRECONDITIONS_VIOLATED;
-    }
+
+        switch (InterfaceToObjectID(this)) {
+        case SL_OBJECTID_AUDIOPLAYER:
+            result = SL_RESULT_SUCCESS;
+            android_audioPlayer_androidBufferQueue_registerCallback_l((CAudioPlayer*) this->mThis);
+            break;
+        case XA_OBJECTID_MEDIAPLAYER:
+            SL_LOGI("IAndroidBufferQueue_RegisterCallback()");
+            result = SL_RESULT_SUCCESS;
+            android_Player_androidBufferQueue_registerCallback_l((CMediaPlayer*) this->mThis);
+        default:
+            result = SL_RESULT_PARAMETER_INVALID;
+            break;
+        }
+
+    //} else {
+    //    result = SL_RESULT_PRECONDITIONS_VIOLATED;
+    //}
 
     interface_unlock_exclusive(this);
 
@@ -75,9 +89,22 @@
 
     // FIXME return value? of particular interest: error is length is larger than size received
     //   in callback
-    result = SL_RESULT_SUCCESS;
-    android_audioPlayer_androidBufferQueue_enqueue_l((CAudioPlayer*) this->mThis,
-            bufferId, length, event, pData);
+    switch (InterfaceToObjectID(this)) {
+    case SL_OBJECTID_AUDIOPLAYER:
+        result = SL_RESULT_SUCCESS;
+        android_audioPlayer_androidBufferQueue_enqueue_l((CAudioPlayer*) this->mThis,
+                bufferId, length, event, pData);
+        break;
+    case XA_OBJECTID_MEDIAPLAYER:
+        //SL_LOGV("IAndroidBufferQueue_Enqueue()");
+        result = SL_RESULT_SUCCESS;
+        android_Player_androidBufferQueue_enqueue_l((CMediaPlayer*) this->mThis,
+                bufferId, length, event, pData);
+        break;
+    default:
+        result = SL_RESULT_PARAMETER_INVALID;
+        break;
+    }
 
     interface_unlock_exclusive(this);
 
diff --git a/libopensles/IEngine.c b/libopensles/IEngine.c
index 69ac576..521e487 100644
--- a/libopensles/IEngine.c
+++ b/libopensles/IEngine.c
@@ -976,7 +976,7 @@
                             &this->mDataSource, DATALOCATOR_MASK_URI
 #ifdef ANDROID
                             | DATALOCATOR_MASK_ANDROIDFD
-                            // FIXME | DATALOCATOR_MASK_ANDROIDBUFFERQUEUE ???
+                            | DATALOCATOR_MASK_ANDROIDBUFFERQUEUE
 #endif
                             , DATAFORMAT_MASK_MIME);
                     if (XA_RESULT_SUCCESS != result) {
@@ -1038,7 +1038,7 @@
 
                     // platform-specific initialization
 #ifdef ANDROID
-                    // ...
+                    android_Player_create(this);
 #endif
 
                 } while (0);
diff --git a/libopensles/MPH_to.c b/libopensles/MPH_to.c
index fd6c7af..53cbf57 100644
--- a/libopensles/MPH_to.c
+++ b/libopensles/MPH_to.c
@@ -251,6 +251,7 @@
     [MPH_OBJECT] = 0,
     [MPH_DYNAMICINTERFACEMANAGEMENT] = 1,
     [MPH_XAPLAY] = 2,
+    [MPH_ANDROIDBUFFERQUEUE] = 3,
     // FIXME more TBD
 #else
 #include "MPH_to_MediaPlayer.h"
diff --git a/libopensles/OpenSLES_IID.c b/libopensles/OpenSLES_IID.c
index fcb4777..7f045b6 100644
--- a/libopensles/OpenSLES_IID.c
+++ b/libopensles/OpenSLES_IID.c
@@ -33,7 +33,8 @@
 #include "SLES/OpenSLES.h"         /* SL Header */
 #include "OMXAL/OpenMAXAL.h"
 #ifdef ANDROID
-#include "SLES/OpenSLES_Android.h" /* Android-specific SL Header */
+#include "SLES/OpenSLES_Android.h"  /* Android-specific SL Header */
+#include "OMXAL/OpenMAXAL_Android.h"/* Android-specific MAX AL Header */
 #endif
 #include "MPH.h"
 
@@ -171,6 +172,10 @@
     // XA_IID_PLAY
     { 0xb9c293e0, 0xf776, 0x11db, 0x80df, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } },
 
+// OpenMAX AL 1.0.1 Android API level 10 extended interfaces
+    // XA_IID_ANDROIDBUFFERQUEUE
+    // same as SL_IID_ANDROIDBUFFERQUEUE
+
 };
 
 #ifdef __cplusplus
@@ -242,6 +247,10 @@
 const XAInterfaceID XA_IID_ENGINE = (XAInterfaceID) &SL_IID_array[MPH_XAENGINE];
 const XAInterfaceID XA_IID_PLAY = (XAInterfaceID) &SL_IID_array[MPH_XAPLAY];
 
+// OpenMAX AL 1.0.1 Android API level 10 extended interfaces
+const XAInterfaceID XA_IID_ANDROIDBUFFERQUEUE =
+        (XAInterfaceID) &SL_IID_array[MPH_ANDROIDBUFFERQUEUE]; //same as SL
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/libopensles/android_AVPlayer.cpp b/libopensles/android_AVPlayer.cpp
index 24903c8..2076025 100644
--- a/libopensles/android_AVPlayer.cpp
+++ b/libopensles/android_AVPlayer.cpp
@@ -87,6 +87,7 @@
 }
 
 void AVPlayer::init() {
+    SL_LOGI("AVPlayer::init()");
     mLooper->registerHandler(this);
     mLooper->start(false /*runOnCallingThread*/, false /*canCallJava*/); // use default priority
 }
diff --git a/libopensles/android_AudioPlayer.cpp b/libopensles/android_AudioPlayer.cpp
index 0f0a367..73751ab 100644
--- a/libopensles/android_AudioPlayer.cpp
+++ b/libopensles/android_AudioPlayer.cpp
@@ -1563,8 +1563,11 @@
 
 //-----------------------------------------------------------------------------
 void android_audioPlayer_androidBufferQueue_registerCallback_l(CAudioPlayer *ap) {
-    if (ap->mAndroidObjType == STREAM_SOURCE) {
-        android_StreamPlayer_registerCallback_l(ap);
+    if ((ap->mAndroidObjType == STREAM_SOURCE) && (ap->mStreamPlayer != 0)) {
+        android_StreamPlayer_androidBufferQueue_registerCallback(ap->mStreamPlayer.get(),
+                ap->mAndroidBufferQueue.mCallback,
+                ap->mAndroidBufferQueue.mContext,
+                (const void*)&(ap->mAndroidBufferQueue.mItf));
     }
 }
 
diff --git a/libopensles/android_Player.cpp b/libopensles/android_Player.cpp
new file mode 100644
index 0000000..64fea87
--- /dev/null
+++ b/libopensles/android_Player.cpp
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "sles_allinclusive.h"
+#include "utils/RefBase.h"
+#include "android_prompts.h"
+
+
+//-----------------------------------------------------------------------------
+XAresult android_Player_create(CMediaPlayer *mp) {
+
+    XAresult result = XA_RESULT_SUCCESS;
+
+    // FIXME verify data source
+    const SLDataSource *pDataSrc = &mp->mDataSource.u.mSource;
+    // FIXME verify audio data sink
+    const SLDataSink *pAudioSnk = &mp->mAudioSink.u.mSink;
+    // FIXME verify image data sink
+    const SLDataSink *pVideoSnk = &mp->mImageVideoSink.u.mSink;
+
+    SLuint32 sourceLocator = *(SLuint32 *)pDataSrc->pLocator;
+    switch(sourceLocator) {
+    case SL_DATALOCATOR_ANDROIDBUFFERQUEUE:
+        break;
+    case SL_DATALOCATOR_URI: // intended fall-through
+    case SL_DATALOCATOR_ANDROIDFD: // intended fall-through
+    case SL_DATALOCATOR_BUFFERQUEUE: // intended fall-through
+    case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE: // intended fall-through
+    default:
+        SL_LOGE("Unable to create MediaPlayer for data source locator 0x%lx", sourceLocator);
+        result = XA_RESULT_PARAMETER_INVALID;
+        break;
+
+    }
+
+
+    // FIXME port all CAudioPlayer initialization to CMediaPlayer
+    // FIXME verify play state is correctly initialized
+/*
+    pAudioPlayer->mAndroidObjState = ANDROID_UNINITIALIZED;
+    pAudioPlayer->mStreamType = ANDROID_DEFAULT_OUTPUT_STREAM_TYPE;
+    pAudioPlayer->mAudioTrack = NULL;
+
+    pAudioPlayer->mSessionId = android::AudioSystem::newAudioSessionId();
+
+
+    pAudioPlayer->mAmplFromVolLevel = 1.0f;
+    pAudioPlayer->mAmplFromStereoPos[0] = 1.0f;
+    pAudioPlayer->mAmplFromStereoPos[1] = 1.0f;
+    pAudioPlayer->mDirectLevel = 0; // no attenuation
+    pAudioPlayer->mAmplFromDirectLevel = 1.0f; // matches initial mDirectLevel value
+    pAudioPlayer->mAuxSendLevel = 0;
+
+    // initialize interface-specific fields that can be used regardless of whether the interface
+    // is exposed on the AudioPlayer or not
+    // (section no longer applicable, as all previous initializations were the same as the defaults)
+*/
+    return result;
+}
+
+
+//-----------------------------------------------------------------------------
+// FIXME abstract out the diff between CMediaPlayer and CAudioPlayer
+XAresult android_Player_realize(CMediaPlayer *mp, SLboolean async) {
+    SL_LOGI("android_Player_realize_l(%p)", mp);
+    XAresult result = XA_RESULT_SUCCESS;
+
+    const SLDataSource *pDataSrc = &mp->mDataSource.u.mSource;
+    const SLuint32 sourceLocator = *(SLuint32 *)pDataSrc->pLocator;
+
+    AudioPlayback_Parameters ap_params;
+    ap_params.sessionId = 0;// FIXME mp->mSessionId;
+    ap_params.streamType = android::AudioSystem::MUSIC;// FIXME mp->mStreamType;
+    ap_params.trackcb = NULL;
+    ap_params.trackcbUser = NULL;
+
+    switch(sourceLocator) {
+    case SL_DATALOCATOR_ANDROIDBUFFERQUEUE: {
+        mp->mAVPlayer = new android::StreamPlayer(&ap_params);
+        mp->mAVPlayer->init();
+        }
+        break;
+    case SL_DATALOCATOR_URI: // intended fall-through
+    case SL_DATALOCATOR_ANDROIDFD: // intended fall-through
+    case SL_DATALOCATOR_BUFFERQUEUE: // intended fall-through
+    case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE: // intended fall-through
+    default:
+        SL_LOGE("Unable to realize MediaPlayer for data source locator 0x%lx", sourceLocator);
+        result = XA_RESULT_PARAMETER_INVALID;
+        break;
+
+    }
+
+    return result;
+}
+
+
+//-----------------------------------------------------------------------------
+// FIXME abstract out the diff between CMediaPlayer and CAudioPlayer
+XAresult android_Player_setPlayState(CMediaPlayer *mp, SLuint32 playState,
+        AndroidObject_state objState)
+{
+    XAresult result = XA_RESULT_SUCCESS;
+
+    switch (playState) {
+     case SL_PLAYSTATE_STOPPED: {
+         SL_LOGV("setting StreamPlayer to SL_PLAYSTATE_STOPPED");
+         if (mp->mAVPlayer != 0) {
+             mp->mAVPlayer->stop();
+         }
+     } break;
+     case SL_PLAYSTATE_PAUSED: {
+         SL_LOGV("setting StreamPlayer to SL_PLAYSTATE_PAUSED");
+         switch(objState) {
+         case(ANDROID_UNINITIALIZED):
+             if (mp->mAVPlayer != 0) {
+                 mp->mAVPlayer->prepare();
+             }
+         break;
+         case(ANDROID_PREPARING):
+             break;
+         case(ANDROID_READY):
+             if (mp->mAVPlayer != 0) {
+                 mp->mAVPlayer->pause();
+             }
+         break;
+         default:
+             break;
+         }
+     } break;
+     case SL_PLAYSTATE_PLAYING: {
+         SL_LOGV("setting StreamPlayer to SL_PLAYSTATE_PLAYING");
+         switch(objState) {
+         case(ANDROID_UNINITIALIZED):
+             // FIXME PRIORITY1 prepare should update the obj state
+             //  for the moment test app sets state to PAUSED to prepare, then to PLAYING
+             /*if (mp->mAVPlayer != 0) {
+                 mp->mAVPlayer->prepare();
+             }*/
+         // fall through
+         case(ANDROID_PREPARING):
+         case(ANDROID_READY):
+             if (mp->mAVPlayer != 0) {
+                 mp->mAVPlayer->play();
+             }
+         break;
+         default:
+             break;
+         }
+     } break;
+
+     default:
+         // checked by caller, should not happen
+         break;
+     }
+
+    return result;
+}
+
+
+//----------------------------------------------------------------
+// FIXME abstract out the diff between CMediaPlayer and CAudioPlayer
+void android_StreamPlayer_setPlayState(CAudioPlayer *ap, SLuint32 playState,
+        AndroidObject_state objState)
+{
+    switch (playState) {
+    case SL_PLAYSTATE_STOPPED: {
+        SL_LOGV("setting StreamPlayer to SL_PLAYSTATE_STOPPED");
+        if (ap->mStreamPlayer != 0) {
+            ap->mStreamPlayer->stop();
+        }
+    } break;
+    case SL_PLAYSTATE_PAUSED: {
+        SL_LOGV("setting StreamPlayer to SL_PLAYSTATE_PAUSED");
+        switch(objState) {
+        case(ANDROID_UNINITIALIZED):
+            if (ap->mStreamPlayer != 0) {
+                ap->mStreamPlayer->prepare();
+            }
+        break;
+        case(ANDROID_PREPARING):
+            break;
+        case(ANDROID_READY):
+            if (ap->mStreamPlayer != 0) {
+                ap->mStreamPlayer->pause();
+            }
+        break;
+        default:
+            break;
+        }
+    } break;
+    case SL_PLAYSTATE_PLAYING: {
+        SL_LOGV("setting StreamPlayer to SL_PLAYSTATE_PLAYING");
+        switch(objState) {
+        case(ANDROID_UNINITIALIZED):
+            // FIXME PRIORITY1 prepare should update the obj state
+            //  for the moment test app sets state to PAUSED to prepare, then to PLAYING
+            /*if (ap->mStreamPlayer != 0) {
+                ap->mStreamPlayer->prepare();
+            }*/
+        // fall through
+        case(ANDROID_PREPARING):
+        case(ANDROID_READY):
+            if (ap->mStreamPlayer != 0) {
+                ap->mStreamPlayer->play();
+            }
+        break;
+        default:
+            break;
+        }
+    } break;
+
+    default:
+        // checked by caller, should not happen
+        break;
+    }
+}
+
+
+//-----------------------------------------------------------------------------
+// FIXME abstract out the diff between CMediaPlayer and CAudioPlayer
+void android_Player_androidBufferQueue_registerCallback_l(CMediaPlayer *mp) {
+    if (mp->mAVPlayer != 0) {
+        SL_LOGI("android_Player_androidBufferQueue_registerCallback_l");
+        android::StreamPlayer* splr = (android::StreamPlayer*)(mp->mAVPlayer.get());
+        splr->registerQueueCallback(mp->mAndroidBufferQueue.mCallback,
+                mp->mAndroidBufferQueue.mContext, (const void*)&(mp->mAndroidBufferQueue.mItf));
+    }
+}
+
+// FIXME abstract out the diff between CMediaPlayer and CAudioPlayer
+void android_Player_androidBufferQueue_enqueue_l(CMediaPlayer *mp,
+        SLuint32 bufferId, SLuint32 length, SLAbufferQueueEvent event, void *pData) {
+    if (mp->mAVPlayer != 0) {
+        android::StreamPlayer* splr = (android::StreamPlayer*)(mp->mAVPlayer.get());
+        splr->appEnqueue(bufferId, length, event, pData);
+    }
+}
+
+
+
diff --git a/libopensles/android_Player.h b/libopensles/android_Player.h
new file mode 100644
index 0000000..46254c7
--- /dev/null
+++ b/libopensles/android_Player.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+/**************************************************************************************************
+ * Player lifecycle
+ ****************************/
+
+extern XAresult android_Player_create(CMediaPlayer *mp);
+
+extern XAresult android_Player_realize(CMediaPlayer *mp, SLboolean async);
+
+
+/**************************************************************************************************
+ * Configuration
+ ****************************/
+
+
+/**************************************************************************************************
+ * Playback control and events
+ ****************************/
+extern XAresult android_Player_setPlayState(CMediaPlayer *mp, SLuint32 playState,
+        AndroidObject_state objState);
+
+
+
+/**************************************************************************************************
+ * Buffer Queue events
+ ****************************/
+
+/**************************************************************************************************
+ * Android Buffer Queue
+ ****************************/
+
+/* must be called with a lock on mp->mThis */
+extern void android_Player_androidBufferQueue_registerCallback_l(CMediaPlayer *mp);
+/* must be called with a lock on mp->mThis */
+extern void android_Player_androidBufferQueue_enqueue_l(CMediaPlayer *mp,
+        SLuint32 bufferId, SLuint32 length, SLAbufferQueueEvent event, void *pData);
diff --git a/libopensles/android_StreamPlayer.cpp b/libopensles/android_StreamPlayer.cpp
index 3c19be3..5ba684e 100644
--- a/libopensles/android_StreamPlayer.cpp
+++ b/libopensles/android_StreamPlayer.cpp
@@ -20,7 +20,8 @@
 #undef this // FIXME shouldn't have to do this, no pun intended
 #include <media/IMediaPlayerService.h>
 
-//----------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+// FIXME abstract out the diff between CMediaPlayer and CAudioPlayer
 void android_StreamPlayer_realize_l(CAudioPlayer *ap) {
     SL_LOGI("android_StreamPlayer_realize_l(%p)", ap);
 
@@ -34,6 +35,7 @@
 }
 
 
+// FIXME abstract out the diff between CMediaPlayer and CAudioPlayer
 void android_StreamPlayer_destroy(CAudioPlayer *ap) {
     SL_LOGI("android_StreamPlayer_destroy(%p)", ap);
 
@@ -41,71 +43,17 @@
 }
 
 
-void android_StreamPlayer_setPlayState(CAudioPlayer *ap, SLuint32 playState,
-        AndroidObject_state objState)
+//-----------------------------------------------------------------------------
+void android_StreamPlayer_androidBufferQueue_registerCallback(android::StreamPlayer *splr,
+        slAndroidBufferQueueCallback callback, void* context, const void* callerItf)
 {
-    switch (playState) {
-    case SL_PLAYSTATE_STOPPED: {
-        SL_LOGV("setting StreamPlayer to SL_PLAYSTATE_STOPPED");
-        if (ap->mStreamPlayer != 0) {
-            ap->mStreamPlayer->stop();
-        }
-    } break;
-    case SL_PLAYSTATE_PAUSED: {
-        SL_LOGV("setting StreamPlayer to SL_PLAYSTATE_PAUSED");
-        switch(objState) {
-        case(ANDROID_UNINITIALIZED):
-            if (ap->mStreamPlayer != 0) {
-                ap->mStreamPlayer->prepare();
-            }
-        break;
-        case(ANDROID_PREPARING):
-            break;
-        case(ANDROID_READY):
-            if (ap->mStreamPlayer != 0) {
-                ap->mStreamPlayer->pause();
-            }
-        break;
-        default:
-            break;
-        }
-    } break;
-    case SL_PLAYSTATE_PLAYING: {
-        SL_LOGV("setting StreamPlayer to SL_PLAYSTATE_PLAYING");
-        switch(objState) {
-        case(ANDROID_UNINITIALIZED):
-            // FIXME PRIORITY1 prepare should update the obj state
-            //  for the moment test app sets state to PAUSED to prepare, then to PLAYING
-            /*if (ap->mStreamPlayer != 0) {
-                ap->mStreamPlayer->prepare();
-            }*/
-        // fall through
-        case(ANDROID_PREPARING):
-        case(ANDROID_READY):
-            if (ap->mStreamPlayer != 0) {
-                ap->mStreamPlayer->play();
-            }
-        break;
-        default:
-            break;
-        }
-    } break;
-
-    default:
-        // checked by caller, should not happen
-        break;
+    if (splr != NULL) {
+        SL_LOGI("android_Player_androidBufferQueue_registerCallback");
+        splr->registerQueueCallback(callback, context, callerItf);
     }
 }
 
-
-void android_StreamPlayer_registerCallback_l(CAudioPlayer *ap) {
-    if (ap->mStreamPlayer != 0) {
-        ap->mStreamPlayer->appRegisterCallback(ap->mAndroidBufferQueue.mCallback,
-                ap->mAndroidBufferQueue.mContext, (const void*)&(ap->mAndroidBufferQueue.mItf));
-    }
-}
-
-
+// FIXME abstract out the diff between CMediaPlayer and CAudioPlayer
 void android_StreamPlayer_enqueue_l(CAudioPlayer *ap,
         SLuint32 bufferId, SLuint32 length, SLAbufferQueueEvent event, void *pData) {
     if (ap->mStreamPlayer != 0) {
@@ -114,27 +62,27 @@
 }
 
 
+// FIXME abstract out the diff between CMediaPlayer and CAudioPlayer
 void android_StreamPlayer_clear_l(CAudioPlayer *ap) {
     if (ap->mStreamPlayer != 0) {
         ap->mStreamPlayer->appClear();
     }
 }
 
-
+//--------------------------------------------------------------------------------------------------
 namespace android {
 
-//--------------------------------------------------------------------------------------------------
 StreamSourceAppProxy::StreamSourceAppProxy(
         slAndroidBufferQueueCallback callback, void *context, const void *caller) :
     mCallback(callback),
     mAppContext(context),
     mCaller(caller)
 {
-    SL_LOGV("StreamSourceAppProxy::StreamSourceAppProxy()");
+    SL_LOGI("StreamSourceAppProxy::StreamSourceAppProxy()");
 }
 
 StreamSourceAppProxy::~StreamSourceAppProxy() {
-    SL_LOGV("StreamSourceAppProxy::~StreamSourceAppProxy()");
+    SL_LOGI("StreamSourceAppProxy::~StreamSourceAppProxy()");
     mListener.clear();
     mBuffers.clear();
 }
@@ -186,7 +134,7 @@
 StreamPlayer::StreamPlayer(AudioPlayback_Parameters* params) : AVPlayer(params),
     mAppProxy(0)
 {
-    SL_LOGV("StreamPlayer::StreamPlayer()");
+    SL_LOGI("StreamPlayer::StreamPlayer()");
 
     mPlaybackParams = *params;
 
@@ -199,16 +147,19 @@
 }
 
 void StreamPlayer::init() {
+    SL_LOGI("StreamPlayer::init()");
     AVPlayer::init();
 }
 
-void StreamPlayer::appRegisterCallback(slAndroidBufferQueueCallback callback, void *context,
+void StreamPlayer::registerQueueCallback(slAndroidBufferQueueCallback callback, void *context,
         const void *caller) {
+    SL_LOGI("StreamPlayer::registerQueueCallback");
     Mutex::Autolock _l(mLock);
 
     mAppProxy = new StreamSourceAppProxy(callback, context, caller);
 
     CHECK(mAppProxy != 0);
+    SL_LOGI("StreamPlayer::registerQueueCallback end");
 }
 
 void StreamPlayer::appEnqueue(SLuint32 bufferId, SLuint32 length, SLAbufferQueueEvent event,
@@ -243,13 +194,16 @@
 // Event handlers
 void StreamPlayer::onPrepare() {
     SL_LOGI("StreamPlayer::onPrepare()");
-    mPlayer = mMediaPlayerService->create(getpid(), mPlayerClient /*IMediaPlayerClient*/,
-            mAppProxy /*IStreamSource*/, mPlaybackParams.sessionId);
-    SL_LOGI("StreamPlayer::onPrepare() after mMediaPlayerService->create()");
-
-    // blocks until mPlayer is prepared
-    AVPlayer::onPrepare();
-    SL_LOGI("StreamPlayer::onPrepare() done");
+    //Mutex::Autolock _l(mLock);
+    if (mAppProxy != 0) {
+        mPlayer = mMediaPlayerService->create(getpid(), mPlayerClient /*IMediaPlayerClient*/,
+                mAppProxy /*IStreamSource*/, mPlaybackParams.sessionId);
+        // blocks until mPlayer is prepared
+        AVPlayer::onPrepare();
+        SL_LOGI("StreamPlayer::onPrepare() done");
+    } else {
+        SL_LOGE("Nothing to do here because there is no registered callback");
+    }
 }
 
 
diff --git a/libopensles/android_StreamPlayer.h b/libopensles/android_StreamPlayer.h
index fcaef8d..e4e53d9 100644
--- a/libopensles/android_StreamPlayer.h
+++ b/libopensles/android_StreamPlayer.h
@@ -16,31 +16,12 @@
 
 #include <binder/IServiceManager.h>
 
-//--------------------------------------------------------------------------------------------------
-// FIXME move to mediaplayer.h
-enum media_player_stream_origin {
-    MEDIA_PLAYER_STREAM_ORIGIN_INVALID           = 0,
-    MEDIA_PLAYER_STREAM_ORIGIN_FILE              = 1 << 0,
-    MEDIA_PLAYER_STREAM_ORIGIN_TRANSPORT_STREAM  = 1 << 1
-};
 
 typedef struct StreamPlayback_Parameters_struct {
     int streamType;
     int sessionId;
 } StreamPlayback_Parameters;
 
-//--------------------------------------------------------------------------------------------------
-/*
- * xxx_l functions are called with a lock on the CAudioPlayer mObject
- */
-extern void android_StreamPlayer_realize_l(CAudioPlayer *ap);
-extern void android_StreamPlayer_destroy(CAudioPlayer *ap);
-extern void android_StreamPlayer_setPlayState(CAudioPlayer *ap, SLuint32 playState,
-        AndroidObject_state objState);
-extern void android_StreamPlayer_registerCallback_l(CAudioPlayer *ap);
-extern void android_StreamPlayer_enqueue_l(CAudioPlayer *ap,
-        SLuint32 bufferId, SLuint32 length, SLAbufferQueueEvent event, void *pData);
-extern void android_StreamPlayer_clear_l(CAudioPlayer *ap);
 
 //--------------------------------------------------------------------------------------------------
 namespace android {
@@ -84,7 +65,7 @@
     virtual void init();
 
 
-    void appRegisterCallback(slAndroidBufferQueueCallback callback, void *context,
+    void registerQueueCallback(slAndroidBufferQueueCallback callback, void *context,
             const void *caller);
     void appEnqueue(SLuint32 bufferId, SLuint32 length, SLAbufferQueueEvent event, void *pData);
     void appClear();
@@ -100,3 +81,19 @@
 };
 
 } // namespace android
+
+
+//--------------------------------------------------------------------------------------------------
+/*
+ * xxx_l functions are called with a lock on the CAudioPlayer mObject
+ */
+extern void android_StreamPlayer_realize_l(CAudioPlayer *ap);
+extern void android_StreamPlayer_destroy(CAudioPlayer *ap);
+extern void android_StreamPlayer_setPlayState(CAudioPlayer *ap, SLuint32 playState,
+        AndroidObject_state objState);
+extern void android_StreamPlayer_androidBufferQueue_registerCallback(
+        android::StreamPlayer *splr,
+        slAndroidBufferQueueCallback callback, void* context, const void* callerItf);
+extern void android_StreamPlayer_enqueue_l(CAudioPlayer *ap,
+        SLuint32 bufferId, SLuint32 length, SLAbufferQueueEvent event, void *pData);
+extern void android_StreamPlayer_clear_l(CAudioPlayer *ap);
diff --git a/libopensles/classes.c b/libopensles/classes.c
index 79fccbc..1ca0a52 100644
--- a/libopensles/classes.c
+++ b/libopensles/classes.c
@@ -405,6 +405,7 @@
     {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT,
         offsetof(CMediaPlayer, mDynamicInterfaceManagement)},
     {MPH_XAPLAY, INTERFACE_IMPLICIT, offsetof(CMediaPlayer, mPlay)},
+    {MPH_ANDROIDBUFFERQUEUE, INTERFACE_EXPLICIT, offsetof(CMediaPlayer, mAndroidBufferQueue)},
 };
 
 static const ClassTable CMediaPlayer_class = {
diff --git a/libopensles/classes.h b/libopensles/classes.h
index 4703bea..e339747 100644
--- a/libopensles/classes.h
+++ b/libopensles/classes.h
@@ -299,10 +299,13 @@
 
 typedef struct CMediaPlayer_struct {
     IObject mObject;
-#define INTERFACES_MediaPlayer 3
+#define INTERFACES_MediaPlayer 4
     XAuint8 mInterfaceStates2[INTERFACES_MediaPlayer - INTERFACES_Default];
     IDynamicInterfaceManagement mDynamicInterfaceManagement;
     IPlay mPlay;
+#ifdef ANDROID
+    IAndroidBufferQueue mAndroidBufferQueue;
+#endif
     // ...
     DataLocatorFormat mDataSource;
     DataLocatorFormat mBankSource;
@@ -311,6 +314,7 @@
     DataLocatorFormat mVibraSink;
     DataLocatorFormat mLEDArraySink;
 #ifdef ANDROID
-    android::sp<android::IMediaPlayer> mPlayer;
+    //android::sp<android::IMediaPlayer> mPlayer;
+    android::sp<android::AVPlayer> mAVPlayer;
 #endif
 } CMediaPlayer;
diff --git a/libopensles/locks.c b/libopensles/locks.c
index 62a3a71..4d66cc3 100644
--- a/libopensles/locks.c
+++ b/libopensles/locks.c
@@ -192,21 +192,10 @@
             {
             attributes &= ~ATTR_TRANSPORT;   // no need to process asynchronously also
             CMediaPlayer *mp = (CMediaPlayer *) this;
-            // CMediaPlayer_setPlayState(mp);
-            android::sp<android::IMediaPlayer> player = mp->mPlayer;
-            if (player != NULL) {
-                switch (mp->mPlay.mState) {
-                case XA_PLAYSTATE_PLAYING:
-                    player->start();
-                    break;
-                case XA_PLAYSTATE_PAUSED:
-                case XA_PLAYSTATE_STOPPED:
-                    player->stop();
-                    break;
-                default:
-                    break;
-                }
-            }
+            SLuint32 playState = mp->mPlay.mState;
+            // FIXME use object state
+            //AndroidObject_state objState = mp->mAndroidObjState;
+            android_Player_setPlayState(mp, playState, ANDROID_UNINITIALIZED);
             }
 #endif
             break;
diff --git a/libopensles/sles_allinclusive.h b/libopensles/sles_allinclusive.h
index c70a0f5..04bd06a 100644
--- a/libopensles/sles_allinclusive.h
+++ b/libopensles/sles_allinclusive.h
@@ -323,6 +323,7 @@
 #define InterfaceToCAudioRecorder(this) (((CAudioRecorder*)InterfaceToIObject(this)))
 
 #ifdef ANDROID
+#include "android_Player.h"
 #include "android_AudioPlayer.h"
 #endif