MediaPlayer2: remove MediaPlayer2Engine

Test: MediaPlayer2 plays
Bug: 63934228
Change-Id: I2459082bf6bbe2384ed94901b1f8f28559345888
diff --git a/media/libmediaplayer2/Android.bp b/media/libmediaplayer2/Android.bp
index 17fa01c..1fa8789 100644
--- a/media/libmediaplayer2/Android.bp
+++ b/media/libmediaplayer2/Android.bp
@@ -9,7 +9,7 @@
 
     srcs: [
         "JAudioTrack.cpp",
-        "MediaPlayer2Manager.cpp",
+        "MediaPlayer2AudioOutput.cpp",
         "mediaplayer2.cpp",
     ],
 
diff --git a/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp b/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp
new file mode 100644
index 0000000..a8e1d1f
--- /dev/null
+++ b/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp
@@ -0,0 +1,727 @@
+/*
+**
+** Copyright 2018, 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 "MediaPlayer2AudioOutput"
+#include <mediaplayer2/MediaPlayer2AudioOutput.h>
+
+#include <cutils/properties.h> // for property_get
+#include <utils/Log.h>
+
+#include <media/AudioPolicyHelper.h>
+#include <media/AudioTrack.h>
+#include <media/stagefright/foundation/ADebug.h>
+
+namespace {
+
+const float kMaxRequiredSpeed = 8.0f; // for PCM tracks allow up to 8x speedup.
+
+} // anonymous namespace
+
+namespace android {
+
+// TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
+/* static */ int MediaPlayer2AudioOutput::mMinBufferCount = 4;
+/* static */ bool MediaPlayer2AudioOutput::mIsOnEmulator = false;
+
+status_t MediaPlayer2AudioOutput::dump(int fd, const Vector<String16>& args) const {
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    result.append(" MediaPlayer2AudioOutput\n");
+    snprintf(buffer, 255, "  stream type(%d), left - right volume(%f, %f)\n",
+            mStreamType, mLeftVolume, mRightVolume);
+    result.append(buffer);
+    snprintf(buffer, 255, "  msec per frame(%f), latency (%d)\n",
+            mMsecsPerFrame, (mTrack != 0) ? mTrack->latency() : -1);
+    result.append(buffer);
+    snprintf(buffer, 255, "  aux effect id(%d), send level (%f)\n",
+            mAuxEffectId, mSendLevel);
+    result.append(buffer);
+
+    ::write(fd, result.string(), result.size());
+    if (mTrack != 0) {
+        mTrack->dump(fd, args);
+    }
+    return NO_ERROR;
+}
+
+MediaPlayer2AudioOutput::MediaPlayer2AudioOutput(audio_session_t sessionId, uid_t uid, int pid,
+        const audio_attributes_t* attr, const sp<AudioSystem::AudioDeviceCallback>& deviceCallback)
+    : mCallback(NULL),
+      mCallbackCookie(NULL),
+      mCallbackData(NULL),
+      mStreamType(AUDIO_STREAM_MUSIC),
+      mLeftVolume(1.0),
+      mRightVolume(1.0),
+      mPlaybackRate(AUDIO_PLAYBACK_RATE_DEFAULT),
+      mSampleRateHz(0),
+      mMsecsPerFrame(0),
+      mFrameSize(0),
+      mSessionId(sessionId),
+      mUid(uid),
+      mPid(pid),
+      mSendLevel(0.0),
+      mAuxEffectId(0),
+      mFlags(AUDIO_OUTPUT_FLAG_NONE),
+      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
+      mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE),
+      mDeviceCallbackEnabled(false),
+      mDeviceCallback(deviceCallback) {
+    ALOGV("MediaPlayer2AudioOutput(%d)", sessionId);
+    if (attr != NULL) {
+        mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
+        if (mAttributes != NULL) {
+            memcpy(mAttributes, attr, sizeof(audio_attributes_t));
+            mStreamType = audio_attributes_to_stream_type(attr);
+        }
+    } else {
+        mAttributes = NULL;
+    }
+
+    setMinBufferCount();
+}
+
+MediaPlayer2AudioOutput::~MediaPlayer2AudioOutput() {
+    close();
+    free(mAttributes);
+    delete mCallbackData;
+}
+
+//static
+void MediaPlayer2AudioOutput::setMinBufferCount() {
+    char value[PROPERTY_VALUE_MAX];
+    if (property_get("ro.kernel.qemu", value, 0)) {
+        mIsOnEmulator = true;
+        mMinBufferCount = 12;  // to prevent systematic buffer underrun for emulator
+    }
+}
+
+// static
+bool MediaPlayer2AudioOutput::isOnEmulator() {
+    setMinBufferCount();  // benign race wrt other threads
+    return mIsOnEmulator;
+}
+
+// static
+int MediaPlayer2AudioOutput::getMinBufferCount() {
+    setMinBufferCount();  // benign race wrt other threads
+    return mMinBufferCount;
+}
+
+ssize_t MediaPlayer2AudioOutput::bufferSize() const {
+    Mutex::Autolock lock(mLock);
+    if (mTrack == 0) {
+        return NO_INIT;
+    }
+    return mTrack->frameCount() * mFrameSize;
+}
+
+ssize_t MediaPlayer2AudioOutput::frameCount() const {
+    Mutex::Autolock lock(mLock);
+    if (mTrack == 0) {
+        return NO_INIT;
+    }
+    return mTrack->frameCount();
+}
+
+ssize_t MediaPlayer2AudioOutput::channelCount() const {
+    Mutex::Autolock lock(mLock);
+    if (mTrack == 0) {
+        return NO_INIT;
+    }
+    return mTrack->channelCount();
+}
+
+ssize_t MediaPlayer2AudioOutput::frameSize() const {
+    Mutex::Autolock lock(mLock);
+    if (mTrack == 0) {
+        return NO_INIT;
+    }
+    return mFrameSize;
+}
+
+uint32_t MediaPlayer2AudioOutput::latency () const {
+    Mutex::Autolock lock(mLock);
+    if (mTrack == 0) {
+        return 0;
+    }
+    return mTrack->latency();
+}
+
+float MediaPlayer2AudioOutput::msecsPerFrame() const {
+    Mutex::Autolock lock(mLock);
+    return mMsecsPerFrame;
+}
+
+status_t MediaPlayer2AudioOutput::getPosition(uint32_t *position) const {
+    Mutex::Autolock lock(mLock);
+    if (mTrack == 0) {
+        return NO_INIT;
+    }
+    return mTrack->getPosition(position);
+}
+
+status_t MediaPlayer2AudioOutput::getTimestamp(AudioTimestamp &ts) const {
+    Mutex::Autolock lock(mLock);
+    if (mTrack == 0) {
+        return NO_INIT;
+    }
+    return mTrack->getTimestamp(ts);
+}
+
+// TODO: Remove unnecessary calls to getPlayedOutDurationUs()
+// as it acquires locks and may query the audio driver.
+//
+// Some calls could conceivably retrieve extrapolated data instead of
+// accessing getTimestamp() or getPosition() every time a data buffer with
+// a media time is received.
+//
+// Calculate duration of played samples if played at normal rate (i.e., 1.0).
+int64_t MediaPlayer2AudioOutput::getPlayedOutDurationUs(int64_t nowUs) const {
+    Mutex::Autolock lock(mLock);
+    if (mTrack == 0 || mSampleRateHz == 0) {
+        return 0;
+    }
+
+    uint32_t numFramesPlayed;
+    int64_t numFramesPlayedAtUs;
+    AudioTimestamp ts;
+
+    status_t res = mTrack->getTimestamp(ts);
+    if (res == OK) {                 // case 1: mixing audio tracks and offloaded tracks.
+        numFramesPlayed = ts.mPosition;
+        numFramesPlayedAtUs = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000;
+        //ALOGD("getTimestamp: OK %d %lld", numFramesPlayed, (long long)numFramesPlayedAtUs);
+    } else if (res == WOULD_BLOCK) { // case 2: transitory state on start of a new track
+        numFramesPlayed = 0;
+        numFramesPlayedAtUs = nowUs;
+        //ALOGD("getTimestamp: WOULD_BLOCK %d %lld",
+        //        numFramesPlayed, (long long)numFramesPlayedAtUs);
+    } else {                         // case 3: transitory at new track or audio fast tracks.
+        res = mTrack->getPosition(&numFramesPlayed);
+        CHECK_EQ(res, (status_t)OK);
+        numFramesPlayedAtUs = nowUs;
+        numFramesPlayedAtUs += 1000LL * mTrack->latency() / 2; /* XXX */
+        //ALOGD("getPosition: %u %lld", numFramesPlayed, (long long)numFramesPlayedAtUs);
+    }
+
+    // CHECK_EQ(numFramesPlayed & (1 << 31), 0);  // can't be negative until 12.4 hrs, test
+    // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
+    int64_t durationUs = (int64_t)((int32_t)numFramesPlayed * 1000000LL / mSampleRateHz)
+            + nowUs - numFramesPlayedAtUs;
+    if (durationUs < 0) {
+        // Occurs when numFramesPlayed position is very small and the following:
+        // (1) In case 1, the time nowUs is computed before getTimestamp() is called and
+        //     numFramesPlayedAtUs is greater than nowUs by time more than numFramesPlayed.
+        // (2) In case 3, using getPosition and adding mAudioSink->latency() to
+        //     numFramesPlayedAtUs, by a time amount greater than numFramesPlayed.
+        //
+        // Both of these are transitory conditions.
+        ALOGV("getPlayedOutDurationUs: negative duration %lld set to zero", (long long)durationUs);
+        durationUs = 0;
+    }
+    ALOGV("getPlayedOutDurationUs(%lld) nowUs(%lld) frames(%u) framesAt(%lld)",
+            (long long)durationUs, (long long)nowUs,
+            numFramesPlayed, (long long)numFramesPlayedAtUs);
+    return durationUs;
+}
+
+status_t MediaPlayer2AudioOutput::getFramesWritten(uint32_t *frameswritten) const {
+    Mutex::Autolock lock(mLock);
+    if (mTrack == 0) {
+        return NO_INIT;
+    }
+    ExtendedTimestamp ets;
+    status_t status = mTrack->getTimestamp(&ets);
+    if (status == OK || status == WOULD_BLOCK) {
+        *frameswritten = (uint32_t)ets.mPosition[ExtendedTimestamp::LOCATION_CLIENT];
+    }
+    return status;
+}
+
+status_t MediaPlayer2AudioOutput::setParameters(const String8& keyValuePairs) {
+    Mutex::Autolock lock(mLock);
+    if (mTrack == 0) {
+        return NO_INIT;
+    }
+    return mTrack->setParameters(keyValuePairs);
+}
+
+String8  MediaPlayer2AudioOutput::getParameters(const String8& keys) {
+    Mutex::Autolock lock(mLock);
+    if (mTrack == 0) {
+        return String8::empty();
+    }
+    return mTrack->getParameters(keys);
+}
+
+void MediaPlayer2AudioOutput::setAudioAttributes(const audio_attributes_t * attributes) {
+    Mutex::Autolock lock(mLock);
+    if (attributes == NULL) {
+        free(mAttributes);
+        mAttributes = NULL;
+    } else {
+        if (mAttributes == NULL) {
+            mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
+        }
+        memcpy(mAttributes, attributes, sizeof(audio_attributes_t));
+        mStreamType = audio_attributes_to_stream_type(attributes);
+    }
+}
+
+void MediaPlayer2AudioOutput::setAudioStreamType(audio_stream_type_t streamType) {
+    Mutex::Autolock lock(mLock);
+    // do not allow direct stream type modification if attributes have been set
+    if (mAttributes == NULL) {
+        mStreamType = streamType;
+    }
+}
+
+void MediaPlayer2AudioOutput::close_l() {
+    mTrack.clear();
+}
+
+status_t MediaPlayer2AudioOutput::open(
+        uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
+        audio_format_t format, int bufferCount,
+        AudioCallback cb, void *cookie,
+        audio_output_flags_t flags,
+        const audio_offload_info_t *offloadInfo,
+        bool doNotReconnect,
+        uint32_t suggestedFrameCount) {
+    ALOGV("open(%u, %d, 0x%x, 0x%x, %d, %d 0x%x)", sampleRate, channelCount, channelMask,
+                format, bufferCount, mSessionId, flags);
+
+    // offloading is only supported in callback mode for now.
+    // offloadInfo must be present if offload flag is set
+    if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) &&
+            ((cb == NULL) || (offloadInfo == NULL))) {
+        return BAD_VALUE;
+    }
+
+    // compute frame count for the AudioTrack internal buffer
+    size_t frameCount;
+    if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
+        frameCount = 0; // AudioTrack will get frame count from AudioFlinger
+    } else {
+        // try to estimate the buffer processing fetch size from AudioFlinger.
+        // framesPerBuffer is approximate and generally correct, except when it's not :-).
+        uint32_t afSampleRate;
+        size_t afFrameCount;
+        if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
+            return NO_INIT;
+        }
+        if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
+            return NO_INIT;
+        }
+        const size_t framesPerBuffer =
+                (unsigned long long)sampleRate * afFrameCount / afSampleRate;
+
+        if (bufferCount == 0) {
+            // use suggestedFrameCount
+            bufferCount = (suggestedFrameCount + framesPerBuffer - 1) / framesPerBuffer;
+        }
+        // Check argument bufferCount against the mininum buffer count
+        if (bufferCount != 0 && bufferCount < mMinBufferCount) {
+            ALOGV("bufferCount (%d) increased to %d", bufferCount, mMinBufferCount);
+            bufferCount = mMinBufferCount;
+        }
+        // if frameCount is 0, then AudioTrack will get frame count from AudioFlinger
+        // which will be the minimum size permitted.
+        frameCount = bufferCount * framesPerBuffer;
+    }
+
+    if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
+        channelMask = audio_channel_out_mask_from_count(channelCount);
+        if (0 == channelMask) {
+            ALOGE("open() error, can\'t derive mask for %d audio channels", channelCount);
+            return NO_INIT;
+        }
+    }
+
+    Mutex::Autolock lock(mLock);
+    mCallback = cb;
+    mCallbackCookie = cookie;
+
+    sp<AudioTrack> t;
+    CallbackData *newcbd = NULL;
+
+    ALOGV("creating new AudioTrack");
+
+    if (mCallback != NULL) {
+        newcbd = new CallbackData(this);
+        t = new AudioTrack(
+                mStreamType,
+                sampleRate,
+                format,
+                channelMask,
+                frameCount,
+                flags,
+                CallbackWrapper,
+                newcbd,
+                0,  // notification frames
+                mSessionId,
+                AudioTrack::TRANSFER_CALLBACK,
+                offloadInfo,
+                mUid,
+                mPid,
+                mAttributes,
+                doNotReconnect,
+                1.0f,  // default value for maxRequiredSpeed
+                mSelectedDeviceId);
+    } else {
+        // TODO: Due to buffer memory concerns, we use a max target playback speed
+        // based on mPlaybackRate at the time of open (instead of kMaxRequiredSpeed),
+        // also clamping the target speed to 1.0 <= targetSpeed <= kMaxRequiredSpeed.
+        const float targetSpeed =
+                std::min(std::max(mPlaybackRate.mSpeed, 1.0f), kMaxRequiredSpeed);
+        ALOGW_IF(targetSpeed != mPlaybackRate.mSpeed,
+                "track target speed:%f clamped from playback speed:%f",
+                targetSpeed, mPlaybackRate.mSpeed);
+        t = new AudioTrack(
+                mStreamType,
+                sampleRate,
+                format,
+                channelMask,
+                frameCount,
+                flags,
+                NULL, // callback
+                NULL, // user data
+                0, // notification frames
+                mSessionId,
+                AudioTrack::TRANSFER_DEFAULT,
+                NULL, // offload info
+                mUid,
+                mPid,
+                mAttributes,
+                doNotReconnect,
+                targetSpeed,
+                mSelectedDeviceId);
+    }
+
+    if ((t == 0) || (t->initCheck() != NO_ERROR)) {
+        ALOGE("Unable to create audio track");
+        delete newcbd;
+        // t goes out of scope, so reference count drops to zero
+        return NO_INIT;
+    } else {
+        // successful AudioTrack initialization implies a legacy stream type was generated
+        // from the audio attributes
+        mStreamType = t->streamType();
+    }
+
+    CHECK((t != NULL) && ((mCallback == NULL) || (newcbd != NULL)));
+
+    mCallbackData = newcbd;
+    ALOGV("setVolume");
+    t->setVolume(mLeftVolume, mRightVolume);
+
+    mSampleRateHz = sampleRate;
+    mFlags = flags;
+    mMsecsPerFrame = 1E3f / (mPlaybackRate.mSpeed * sampleRate);
+    mFrameSize = t->frameSize();
+    mTrack = t;
+
+    return updateTrack_l();
+}
+
+status_t MediaPlayer2AudioOutput::updateTrack_l() {
+    if (mTrack == NULL) {
+        return NO_ERROR;
+    }
+
+    status_t res = NO_ERROR;
+    // Note some output devices may give us a direct track even though we don't specify it.
+    // Example: Line application b/17459982.
+    if ((mTrack->getFlags()
+            & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT)) == 0) {
+        res = mTrack->setPlaybackRate(mPlaybackRate);
+        if (res == NO_ERROR) {
+            mTrack->setAuxEffectSendLevel(mSendLevel);
+            res = mTrack->attachAuxEffect(mAuxEffectId);
+        }
+    }
+    mTrack->setOutputDevice(mSelectedDeviceId);
+    if (mDeviceCallbackEnabled) {
+        mTrack->addAudioDeviceCallback(mDeviceCallback.promote());
+    }
+    ALOGV("updateTrack_l() DONE status %d", res);
+    return res;
+}
+
+status_t MediaPlayer2AudioOutput::start() {
+    ALOGV("start");
+    Mutex::Autolock lock(mLock);
+    if (mCallbackData != NULL) {
+        mCallbackData->endTrackSwitch();
+    }
+    if (mTrack != 0) {
+        mTrack->setVolume(mLeftVolume, mRightVolume);
+        mTrack->setAuxEffectSendLevel(mSendLevel);
+        status_t status = mTrack->start();
+        return status;
+    }
+    return NO_INIT;
+}
+
+ssize_t MediaPlayer2AudioOutput::write(const void* buffer, size_t size, bool blocking) {
+    Mutex::Autolock lock(mLock);
+    LOG_ALWAYS_FATAL_IF(mCallback != NULL, "Don't call write if supplying a callback.");
+
+    //ALOGV("write(%p, %u)", buffer, size);
+    if (mTrack != 0) {
+        return mTrack->write(buffer, size, blocking);
+    }
+    return NO_INIT;
+}
+
+void MediaPlayer2AudioOutput::stop() {
+    ALOGV("stop");
+    Mutex::Autolock lock(mLock);
+    if (mTrack != 0) {
+        mTrack->stop();
+    }
+}
+
+void MediaPlayer2AudioOutput::flush() {
+    ALOGV("flush");
+    Mutex::Autolock lock(mLock);
+    if (mTrack != 0) {
+        mTrack->flush();
+    }
+}
+
+void MediaPlayer2AudioOutput::pause() {
+    ALOGV("pause");
+    Mutex::Autolock lock(mLock);
+    if (mTrack != 0) {
+        mTrack->pause();
+    }
+}
+
+void MediaPlayer2AudioOutput::close() {
+    ALOGV("close");
+    sp<AudioTrack> track;
+    {
+        Mutex::Autolock lock(mLock);
+        track = mTrack;
+        close_l(); // clears mTrack
+    }
+    // destruction of the track occurs outside of mutex.
+}
+
+void MediaPlayer2AudioOutput::setVolume(float left, float right) {
+    ALOGV("setVolume(%f, %f)", left, right);
+    Mutex::Autolock lock(mLock);
+    mLeftVolume = left;
+    mRightVolume = right;
+    if (mTrack != 0) {
+        mTrack->setVolume(left, right);
+    }
+}
+
+status_t MediaPlayer2AudioOutput::setPlaybackRate(const AudioPlaybackRate &rate) {
+    ALOGV("setPlaybackRate(%f %f %d %d)",
+                rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
+    Mutex::Autolock lock(mLock);
+    if (mTrack == 0) {
+        // remember rate so that we can set it when the track is opened
+        mPlaybackRate = rate;
+        return OK;
+    }
+    status_t res = mTrack->setPlaybackRate(rate);
+    if (res != NO_ERROR) {
+        return res;
+    }
+    // rate.mSpeed is always greater than 0 if setPlaybackRate succeeded
+    CHECK_GT(rate.mSpeed, 0.f);
+    mPlaybackRate = rate;
+    if (mSampleRateHz != 0) {
+        mMsecsPerFrame = 1E3f / (rate.mSpeed * mSampleRateHz);
+    }
+    return res;
+}
+
+status_t MediaPlayer2AudioOutput::getPlaybackRate(AudioPlaybackRate *rate) {
+    ALOGV("setPlaybackRate");
+    Mutex::Autolock lock(mLock);
+    if (mTrack == 0) {
+        return NO_INIT;
+    }
+    *rate = mTrack->getPlaybackRate();
+    return NO_ERROR;
+}
+
+status_t MediaPlayer2AudioOutput::setAuxEffectSendLevel(float level) {
+    ALOGV("setAuxEffectSendLevel(%f)", level);
+    Mutex::Autolock lock(mLock);
+    mSendLevel = level;
+    if (mTrack != 0) {
+        return mTrack->setAuxEffectSendLevel(level);
+    }
+    return NO_ERROR;
+}
+
+status_t MediaPlayer2AudioOutput::attachAuxEffect(int effectId) {
+    ALOGV("attachAuxEffect(%d)", effectId);
+    Mutex::Autolock lock(mLock);
+    mAuxEffectId = effectId;
+    if (mTrack != 0) {
+        return mTrack->attachAuxEffect(effectId);
+    }
+    return NO_ERROR;
+}
+
+status_t MediaPlayer2AudioOutput::setOutputDevice(audio_port_handle_t deviceId) {
+    ALOGV("setOutputDevice(%d)", deviceId);
+    Mutex::Autolock lock(mLock);
+    mSelectedDeviceId = deviceId;
+    if (mTrack != 0) {
+        return mTrack->setOutputDevice(deviceId);
+    }
+    return NO_ERROR;
+}
+
+status_t MediaPlayer2AudioOutput::getRoutedDeviceId(audio_port_handle_t* deviceId) {
+    ALOGV("getRoutedDeviceId");
+    Mutex::Autolock lock(mLock);
+    if (mTrack != 0) {
+        mRoutedDeviceId = mTrack->getRoutedDeviceId();
+    }
+    *deviceId = mRoutedDeviceId;
+    return NO_ERROR;
+}
+
+status_t MediaPlayer2AudioOutput::enableAudioDeviceCallback(bool enabled) {
+    ALOGV("enableAudioDeviceCallback, %d", enabled);
+    Mutex::Autolock lock(mLock);
+    mDeviceCallbackEnabled = enabled;
+    if (mTrack != 0) {
+        status_t status;
+        if (enabled) {
+            status = mTrack->addAudioDeviceCallback(mDeviceCallback.promote());
+        } else {
+            status = mTrack->removeAudioDeviceCallback(mDeviceCallback.promote());
+        }
+        return status;
+    }
+    return NO_ERROR;
+}
+
+// static
+void MediaPlayer2AudioOutput::CallbackWrapper(
+        int event, void *cookie, void *info) {
+    //ALOGV("callbackwrapper");
+    CallbackData *data = (CallbackData*)cookie;
+    // lock to ensure we aren't caught in the middle of a track switch.
+    data->lock();
+    MediaPlayer2AudioOutput *me = data->getOutput();
+    AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
+    if (me == NULL) {
+        // no output set, likely because the track was scheduled to be reused
+        // by another player, but the format turned out to be incompatible.
+        data->unlock();
+        if (buffer != NULL) {
+            buffer->size = 0;
+        }
+        return;
+    }
+
+    switch(event) {
+    case AudioTrack::EVENT_MORE_DATA: {
+        size_t actualSize = (*me->mCallback)(
+                me, buffer->raw, buffer->size, me->mCallbackCookie,
+                CB_EVENT_FILL_BUFFER);
+
+        // Log when no data is returned from the callback.
+        // (1) We may have no data (especially with network streaming sources).
+        // (2) We may have reached the EOS and the audio track is not stopped yet.
+        // Note that AwesomePlayer/AudioPlayer will only return zero size when it reaches the EOS.
+        // NuPlayer2Renderer will return zero when it doesn't have data (it doesn't block to fill).
+        //
+        // This is a benign busy-wait, with the next data request generated 10 ms or more later;
+        // nevertheless for power reasons, we don't want to see too many of these.
+
+        ALOGV_IF(actualSize == 0 && buffer->size > 0, "callbackwrapper: empty buffer returned");
+
+        buffer->size = actualSize;
+        } break;
+
+    case AudioTrack::EVENT_STREAM_END:
+        // currently only occurs for offloaded callbacks
+        ALOGV("callbackwrapper: deliver EVENT_STREAM_END");
+        (*me->mCallback)(me, NULL /* buffer */, 0 /* size */,
+                me->mCallbackCookie, CB_EVENT_STREAM_END);
+        break;
+
+    case AudioTrack::EVENT_NEW_IAUDIOTRACK :
+        ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN");
+        (*me->mCallback)(me,  NULL /* buffer */, 0 /* size */,
+                me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
+        break;
+
+    case AudioTrack::EVENT_UNDERRUN:
+        // This occurs when there is no data available, typically
+        // when there is a failure to supply data to the AudioTrack.  It can also
+        // occur in non-offloaded mode when the audio device comes out of standby.
+        //
+        // If an AudioTrack underruns it outputs silence. Since this happens suddenly
+        // it may sound like an audible pop or glitch.
+        //
+        // The underrun event is sent once per track underrun; the condition is reset
+        // when more data is sent to the AudioTrack.
+        ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)");
+        break;
+
+    default:
+        ALOGE("received unknown event type: %d inside CallbackWrapper !", event);
+    }
+
+    data->unlock();
+}
+
+audio_session_t MediaPlayer2AudioOutput::getSessionId() const
+{
+    Mutex::Autolock lock(mLock);
+    return mSessionId;
+}
+
+uint32_t MediaPlayer2AudioOutput::getSampleRate() const
+{
+    Mutex::Autolock lock(mLock);
+    if (mTrack == 0) {
+        return 0;
+    }
+    return mTrack->getSampleRate();
+}
+
+int64_t MediaPlayer2AudioOutput::getBufferDurationInUs() const
+{
+    Mutex::Autolock lock(mLock);
+    if (mTrack == 0) {
+        return 0;
+    }
+    int64_t duration;
+    if (mTrack->getBufferDurationInUs(&duration) != OK) {
+        return 0;
+    }
+    return duration;
+}
+
+} // namespace android
diff --git a/media/libmediaplayer2/MediaPlayer2Manager.cpp b/media/libmediaplayer2/MediaPlayer2Manager.cpp
deleted file mode 100644
index 39b102c..0000000
--- a/media/libmediaplayer2/MediaPlayer2Manager.cpp
+++ /dev/null
@@ -1,2119 +0,0 @@
-/*
-**
-** Copyright 2017, 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.
-*/
-
-// Proxy for media player implementations
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "MediaPlayer2Manager"
-#include <utils/Log.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <dirent.h>
-#include <unistd.h>
-
-#include <string.h>
-
-#include <cutils/atomic.h>
-#include <cutils/properties.h> // for property_get
-
-#include <utils/misc.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/MemoryHeapBase.h>
-#include <binder/MemoryBase.h>
-#include <utils/Errors.h>  // for status_t
-#include <utils/String8.h>
-#include <utils/SystemClock.h>
-#include <utils/Timers.h>
-#include <utils/Vector.h>
-
-#include <media/AudioPolicyHelper.h>
-#include <media/DataSourceDesc.h>
-#include <media/MediaHTTPService.h>
-#include <media/Metadata.h>
-#include <media/AudioTrack.h>
-#include <media/MemoryLeakTrackUtil.h>
-#include <media/NdkWrapper.h>
-
-#include <media/stagefright/InterfaceUtils.h>
-#include <media/stagefright/MediaCodecList.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/Utils.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/ALooperRoster.h>
-#include <media/stagefright/SurfaceUtils.h>
-#include <mediautils/BatteryNotifier.h>
-
-#include <mediaplayer2/MediaPlayer2EngineClient.h>
-#include <mediaplayer2/MediaPlayer2Interface.h>
-
-#include <memunreachable/memunreachable.h>
-#include <system/audio.h>
-#include <system/window.h>
-
-#include <private/android_filesystem_config.h>
-
-#include <nuplayer2/NuPlayer2Driver.h>
-#include "MediaPlayer2Manager.h"
-
-static const int kDumpLockRetries = 50;
-static const int kDumpLockSleepUs = 20000;
-
-namespace {
-using android::media::Metadata;
-using android::status_t;
-using android::OK;
-using android::BAD_VALUE;
-using android::NOT_ENOUGH_DATA;
-using android::Parcel;
-
-// Max number of entries in the filter.
-const int kMaxFilterSize = 64;  // I pulled that out of thin air.
-
-const float kMaxRequiredSpeed = 8.0f; // for PCM tracks allow up to 8x speedup.
-
-// FIXME: Move all the metadata related function in the Metadata.cpp
-
-
-// Unmarshall a filter from a Parcel.
-// Filter format in a parcel:
-//
-//  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// |                       number of entries (n)                   |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// |                       metadata type 1                         |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// |                       metadata type 2                         |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//  ....
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// |                       metadata type n                         |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//
-// @param p Parcel that should start with a filter.
-// @param[out] filter On exit contains the list of metadata type to be
-//                    filtered.
-// @param[out] status On exit contains the status code to be returned.
-// @return true if the parcel starts with a valid filter.
-bool unmarshallFilter(const Parcel& p,
-                      Metadata::Filter *filter,
-                      status_t *status)
-{
-    int32_t val;
-    if (p.readInt32(&val) != OK)
-    {
-        ALOGE("Failed to read filter's length");
-        *status = NOT_ENOUGH_DATA;
-        return false;
-    }
-
-    if( val > kMaxFilterSize || val < 0)
-    {
-        ALOGE("Invalid filter len %d", val);
-        *status = BAD_VALUE;
-        return false;
-    }
-
-    const size_t num = val;
-
-    filter->clear();
-    filter->setCapacity(num);
-
-    size_t size = num * sizeof(Metadata::Type);
-
-
-    if (p.dataAvail() < size)
-    {
-        ALOGE("Filter too short expected %zu but got %zu", size, p.dataAvail());
-        *status = NOT_ENOUGH_DATA;
-        return false;
-    }
-
-    const Metadata::Type *data =
-            static_cast<const Metadata::Type*>(p.readInplace(size));
-
-    if (NULL == data)
-    {
-        ALOGE("Filter had no data");
-        *status = BAD_VALUE;
-        return false;
-    }
-
-    // TODO: The stl impl of vector would be more efficient here
-    // because it degenerates into a memcpy on pod types. Try to
-    // replace later or use stl::set.
-    for (size_t i = 0; i < num; ++i)
-    {
-        filter->add(*data);
-        ++data;
-    }
-    *status = OK;
-    return true;
-}
-
-// @param filter Of metadata type.
-// @param val To be searched.
-// @return true if a match was found.
-bool findMetadata(const Metadata::Filter& filter, const int32_t val)
-{
-    // Deal with empty and ANY right away
-    if (filter.isEmpty()) return false;
-    if (filter[0] == Metadata::kAny) return true;
-
-    return filter.indexOf(val) >= 0;
-}
-
-}  // anonymous namespace
-
-
-namespace {
-using android::Parcel;
-using android::String16;
-
-// marshalling tag indicating flattened utf16 tags
-// keep in sync with frameworks/base/media/java/android/media/AudioAttributes.java
-const int32_t kAudioAttributesMarshallTagFlattenTags = 1;
-
-// Audio attributes format in a parcel:
-//
-//  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// |                       usage                                   |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// |                       content_type                            |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// |                       source                                  |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// |                       flags                                   |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// |                       kAudioAttributesMarshallTagFlattenTags  | // ignore tags if not found
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// |                       flattened tags in UTF16                 |
-// |                         ...                                   |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//
-// @param p Parcel that contains audio attributes.
-// @param[out] attributes On exit points to an initialized audio_attributes_t structure
-// @param[out] status On exit contains the status code to be returned.
-void unmarshallAudioAttributes(const Parcel& parcel, audio_attributes_t *attributes)
-{
-    attributes->usage = (audio_usage_t) parcel.readInt32();
-    attributes->content_type = (audio_content_type_t) parcel.readInt32();
-    attributes->source = (audio_source_t) parcel.readInt32();
-    attributes->flags = (audio_flags_mask_t) parcel.readInt32();
-    const bool hasFlattenedTag = (parcel.readInt32() == kAudioAttributesMarshallTagFlattenTags);
-    if (hasFlattenedTag) {
-        // the tags are UTF16, convert to UTF8
-        String16 tags = parcel.readString16();
-        ssize_t realTagSize = utf16_to_utf8_length(tags.string(), tags.size());
-        if (realTagSize <= 0) {
-            strcpy(attributes->tags, "");
-        } else {
-            // copy the flattened string into the attributes as the destination for the conversion:
-            // copying array size -1, array for tags was calloc'd, no need to NULL-terminate it
-            size_t tagSize = realTagSize > AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 ?
-                    AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 : realTagSize;
-            utf16_to_utf8(tags.string(), tagSize, attributes->tags,
-                    sizeof(attributes->tags) / sizeof(attributes->tags[0]));
-        }
-    } else {
-        ALOGE("unmarshallAudioAttributes() received unflattened tags, ignoring tag values");
-        strcpy(attributes->tags, "");
-    }
-}
-} // anonymous namespace
-
-
-namespace android {
-
-extern ALooperRoster gLooperRoster;
-
-MediaPlayer2Manager gMediaPlayer2Manager;
-
-// TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
-/* static */ int MediaPlayer2Manager::AudioOutput::mMinBufferCount = 4;
-/* static */ bool MediaPlayer2Manager::AudioOutput::mIsOnEmulator = false;
-
-// static
-MediaPlayer2Manager& MediaPlayer2Manager::get() {
-    return gMediaPlayer2Manager;
-}
-
-MediaPlayer2Manager::MediaPlayer2Manager() {
-    ALOGV("MediaPlayer2Manager created");
-    // TODO: remove all unnecessary pid/uid handling.
-    mPid = IPCThreadState::self()->getCallingPid();
-    mUid = IPCThreadState::self()->getCallingUid();
-    mNextConnId = 1;
-}
-
-MediaPlayer2Manager::~MediaPlayer2Manager() {
-    ALOGV("MediaPlayer2Manager destroyed");
-}
-
-sp<MediaPlayer2Engine> MediaPlayer2Manager::create(
-        const sp<MediaPlayer2EngineClient>& client,
-        audio_session_t audioSessionId)
-{
-    int32_t connId = android_atomic_inc(&mNextConnId);
-
-    sp<Client> c = new Client(
-            mPid, connId, client, audioSessionId, mUid);
-
-    if (!c->init()) {
-        return NULL;
-    }
-
-    ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, mPid, mUid);
-
-    wp<Client> w = c;
-    {
-        Mutex::Autolock lock(mLock);
-        mClients.add(w);
-    }
-    return c;
-}
-
-status_t MediaPlayer2Manager::AudioOutput::dump(int fd, const Vector<String16>& args) const
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    result.append(" AudioOutput\n");
-    snprintf(buffer, 255, "  stream type(%d), left - right volume(%f, %f)\n",
-            mStreamType, mLeftVolume, mRightVolume);
-    result.append(buffer);
-    snprintf(buffer, 255, "  msec per frame(%f), latency (%d)\n",
-            mMsecsPerFrame, (mTrack != 0) ? mTrack->latency() : -1);
-    result.append(buffer);
-    snprintf(buffer, 255, "  aux effect id(%d), send level (%f)\n",
-            mAuxEffectId, mSendLevel);
-    result.append(buffer);
-
-    ::write(fd, result.string(), result.size());
-    if (mTrack != 0) {
-        mTrack->dump(fd, args);
-    }
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2Manager::Client::dump(int fd, const Vector<String16>& args)
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-    result.append(" Client\n");
-    snprintf(buffer, 255, "  pid(%d), connId(%d), status(%d), looping(%s)\n",
-            mPid, mConnId, mStatus, mLoop?"true": "false");
-    result.append(buffer);
-
-    sp<MediaPlayer2Interface> p;
-    sp<AudioOutput> audioOutput;
-    bool locked = false;
-    for (int i = 0; i < kDumpLockRetries; ++i) {
-        if (mLock.tryLock() == NO_ERROR) {
-            locked = true;
-            break;
-        }
-        usleep(kDumpLockSleepUs);
-    }
-
-    if (locked) {
-        p = mPlayer;
-        audioOutput = mAudioOutput;
-        mLock.unlock();
-    } else {
-        result.append("  lock is taken, no dump from player and audio output\n");
-    }
-    write(fd, result.string(), result.size());
-
-    if (p != NULL) {
-        p->dump(fd, args);
-    }
-    if (audioOutput != 0) {
-        audioOutput->dump(fd, args);
-    }
-    write(fd, "\n", 1);
-    return NO_ERROR;
-}
-
-/**
- * The only arguments this understands right now are -c, -von and -voff,
- * which are parsed by ALooperRoster::dump()
- */
-status_t MediaPlayer2Manager::dump(int fd, const Vector<String16>& args)
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-    SortedVector< sp<Client> > clients; //to serialise the mutex unlock & client destruction.
-
-    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
-        snprintf(buffer, SIZE, "Permission Denial: "
-                "can't dump MediaPlayer2Manager from pid=%d, uid=%d\n",
-                mPid, mUid);
-        result.append(buffer);
-    } else {
-        Mutex::Autolock lock(mLock);
-        for (int i = 0, n = mClients.size(); i < n; ++i) {
-            sp<Client> c = mClients[i].promote();
-            if (c != 0) c->dump(fd, args);
-            clients.add(c);
-        }
-
-        result.append(" Files opened and/or mapped:\n");
-        snprintf(buffer, SIZE, "/proc/%d/maps", getpid());
-        FILE *f = fopen(buffer, "r");
-        if (f) {
-            while (!feof(f)) {
-                fgets(buffer, SIZE, f);
-                if (strstr(buffer, " /storage/") ||
-                    strstr(buffer, " /system/sounds/") ||
-                    strstr(buffer, " /data/") ||
-                    strstr(buffer, " /system/media/")) {
-                    result.append("  ");
-                    result.append(buffer);
-                }
-            }
-            fclose(f);
-        } else {
-            result.append("couldn't open ");
-            result.append(buffer);
-            result.append("\n");
-        }
-
-        snprintf(buffer, SIZE, "/proc/%d/fd", getpid());
-        DIR *d = opendir(buffer);
-        if (d) {
-            struct dirent *ent;
-            while((ent = readdir(d)) != NULL) {
-                if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
-                    snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name);
-                    struct stat s;
-                    if (lstat(buffer, &s) == 0) {
-                        if ((s.st_mode & S_IFMT) == S_IFLNK) {
-                            char linkto[256];
-                            int len = readlink(buffer, linkto, sizeof(linkto));
-                            if(len > 0) {
-                                if(len > 255) {
-                                    linkto[252] = '.';
-                                    linkto[253] = '.';
-                                    linkto[254] = '.';
-                                    linkto[255] = 0;
-                                } else {
-                                    linkto[len] = 0;
-                                }
-                                if (strstr(linkto, "/storage/") == linkto ||
-                                    strstr(linkto, "/system/sounds/") == linkto ||
-                                    strstr(linkto, "/data/") == linkto ||
-                                    strstr(linkto, "/system/media/") == linkto) {
-                                    result.append("  ");
-                                    result.append(buffer);
-                                    result.append(" -> ");
-                                    result.append(linkto);
-                                    result.append("\n");
-                                }
-                            }
-                        } else {
-                            result.append("  unexpected type for ");
-                            result.append(buffer);
-                            result.append("\n");
-                        }
-                    }
-                }
-            }
-            closedir(d);
-        } else {
-            result.append("couldn't open ");
-            result.append(buffer);
-            result.append("\n");
-        }
-
-        gLooperRoster.dump(fd, args);
-
-        bool dumpMem = false;
-        bool unreachableMemory = false;
-        for (size_t i = 0; i < args.size(); i++) {
-            if (args[i] == String16("-m")) {
-                dumpMem = true;
-            } else if (args[i] == String16("--unreachable")) {
-                unreachableMemory = true;
-            }
-        }
-        if (dumpMem) {
-            result.append("\nDumping memory:\n");
-            std::string s = dumpMemoryAddresses(100 /* limit */);
-            result.append(s.c_str(), s.size());
-        }
-        if (unreachableMemory) {
-            result.append("\nDumping unreachable memory:\n");
-            // TODO - should limit be an argument parameter?
-            // TODO: enable GetUnreachableMemoryString if it's part of stable API
-            //std::string s = GetUnreachableMemoryString(true /* contents */, 10000 /* limit */);
-            //result.append(s.c_str(), s.size());
-        }
-    }
-    write(fd, result.string(), result.size());
-    return NO_ERROR;
-}
-
-void MediaPlayer2Manager::removeClient(const wp<Client>& client)
-{
-    Mutex::Autolock lock(mLock);
-    mClients.remove(client);
-}
-
-bool MediaPlayer2Manager::hasClient(wp<Client> client)
-{
-    Mutex::Autolock lock(mLock);
-    return mClients.indexOf(client) != NAME_NOT_FOUND;
-}
-
-MediaPlayer2Manager::Client::Client(
-        pid_t pid,
-        int32_t connId,
-        const sp<MediaPlayer2EngineClient>& client,
-        audio_session_t audioSessionId,
-        uid_t uid)
-{
-    ALOGV("Client(%d) constructor", connId);
-    mPid = pid;
-    mConnId = connId;
-    mClient = client;
-    mLoop = false;
-    mStatus = NO_INIT;
-    mAudioSessionId = audioSessionId;
-    mUid = uid;
-    mAudioAttributes = NULL;
-
-#if CALLBACK_ANTAGONIZER
-    ALOGD("create Antagonizer");
-    mAntagonizer = new Antagonizer(notify, this);
-#endif
-}
-
-bool MediaPlayer2Manager::Client::init() {
-    sp<MediaPlayer2Interface> p = new NuPlayer2Driver(mPid, mUid);
-    status_t init_result = p->initCheck();
-    if (init_result != NO_ERROR) {
-        ALOGE("Failed to create player object, initCheck failed(%d)", init_result);
-        return false;
-    }
-
-    p->setNotifyCallback(this, notify);
-    mAudioDeviceUpdatedListener = new AudioDeviceUpdatedNotifier(p);
-    mAudioOutput = new AudioOutput(mAudioSessionId, mUid,
-            mPid, mAudioAttributes, mAudioDeviceUpdatedListener);
-    p->setAudioSink(mAudioOutput);
-
-    mPlayer = p;
-    return true;
-}
-
-MediaPlayer2Manager::Client::~Client()
-{
-    ALOGV("Client(%d) destructor pid = %d", mConnId, mPid);
-    mAudioOutput.clear();
-    wp<Client> client(this);
-    disconnect();
-    gMediaPlayer2Manager.removeClient(client);
-    if (mAudioAttributes != NULL) {
-        free(mAudioAttributes);
-    }
-    mAudioDeviceUpdatedListener.clear();
-}
-
-void MediaPlayer2Manager::Client::disconnect()
-{
-    ALOGV("disconnect(%d) from pid %d", mConnId, mPid);
-    // grab local reference and clear main reference to prevent future
-    // access to object
-    sp<MediaPlayer2Interface> p;
-    {
-        Mutex::Autolock l(mLock);
-        p = mPlayer;
-        mClient.clear();
-        mPlayer.clear();
-    }
-
-    // clear the notification to prevent callbacks to dead client
-    // and reset the player. We assume the player will serialize
-    // access to itself if necessary.
-    if (p != 0) {
-        p->setNotifyCallback(0, 0);
-#if CALLBACK_ANTAGONIZER
-        ALOGD("kill Antagonizer");
-        mAntagonizer->kill();
-#endif
-        p->reset();
-    }
-
-    {
-        Mutex::Autolock l(mLock);
-        disconnectNativeWindow_l();
-    }
-
-    IPCThreadState::self()->flushCommands();
-}
-
-void MediaPlayer2Manager::Client::AudioDeviceUpdatedNotifier::onAudioDeviceUpdate(
-        audio_io_handle_t audioIo,
-        audio_port_handle_t deviceId) {
-    sp<MediaPlayer2Interface> listener = mListener.promote();
-    if (listener != NULL) {
-        listener->sendEvent(0, MEDIA2_AUDIO_ROUTING_CHANGED, audioIo, deviceId);
-    } else {
-        ALOGW("listener for process %d death is gone", MEDIA2_AUDIO_ROUTING_CHANGED);
-    }
-}
-
-status_t MediaPlayer2Manager::Client::setDataSource(
-        const sp<DataSourceDesc> &dsd) {
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == NULL) {
-        return NO_INIT;
-    }
-
-    if (dsd == NULL) {
-        return BAD_VALUE;
-    }
-
-    status_t status = p->setDataSource(dsd);
-    if (status != OK) {
-        ALOGE("setDataSource error: %d", status);
-        return status;
-    }
-
-    return status;
-}
-
-status_t MediaPlayer2Manager::Client::prepareNextDataSource(
-        const sp<DataSourceDesc> &dsd) {
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == NULL) {
-        return NO_INIT;
-    }
-
-    if (dsd == NULL) {
-        return BAD_VALUE;
-    }
-
-    status_t status = p->prepareNextDataSource(dsd);
-    if (status != OK) {
-        ALOGE("prepareNextDataSource error: %d", status);
-    }
-
-    return status;
-}
-
-status_t MediaPlayer2Manager::Client::playNextDataSource(int64_t srcId) {
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == NULL) {
-        return NO_INIT;
-    }
-
-    status_t status = p->playNextDataSource(srcId);
-    if (status != OK) {
-        ALOGE("playNextDataSource error: %d", status);
-    }
-
-    return status;
-}
-
-void MediaPlayer2Manager::Client::disconnectNativeWindow_l() {
-    if (mConnectedWindow != NULL && mConnectedWindow->getANativeWindow() != NULL) {
-        status_t err = native_window_api_disconnect(
-                mConnectedWindow->getANativeWindow(), NATIVE_WINDOW_API_MEDIA);
-
-        if (err != OK) {
-            ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
-                    strerror(-err), err);
-        }
-    }
-    mConnectedWindow.clear();
-}
-
-status_t MediaPlayer2Manager::Client::setVideoSurfaceTexture(
-        const sp<ANativeWindowWrapper>& nww)
-{
-    ALOGV("[%d] setVideoSurfaceTexture(%p)",
-          mConnId,
-          (nww == NULL ? NULL : nww->getANativeWindow()));
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-
-    if (nww != NULL && nww->getANativeWindow() != NULL) {
-        if (mConnectedWindow != NULL
-            && mConnectedWindow->getANativeWindow() == nww->getANativeWindow()) {
-            return OK;
-        }
-        status_t err = native_window_api_connect(
-                nww->getANativeWindow(), NATIVE_WINDOW_API_MEDIA);
-
-        if (err != OK) {
-            ALOGE("setVideoSurfaceTexture failed: %d", err);
-            // Note that we must do the reset before disconnecting from the ANW.
-            // Otherwise queue/dequeue calls could be made on the disconnected
-            // ANW, which may result in errors.
-            reset();
-
-            Mutex::Autolock lock(mLock);
-            disconnectNativeWindow_l();
-
-            return err;
-        }
-    }
-
-    // Note that we must set the player's new GraphicBufferProducer before
-    // disconnecting the old one.  Otherwise queue/dequeue calls could be made
-    // on the disconnected ANW, which may result in errors.
-    status_t err = p->setVideoSurfaceTexture(nww);
-
-    mLock.lock();
-    disconnectNativeWindow_l();
-
-    if (err == OK) {
-        mConnectedWindow = nww;
-        mLock.unlock();
-    } else if (nww != NULL) {
-        mLock.unlock();
-        status_t err = native_window_api_disconnect(
-                nww->getANativeWindow(), NATIVE_WINDOW_API_MEDIA);
-
-        if (err != OK) {
-            ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
-                    strerror(-err), err);
-        }
-    }
-
-    return err;
-}
-
-status_t MediaPlayer2Manager::Client::invoke(const Parcel& request,
-                                            Parcel *reply)
-{
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == NULL) return UNKNOWN_ERROR;
-    return p->invoke(request, reply);
-}
-
-// This call doesn't need to access the native player.
-status_t MediaPlayer2Manager::Client::setMetadataFilter(const Parcel& filter)
-{
-    status_t status;
-    media::Metadata::Filter allow, drop;
-
-    if (unmarshallFilter(filter, &allow, &status) &&
-        unmarshallFilter(filter, &drop, &status)) {
-        Mutex::Autolock lock(mLock);
-
-        mMetadataAllow = allow;
-        mMetadataDrop = drop;
-    }
-    return status;
-}
-
-status_t MediaPlayer2Manager::Client::getMetadata(
-        bool update_only, bool /*apply_filter*/, Parcel *reply)
-{
-    sp<MediaPlayer2Interface> player = getPlayer();
-    if (player == 0) return UNKNOWN_ERROR;
-
-    status_t status;
-    // Placeholder for the return code, updated by the caller.
-    reply->writeInt32(-1);
-
-    media::Metadata::Filter ids;
-
-    // We don't block notifications while we fetch the data. We clear
-    // mMetadataUpdated first so we don't lose notifications happening
-    // during the rest of this call.
-    {
-        Mutex::Autolock lock(mLock);
-        if (update_only) {
-            ids = mMetadataUpdated;
-        }
-        mMetadataUpdated.clear();
-    }
-
-    media::Metadata metadata(reply);
-
-    metadata.appendHeader();
-    status = player->getMetadata(ids, reply);
-
-    if (status != OK) {
-        metadata.resetParcel();
-        ALOGE("getMetadata failed %d", status);
-        return status;
-    }
-
-    // FIXME: ement filtering on the result. Not critical since
-    // filtering takes place on the update notifications already. This
-    // would be when all the metadata are fetch and a filter is set.
-
-    // Everything is fine, update the metadata length.
-    metadata.updateLength();
-    return OK;
-}
-
-status_t MediaPlayer2Manager::Client::setBufferingSettings(
-        const BufferingSettings& buffering)
-{
-    ALOGV("[%d] setBufferingSettings{%s}",
-            mConnId, buffering.toString().string());
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-    return p->setBufferingSettings(buffering);
-}
-
-status_t MediaPlayer2Manager::Client::getBufferingSettings(
-        BufferingSettings* buffering /* nonnull */)
-{
-    sp<MediaPlayer2Interface> p = getPlayer();
-    // TODO: create mPlayer on demand.
-    if (p == 0) return UNKNOWN_ERROR;
-    status_t ret = p->getBufferingSettings(buffering);
-    if (ret == NO_ERROR) {
-        ALOGV("[%d] getBufferingSettings{%s}",
-                mConnId, buffering->toString().string());
-    } else {
-        ALOGE("[%d] getBufferingSettings returned %d", mConnId, ret);
-    }
-    return ret;
-}
-
-status_t MediaPlayer2Manager::Client::prepareAsync()
-{
-    ALOGV("[%d] prepareAsync", mConnId);
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-    status_t ret = p->prepareAsync();
-#if CALLBACK_ANTAGONIZER
-    ALOGD("start Antagonizer");
-    if (ret == NO_ERROR) mAntagonizer->start();
-#endif
-    return ret;
-}
-
-status_t MediaPlayer2Manager::Client::start()
-{
-    ALOGV("[%d] start", mConnId);
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-    p->setLooping(mLoop);
-    return p->start();
-}
-
-status_t MediaPlayer2Manager::Client::stop()
-{
-    ALOGV("[%d] stop", mConnId);
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-    return p->stop();
-}
-
-status_t MediaPlayer2Manager::Client::pause()
-{
-    ALOGV("[%d] pause", mConnId);
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-    return p->pause();
-}
-
-status_t MediaPlayer2Manager::Client::isPlaying(bool* state)
-{
-    *state = false;
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-    *state = p->isPlaying();
-    ALOGV("[%d] isPlaying: %d", mConnId, *state);
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2Manager::Client::setPlaybackSettings(const AudioPlaybackRate& rate)
-{
-    ALOGV("[%d] setPlaybackSettings(%f, %f, %d, %d)",
-            mConnId, rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-    return p->setPlaybackSettings(rate);
-}
-
-status_t MediaPlayer2Manager::Client::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */)
-{
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-    status_t ret = p->getPlaybackSettings(rate);
-    if (ret == NO_ERROR) {
-        ALOGV("[%d] getPlaybackSettings(%f, %f, %d, %d)",
-                mConnId, rate->mSpeed, rate->mPitch, rate->mFallbackMode, rate->mStretchMode);
-    } else {
-        ALOGV("[%d] getPlaybackSettings returned %d", mConnId, ret);
-    }
-    return ret;
-}
-
-status_t MediaPlayer2Manager::Client::setSyncSettings(
-        const AVSyncSettings& sync, float videoFpsHint)
-{
-    ALOGV("[%d] setSyncSettings(%u, %u, %f, %f)",
-            mConnId, sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint);
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-    return p->setSyncSettings(sync, videoFpsHint);
-}
-
-status_t MediaPlayer2Manager::Client::getSyncSettings(
-        AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */)
-{
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-    status_t ret = p->getSyncSettings(sync, videoFps);
-    if (ret == NO_ERROR) {
-        ALOGV("[%d] getSyncSettings(%u, %u, %f, %f)",
-                mConnId, sync->mSource, sync->mAudioAdjustMode, sync->mTolerance, *videoFps);
-    } else {
-        ALOGV("[%d] getSyncSettings returned %d", mConnId, ret);
-    }
-    return ret;
-}
-
-status_t MediaPlayer2Manager::Client::getCurrentPosition(int *msec)
-{
-    ALOGV("getCurrentPosition");
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-    status_t ret = p->getCurrentPosition(msec);
-    if (ret == NO_ERROR) {
-        ALOGV("[%d] getCurrentPosition = %d", mConnId, *msec);
-    } else {
-        ALOGE("getCurrentPosition returned %d", ret);
-    }
-    return ret;
-}
-
-status_t MediaPlayer2Manager::Client::getDuration(int *msec)
-{
-    ALOGV("getDuration");
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-    status_t ret = p->getDuration(msec);
-    if (ret == NO_ERROR) {
-        ALOGV("[%d] getDuration = %d", mConnId, *msec);
-    } else {
-        ALOGE("getDuration returned %d", ret);
-    }
-    return ret;
-}
-
-status_t MediaPlayer2Manager::Client::setNextPlayer(const sp<MediaPlayer2Engine>& player) {
-    ALOGV("setNextPlayer");
-    Mutex::Autolock l(mLock);
-    sp<Client> c = static_cast<Client*>(player.get());
-    if (c != NULL && !gMediaPlayer2Manager.hasClient(c)) {
-      return BAD_VALUE;
-    }
-
-    mNextClient = c;
-
-    if (c != NULL) {
-        if (mAudioOutput != NULL) {
-            mAudioOutput->setNextOutput(c->mAudioOutput);
-        } else {
-            ALOGE("no current audio output");
-        }
-
-        if ((mPlayer != NULL) && (mNextClient->getPlayer() != NULL)) {
-            mPlayer->setNextPlayer(mNextClient->getPlayer());
-        }
-    }
-
-    return OK;
-}
-
-status_t MediaPlayer2Manager::Client::seekTo(int msec, MediaPlayer2SeekMode mode)
-{
-    ALOGV("[%d] seekTo(%d, %d)", mConnId, msec, mode);
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-    return p->seekTo(msec, mode);
-}
-
-status_t MediaPlayer2Manager::Client::reset()
-{
-    ALOGV("[%d] reset", mConnId);
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-    return p->reset();
-}
-
-status_t MediaPlayer2Manager::Client::notifyAt(int64_t mediaTimeUs)
-{
-    ALOGV("[%d] notifyAt(%lld)", mConnId, (long long)mediaTimeUs);
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-    return p->notifyAt(mediaTimeUs);
-}
-
-status_t MediaPlayer2Manager::Client::setAudioStreamType(audio_stream_type_t type)
-{
-    ALOGV("[%d] setAudioStreamType(%d)", mConnId, type);
-    // TODO: for hardware output, call player instead
-    Mutex::Autolock l(mLock);
-    if (mAudioOutput != 0) mAudioOutput->setAudioStreamType(type);
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2Manager::Client::setAudioAttributes_l(const Parcel &parcel)
-{
-    if (mAudioAttributes != NULL) { free(mAudioAttributes); }
-    mAudioAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
-    if (mAudioAttributes == NULL) {
-        return NO_MEMORY;
-    }
-    unmarshallAudioAttributes(parcel, mAudioAttributes);
-
-    ALOGV("setAudioAttributes_l() usage=%d content=%d flags=0x%x tags=%s",
-            mAudioAttributes->usage, mAudioAttributes->content_type, mAudioAttributes->flags,
-            mAudioAttributes->tags);
-
-    if (mAudioOutput != 0) {
-        mAudioOutput->setAudioAttributes(mAudioAttributes);
-    }
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2Manager::Client::setLooping(int loop)
-{
-    ALOGV("[%d] setLooping(%d)", mConnId, loop);
-    mLoop = loop;
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p != 0) return p->setLooping(loop);
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2Manager::Client::setVolume(float leftVolume, float rightVolume)
-{
-    ALOGV("[%d] setVolume(%f, %f)", mConnId, leftVolume, rightVolume);
-
-    // for hardware output, call player instead
-    sp<MediaPlayer2Interface> p = getPlayer();
-    {
-      Mutex::Autolock l(mLock);
-      if (mAudioOutput != 0) mAudioOutput->setVolume(leftVolume, rightVolume);
-    }
-
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2Manager::Client::setAuxEffectSendLevel(float level)
-{
-    ALOGV("[%d] setAuxEffectSendLevel(%f)", mConnId, level);
-    Mutex::Autolock l(mLock);
-    if (mAudioOutput != 0) return mAudioOutput->setAuxEffectSendLevel(level);
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2Manager::Client::attachAuxEffect(int effectId)
-{
-    ALOGV("[%d] attachAuxEffect(%d)", mConnId, effectId);
-    Mutex::Autolock l(mLock);
-    if (mAudioOutput != 0) return mAudioOutput->attachAuxEffect(effectId);
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2Manager::Client::setParameter(int key, const Parcel &request) {
-    ALOGV("[%d] setParameter(%d)", mConnId, key);
-    switch (key) {
-    case MEDIA2_KEY_PARAMETER_AUDIO_ATTRIBUTES:
-    {
-        Mutex::Autolock l(mLock);
-        return setAudioAttributes_l(request);
-    }
-    default:
-        sp<MediaPlayer2Interface> p = getPlayer();
-        if (p == 0) { return UNKNOWN_ERROR; }
-        return p->setParameter(key, request);
-    }
-}
-
-status_t MediaPlayer2Manager::Client::getParameter(int key, Parcel *reply) {
-    ALOGV("[%d] getParameter(%d)", mConnId, key);
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-    return p->getParameter(key, reply);
-}
-
-void MediaPlayer2Manager::Client::notify(
-        const wp<MediaPlayer2Engine> &listener, int64_t srcId,
-        int msg, int ext1, int ext2, const Parcel *obj)
-{
-    sp<MediaPlayer2Engine> spListener = listener.promote();
-    if (spListener == NULL) {
-        return;
-    }
-    Client* client = static_cast<Client*>(spListener.get());
-
-    sp<MediaPlayer2EngineClient> c;
-    sp<Client> nextClient;
-    status_t errStartNext = NO_ERROR;
-    {
-        Mutex::Autolock l(client->mLock);
-        c = client->mClient;
-        if (msg == MEDIA2_PLAYBACK_COMPLETE && client->mNextClient != NULL) {
-            nextClient = client->mNextClient;
-
-            if (client->mAudioOutput != NULL)
-                client->mAudioOutput->switchToNextOutput();
-
-            errStartNext = nextClient->start();
-        }
-    }
-
-    if (nextClient != NULL) {
-        sp<MediaPlayer2EngineClient> nc;
-        {
-            Mutex::Autolock l(nextClient->mLock);
-            nc = nextClient->mClient;
-        }
-        if (nc != NULL) {
-            if (errStartNext == NO_ERROR) {
-                nc->notify(srcId, MEDIA2_INFO, MEDIA2_INFO_STARTED_AS_NEXT, 0, obj);
-            } else {
-                nc->notify(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN , 0, obj);
-                ALOGE("gapless:start playback for next track failed, err(%d)", errStartNext);
-            }
-        }
-    }
-
-    if (MEDIA2_INFO == msg &&
-        MEDIA2_INFO_METADATA_UPDATE == ext1) {
-        const media::Metadata::Type metadata_type = ext2;
-
-        if(client->shouldDropMetadata(metadata_type)) {
-            return;
-        }
-
-        // Update the list of metadata that have changed. getMetadata
-        // also access mMetadataUpdated and clears it.
-        client->addNewMetadataUpdate(metadata_type);
-    }
-
-    if (c != NULL) {
-        ALOGV("[%d] notify (%p, %lld, %d, %d, %d)", client->mConnId, spListener.get(),
-              (long long)srcId, msg, ext1, ext2);
-        c->notify(srcId, msg, ext1, ext2, obj);
-    }
-}
-
-
-bool MediaPlayer2Manager::Client::shouldDropMetadata(media::Metadata::Type code) const
-{
-    Mutex::Autolock lock(mLock);
-
-    if (findMetadata(mMetadataDrop, code)) {
-        return true;
-    }
-
-    if (mMetadataAllow.isEmpty() || findMetadata(mMetadataAllow, code)) {
-        return false;
-    } else {
-        return true;
-    }
-}
-
-
-void MediaPlayer2Manager::Client::addNewMetadataUpdate(media::Metadata::Type metadata_type) {
-    Mutex::Autolock lock(mLock);
-    if (mMetadataUpdated.indexOf(metadata_type) < 0) {
-        mMetadataUpdated.add(metadata_type);
-    }
-}
-
-// Modular DRM
-status_t MediaPlayer2Manager::Client::prepareDrm(const uint8_t uuid[16],
-        const Vector<uint8_t>& drmSessionId)
-{
-    ALOGV("[%d] prepareDrm", mConnId);
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-
-    status_t ret = p->prepareDrm(uuid, drmSessionId);
-    ALOGV("prepareDrm ret: %d", ret);
-
-    return ret;
-}
-
-status_t MediaPlayer2Manager::Client::releaseDrm()
-{
-    ALOGV("[%d] releaseDrm", mConnId);
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-
-    status_t ret = p->releaseDrm();
-    ALOGV("releaseDrm ret: %d", ret);
-
-    return ret;
-}
-
-status_t MediaPlayer2Manager::Client::setOutputDevice(audio_port_handle_t deviceId)
-{
-    ALOGV("[%d] setOutputDevice", mConnId);
-    {
-        Mutex::Autolock l(mLock);
-        if (mAudioOutput.get() != nullptr) {
-            return mAudioOutput->setOutputDevice(deviceId);
-        }
-    }
-    return NO_INIT;
-}
-
-status_t MediaPlayer2Manager::Client::getRoutedDeviceId(audio_port_handle_t* deviceId)
-{
-    ALOGV("[%d] getRoutedDeviceId", mConnId);
-    {
-        Mutex::Autolock l(mLock);
-        if (mAudioOutput.get() != nullptr) {
-            return mAudioOutput->getRoutedDeviceId(deviceId);
-        }
-    }
-    return NO_INIT;
-}
-
-status_t MediaPlayer2Manager::Client::enableAudioDeviceCallback(bool enabled)
-{
-    ALOGV("[%d] enableAudioDeviceCallback, %d", mConnId, enabled);
-    {
-        Mutex::Autolock l(mLock);
-        if (mAudioOutput.get() != nullptr) {
-            return mAudioOutput->enableAudioDeviceCallback(enabled);
-        }
-    }
-    return NO_INIT;
-}
-
-#if CALLBACK_ANTAGONIZER
-const int Antagonizer::interval = 10000; // 10 msecs
-
-Antagonizer::Antagonizer(
-        MediaPlayer2Manager::NotifyCallback cb,
-        const wp<MediaPlayer2Engine> &client) :
-    mExit(false), mActive(false), mClient(client), mCb(cb)
-{
-    createThread(callbackThread, this);
-}
-
-void Antagonizer::kill()
-{
-    Mutex::Autolock _l(mLock);
-    mActive = false;
-    mExit = true;
-    mCondition.wait(mLock);
-}
-
-int Antagonizer::callbackThread(void* user)
-{
-    ALOGD("Antagonizer started");
-    Antagonizer* p = reinterpret_cast<Antagonizer*>(user);
-    while (!p->mExit) {
-        if (p->mActive) {
-            ALOGV("send event");
-            p->mCb(p->mClient, 0, 0, 0);
-        }
-        usleep(interval);
-    }
-    Mutex::Autolock _l(p->mLock);
-    p->mCondition.signal();
-    ALOGD("Antagonizer stopped");
-    return 0;
-}
-#endif
-
-#undef LOG_TAG
-#define LOG_TAG "AudioSink"
-MediaPlayer2Manager::AudioOutput::AudioOutput(audio_session_t sessionId, uid_t uid, int pid,
-        const audio_attributes_t* attr, const sp<AudioSystem::AudioDeviceCallback>& deviceCallback)
-    : mCallback(NULL),
-      mCallbackCookie(NULL),
-      mCallbackData(NULL),
-      mStreamType(AUDIO_STREAM_MUSIC),
-      mLeftVolume(1.0),
-      mRightVolume(1.0),
-      mPlaybackRate(AUDIO_PLAYBACK_RATE_DEFAULT),
-      mSampleRateHz(0),
-      mMsecsPerFrame(0),
-      mFrameSize(0),
-      mSessionId(sessionId),
-      mUid(uid),
-      mPid(pid),
-      mSendLevel(0.0),
-      mAuxEffectId(0),
-      mFlags(AUDIO_OUTPUT_FLAG_NONE),
-      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
-      mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE),
-      mDeviceCallbackEnabled(false),
-      mDeviceCallback(deviceCallback)
-{
-    ALOGV("AudioOutput(%d)", sessionId);
-    if (attr != NULL) {
-        mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
-        if (mAttributes != NULL) {
-            memcpy(mAttributes, attr, sizeof(audio_attributes_t));
-            mStreamType = audio_attributes_to_stream_type(attr);
-        }
-    } else {
-        mAttributes = NULL;
-    }
-
-    setMinBufferCount();
-}
-
-MediaPlayer2Manager::AudioOutput::~AudioOutput()
-{
-    close();
-    free(mAttributes);
-    delete mCallbackData;
-}
-
-//static
-void MediaPlayer2Manager::AudioOutput::setMinBufferCount()
-{
-    char value[PROPERTY_VALUE_MAX];
-    if (property_get("ro.kernel.qemu", value, 0)) {
-        mIsOnEmulator = true;
-        mMinBufferCount = 12;  // to prevent systematic buffer underrun for emulator
-    }
-}
-
-// static
-bool MediaPlayer2Manager::AudioOutput::isOnEmulator()
-{
-    setMinBufferCount(); // benign race wrt other threads
-    return mIsOnEmulator;
-}
-
-// static
-int MediaPlayer2Manager::AudioOutput::getMinBufferCount()
-{
-    setMinBufferCount(); // benign race wrt other threads
-    return mMinBufferCount;
-}
-
-ssize_t MediaPlayer2Manager::AudioOutput::bufferSize() const
-{
-    Mutex::Autolock lock(mLock);
-    if (mTrack == 0) return NO_INIT;
-    return mTrack->frameCount() * mFrameSize;
-}
-
-ssize_t MediaPlayer2Manager::AudioOutput::frameCount() const
-{
-    Mutex::Autolock lock(mLock);
-    if (mTrack == 0) return NO_INIT;
-    return mTrack->frameCount();
-}
-
-ssize_t MediaPlayer2Manager::AudioOutput::channelCount() const
-{
-    Mutex::Autolock lock(mLock);
-    if (mTrack == 0) return NO_INIT;
-    return mTrack->channelCount();
-}
-
-ssize_t MediaPlayer2Manager::AudioOutput::frameSize() const
-{
-    Mutex::Autolock lock(mLock);
-    if (mTrack == 0) return NO_INIT;
-    return mFrameSize;
-}
-
-uint32_t MediaPlayer2Manager::AudioOutput::latency () const
-{
-    Mutex::Autolock lock(mLock);
-    if (mTrack == 0) return 0;
-    return mTrack->latency();
-}
-
-float MediaPlayer2Manager::AudioOutput::msecsPerFrame() const
-{
-    Mutex::Autolock lock(mLock);
-    return mMsecsPerFrame;
-}
-
-status_t MediaPlayer2Manager::AudioOutput::getPosition(uint32_t *position) const
-{
-    Mutex::Autolock lock(mLock);
-    if (mTrack == 0) return NO_INIT;
-    return mTrack->getPosition(position);
-}
-
-status_t MediaPlayer2Manager::AudioOutput::getTimestamp(AudioTimestamp &ts) const
-{
-    Mutex::Autolock lock(mLock);
-    if (mTrack == 0) return NO_INIT;
-    return mTrack->getTimestamp(ts);
-}
-
-// TODO: Remove unnecessary calls to getPlayedOutDurationUs()
-// as it acquires locks and may query the audio driver.
-//
-// Some calls could conceivably retrieve extrapolated data instead of
-// accessing getTimestamp() or getPosition() every time a data buffer with
-// a media time is received.
-//
-// Calculate duration of played samples if played at normal rate (i.e., 1.0).
-int64_t MediaPlayer2Manager::AudioOutput::getPlayedOutDurationUs(int64_t nowUs) const
-{
-    Mutex::Autolock lock(mLock);
-    if (mTrack == 0 || mSampleRateHz == 0) {
-        return 0;
-    }
-
-    uint32_t numFramesPlayed;
-    int64_t numFramesPlayedAtUs;
-    AudioTimestamp ts;
-
-    status_t res = mTrack->getTimestamp(ts);
-    if (res == OK) {                 // case 1: mixing audio tracks and offloaded tracks.
-        numFramesPlayed = ts.mPosition;
-        numFramesPlayedAtUs = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000;
-        //ALOGD("getTimestamp: OK %d %lld", numFramesPlayed, (long long)numFramesPlayedAtUs);
-    } else if (res == WOULD_BLOCK) { // case 2: transitory state on start of a new track
-        numFramesPlayed = 0;
-        numFramesPlayedAtUs = nowUs;
-        //ALOGD("getTimestamp: WOULD_BLOCK %d %lld",
-        //        numFramesPlayed, (long long)numFramesPlayedAtUs);
-    } else {                         // case 3: transitory at new track or audio fast tracks.
-        res = mTrack->getPosition(&numFramesPlayed);
-        CHECK_EQ(res, (status_t)OK);
-        numFramesPlayedAtUs = nowUs;
-        numFramesPlayedAtUs += 1000LL * mTrack->latency() / 2; /* XXX */
-        //ALOGD("getPosition: %u %lld", numFramesPlayed, (long long)numFramesPlayedAtUs);
-    }
-
-    // CHECK_EQ(numFramesPlayed & (1 << 31), 0);  // can't be negative until 12.4 hrs, test
-    // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
-    int64_t durationUs = (int64_t)((int32_t)numFramesPlayed * 1000000LL / mSampleRateHz)
-            + nowUs - numFramesPlayedAtUs;
-    if (durationUs < 0) {
-        // Occurs when numFramesPlayed position is very small and the following:
-        // (1) In case 1, the time nowUs is computed before getTimestamp() is called and
-        //     numFramesPlayedAtUs is greater than nowUs by time more than numFramesPlayed.
-        // (2) In case 3, using getPosition and adding mAudioSink->latency() to
-        //     numFramesPlayedAtUs, by a time amount greater than numFramesPlayed.
-        //
-        // Both of these are transitory conditions.
-        ALOGV("getPlayedOutDurationUs: negative duration %lld set to zero", (long long)durationUs);
-        durationUs = 0;
-    }
-    ALOGV("getPlayedOutDurationUs(%lld) nowUs(%lld) frames(%u) framesAt(%lld)",
-            (long long)durationUs, (long long)nowUs,
-            numFramesPlayed, (long long)numFramesPlayedAtUs);
-    return durationUs;
-}
-
-status_t MediaPlayer2Manager::AudioOutput::getFramesWritten(uint32_t *frameswritten) const
-{
-    Mutex::Autolock lock(mLock);
-    if (mTrack == 0) return NO_INIT;
-    ExtendedTimestamp ets;
-    status_t status = mTrack->getTimestamp(&ets);
-    if (status == OK || status == WOULD_BLOCK) {
-        *frameswritten = (uint32_t)ets.mPosition[ExtendedTimestamp::LOCATION_CLIENT];
-    }
-    return status;
-}
-
-status_t MediaPlayer2Manager::AudioOutput::setParameters(const String8& keyValuePairs)
-{
-    Mutex::Autolock lock(mLock);
-    if (mTrack == 0) return NO_INIT;
-    return mTrack->setParameters(keyValuePairs);
-}
-
-String8  MediaPlayer2Manager::AudioOutput::getParameters(const String8& keys)
-{
-    Mutex::Autolock lock(mLock);
-    if (mTrack == 0) return String8::empty();
-    return mTrack->getParameters(keys);
-}
-
-void MediaPlayer2Manager::AudioOutput::setAudioAttributes(const audio_attributes_t * attributes) {
-    Mutex::Autolock lock(mLock);
-    if (attributes == NULL) {
-        free(mAttributes);
-        mAttributes = NULL;
-    } else {
-        if (mAttributes == NULL) {
-            mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
-        }
-        memcpy(mAttributes, attributes, sizeof(audio_attributes_t));
-        mStreamType = audio_attributes_to_stream_type(attributes);
-    }
-}
-
-void MediaPlayer2Manager::AudioOutput::setAudioStreamType(audio_stream_type_t streamType)
-{
-    Mutex::Autolock lock(mLock);
-    // do not allow direct stream type modification if attributes have been set
-    if (mAttributes == NULL) {
-        mStreamType = streamType;
-    }
-}
-
-void MediaPlayer2Manager::AudioOutput::deleteRecycledTrack_l()
-{
-    ALOGV("deleteRecycledTrack_l");
-    if (mRecycledTrack != 0) {
-
-        if (mCallbackData != NULL) {
-            mCallbackData->setOutput(NULL);
-            mCallbackData->endTrackSwitch();
-        }
-
-        if ((mRecycledTrack->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) {
-            int32_t msec = 0;
-            if (!mRecycledTrack->stopped()) { // check if active
-                 (void)mRecycledTrack->pendingDuration(&msec);
-            }
-            mRecycledTrack->stop(); // ensure full data drain
-            ALOGD("deleting recycled track, waiting for data drain (%d msec)", msec);
-            if (msec > 0) {
-                static const int32_t WAIT_LIMIT_MS = 3000;
-                if (msec > WAIT_LIMIT_MS) {
-                    msec = WAIT_LIMIT_MS;
-                }
-                usleep(msec * 1000LL);
-            }
-        }
-        // An offloaded track isn't flushed because the STREAM_END is reported
-        // slightly prematurely to allow time for the gapless track switch
-        // but this means that if we decide not to recycle the track there
-        // could be a small amount of residual data still playing. We leave
-        // AudioFlinger to drain the track.
-
-        mRecycledTrack.clear();
-        close_l();
-        delete mCallbackData;
-        mCallbackData = NULL;
-    }
-}
-
-void MediaPlayer2Manager::AudioOutput::close_l()
-{
-    mTrack.clear();
-}
-
-status_t MediaPlayer2Manager::AudioOutput::open(
-        uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
-        audio_format_t format, int bufferCount,
-        AudioCallback cb, void *cookie,
-        audio_output_flags_t flags,
-        const audio_offload_info_t *offloadInfo,
-        bool doNotReconnect,
-        uint32_t suggestedFrameCount)
-{
-    ALOGV("open(%u, %d, 0x%x, 0x%x, %d, %d 0x%x)", sampleRate, channelCount, channelMask,
-                format, bufferCount, mSessionId, flags);
-
-    // offloading is only supported in callback mode for now.
-    // offloadInfo must be present if offload flag is set
-    if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) &&
-            ((cb == NULL) || (offloadInfo == NULL))) {
-        return BAD_VALUE;
-    }
-
-    // compute frame count for the AudioTrack internal buffer
-    size_t frameCount;
-    if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
-        frameCount = 0; // AudioTrack will get frame count from AudioFlinger
-    } else {
-        // try to estimate the buffer processing fetch size from AudioFlinger.
-        // framesPerBuffer is approximate and generally correct, except when it's not :-).
-        uint32_t afSampleRate;
-        size_t afFrameCount;
-        if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
-            return NO_INIT;
-        }
-        if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
-            return NO_INIT;
-        }
-        const size_t framesPerBuffer =
-                (unsigned long long)sampleRate * afFrameCount / afSampleRate;
-
-        if (bufferCount == 0) {
-            // use suggestedFrameCount
-            bufferCount = (suggestedFrameCount + framesPerBuffer - 1) / framesPerBuffer;
-        }
-        // Check argument bufferCount against the mininum buffer count
-        if (bufferCount != 0 && bufferCount < mMinBufferCount) {
-            ALOGV("bufferCount (%d) increased to %d", bufferCount, mMinBufferCount);
-            bufferCount = mMinBufferCount;
-        }
-        // if frameCount is 0, then AudioTrack will get frame count from AudioFlinger
-        // which will be the minimum size permitted.
-        frameCount = bufferCount * framesPerBuffer;
-    }
-
-    if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
-        channelMask = audio_channel_out_mask_from_count(channelCount);
-        if (0 == channelMask) {
-            ALOGE("open() error, can\'t derive mask for %d audio channels", channelCount);
-            return NO_INIT;
-        }
-    }
-
-    Mutex::Autolock lock(mLock);
-    mCallback = cb;
-    mCallbackCookie = cookie;
-
-    // Check whether we can recycle the track
-    bool reuse = false;
-    bool bothOffloaded = false;
-
-    if (mRecycledTrack != 0) {
-        // check whether we are switching between two offloaded tracks
-        bothOffloaded = (flags & mRecycledTrack->getFlags()
-                                & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0;
-
-        // check if the existing track can be reused as-is, or if a new track needs to be created.
-        reuse = true;
-
-        if ((mCallbackData == NULL && mCallback != NULL) ||
-                (mCallbackData != NULL && mCallback == NULL)) {
-            // recycled track uses callbacks but the caller wants to use writes, or vice versa
-            ALOGV("can't chain callback and write");
-            reuse = false;
-        } else if ((mRecycledTrack->getSampleRate() != sampleRate) ||
-                (mRecycledTrack->channelCount() != (uint32_t)channelCount) ) {
-            ALOGV("samplerate, channelcount differ: %u/%u Hz, %u/%d ch",
-                  mRecycledTrack->getSampleRate(), sampleRate,
-                  mRecycledTrack->channelCount(), channelCount);
-            reuse = false;
-        } else if (flags != mFlags) {
-            ALOGV("output flags differ %08x/%08x", flags, mFlags);
-            reuse = false;
-        } else if (mRecycledTrack->format() != format) {
-            reuse = false;
-        }
-    } else {
-        ALOGV("no track available to recycle");
-    }
-
-    ALOGV_IF(bothOffloaded, "both tracks offloaded");
-
-    // If we can't recycle and both tracks are offloaded
-    // we must close the previous output before opening a new one
-    if (bothOffloaded && !reuse) {
-        ALOGV("both offloaded and not recycling");
-        deleteRecycledTrack_l();
-    }
-
-    sp<AudioTrack> t;
-    CallbackData *newcbd = NULL;
-
-    // We don't attempt to create a new track if we are recycling an
-    // offloaded track. But, if we are recycling a non-offloaded or we
-    // are switching where one is offloaded and one isn't then we create
-    // the new track in advance so that we can read additional stream info
-
-    if (!(reuse && bothOffloaded)) {
-        ALOGV("creating new AudioTrack");
-
-        if (mCallback != NULL) {
-            newcbd = new CallbackData(this);
-            t = new AudioTrack(
-                    mStreamType,
-                    sampleRate,
-                    format,
-                    channelMask,
-                    frameCount,
-                    flags,
-                    CallbackWrapper,
-                    newcbd,
-                    0,  // notification frames
-                    mSessionId,
-                    AudioTrack::TRANSFER_CALLBACK,
-                    offloadInfo,
-                    mUid,
-                    mPid,
-                    mAttributes,
-                    doNotReconnect,
-                    1.0f,  // default value for maxRequiredSpeed
-                    mSelectedDeviceId);
-        } else {
-            // TODO: Due to buffer memory concerns, we use a max target playback speed
-            // based on mPlaybackRate at the time of open (instead of kMaxRequiredSpeed),
-            // also clamping the target speed to 1.0 <= targetSpeed <= kMaxRequiredSpeed.
-            const float targetSpeed =
-                    std::min(std::max(mPlaybackRate.mSpeed, 1.0f), kMaxRequiredSpeed);
-            ALOGW_IF(targetSpeed != mPlaybackRate.mSpeed,
-                    "track target speed:%f clamped from playback speed:%f",
-                    targetSpeed, mPlaybackRate.mSpeed);
-            t = new AudioTrack(
-                    mStreamType,
-                    sampleRate,
-                    format,
-                    channelMask,
-                    frameCount,
-                    flags,
-                    NULL, // callback
-                    NULL, // user data
-                    0, // notification frames
-                    mSessionId,
-                    AudioTrack::TRANSFER_DEFAULT,
-                    NULL, // offload info
-                    mUid,
-                    mPid,
-                    mAttributes,
-                    doNotReconnect,
-                    targetSpeed,
-                    mSelectedDeviceId);
-        }
-
-        if ((t == 0) || (t->initCheck() != NO_ERROR)) {
-            ALOGE("Unable to create audio track");
-            delete newcbd;
-            // t goes out of scope, so reference count drops to zero
-            return NO_INIT;
-        } else {
-            // successful AudioTrack initialization implies a legacy stream type was generated
-            // from the audio attributes
-            mStreamType = t->streamType();
-        }
-    }
-
-    if (reuse) {
-        CHECK(mRecycledTrack != NULL);
-
-        if (!bothOffloaded) {
-            if (mRecycledTrack->frameCount() != t->frameCount()) {
-                ALOGV("framecount differs: %zu/%zu frames",
-                      mRecycledTrack->frameCount(), t->frameCount());
-                reuse = false;
-            }
-        }
-
-        if (reuse) {
-            ALOGV("chaining to next output and recycling track");
-            close_l();
-            mTrack = mRecycledTrack;
-            mRecycledTrack.clear();
-            if (mCallbackData != NULL) {
-                mCallbackData->setOutput(this);
-            }
-            delete newcbd;
-            return updateTrack();
-        }
-    }
-
-    // we're not going to reuse the track, unblock and flush it
-    // this was done earlier if both tracks are offloaded
-    if (!bothOffloaded) {
-        deleteRecycledTrack_l();
-    }
-
-    CHECK((t != NULL) && ((mCallback == NULL) || (newcbd != NULL)));
-
-    mCallbackData = newcbd;
-    ALOGV("setVolume");
-    t->setVolume(mLeftVolume, mRightVolume);
-
-    mSampleRateHz = sampleRate;
-    mFlags = flags;
-    mMsecsPerFrame = 1E3f / (mPlaybackRate.mSpeed * sampleRate);
-    mFrameSize = t->frameSize();
-    mTrack = t;
-
-    return updateTrack();
-}
-
-status_t MediaPlayer2Manager::AudioOutput::updateTrack() {
-    if (mTrack == NULL) {
-        return NO_ERROR;
-    }
-
-    status_t res = NO_ERROR;
-    // Note some output devices may give us a direct track even though we don't specify it.
-    // Example: Line application b/17459982.
-    if ((mTrack->getFlags()
-            & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT)) == 0) {
-        res = mTrack->setPlaybackRate(mPlaybackRate);
-        if (res == NO_ERROR) {
-            mTrack->setAuxEffectSendLevel(mSendLevel);
-            res = mTrack->attachAuxEffect(mAuxEffectId);
-        }
-    }
-    mTrack->setOutputDevice(mSelectedDeviceId);
-    if (mDeviceCallbackEnabled) {
-        mTrack->addAudioDeviceCallback(mDeviceCallback.promote());
-    }
-    ALOGV("updateTrack() DONE status %d", res);
-    return res;
-}
-
-status_t MediaPlayer2Manager::AudioOutput::start()
-{
-    ALOGV("start");
-    Mutex::Autolock lock(mLock);
-    if (mCallbackData != NULL) {
-        mCallbackData->endTrackSwitch();
-    }
-    if (mTrack != 0) {
-        mTrack->setVolume(mLeftVolume, mRightVolume);
-        mTrack->setAuxEffectSendLevel(mSendLevel);
-        status_t status = mTrack->start();
-        return status;
-    }
-    return NO_INIT;
-}
-
-void MediaPlayer2Manager::AudioOutput::setNextOutput(const sp<AudioOutput>& nextOutput) {
-    Mutex::Autolock lock(mLock);
-    mNextOutput = nextOutput;
-}
-
-void MediaPlayer2Manager::AudioOutput::switchToNextOutput() {
-    ALOGV("switchToNextOutput");
-
-    // Try to acquire the callback lock before moving track (without incurring deadlock).
-    const unsigned kMaxSwitchTries = 100;
-    Mutex::Autolock lock(mLock);
-    for (unsigned tries = 0;;) {
-        if (mTrack == 0) {
-            return;
-        }
-        if (mNextOutput != NULL && mNextOutput != this) {
-            if (mCallbackData != NULL) {
-                // two alternative approaches
-#if 1
-                CallbackData *callbackData = mCallbackData;
-                mLock.unlock();
-                // proper acquisition sequence
-                callbackData->lock();
-                mLock.lock();
-                // Caution: it is unlikely that someone deleted our callback or changed our target
-                if (callbackData != mCallbackData || mNextOutput == NULL || mNextOutput == this) {
-                    // fatal if we are starved out.
-                    LOG_ALWAYS_FATAL_IF(++tries > kMaxSwitchTries,
-                            "switchToNextOutput() cannot obtain correct lock sequence");
-                    callbackData->unlock();
-                    continue;
-                }
-                callbackData->mSwitching = true; // begin track switch
-                callbackData->setOutput(NULL);
-#else
-                // tryBeginTrackSwitch() returns false if the callback has the lock.
-                if (!mCallbackData->tryBeginTrackSwitch()) {
-                    // fatal if we are starved out.
-                    LOG_ALWAYS_FATAL_IF(++tries > kMaxSwitchTries,
-                            "switchToNextOutput() cannot obtain callback lock");
-                    mLock.unlock();
-                    usleep(5 * 1000 /* usec */); // allow callback to use AudioOutput
-                    mLock.lock();
-                    continue;
-                }
-#endif
-            }
-
-            Mutex::Autolock nextLock(mNextOutput->mLock);
-
-            // If the next output track is not NULL, then it has been
-            // opened already for playback.
-            // This is possible even without the next player being started,
-            // for example, the next player could be prepared and seeked.
-            //
-            // Presuming it isn't advisable to force the track over.
-             if (mNextOutput->mTrack == NULL) {
-                ALOGD("Recycling track for gapless playback");
-                delete mNextOutput->mCallbackData;
-                mNextOutput->mCallbackData = mCallbackData;
-                mNextOutput->mRecycledTrack = mTrack;
-                mNextOutput->mSampleRateHz = mSampleRateHz;
-                mNextOutput->mMsecsPerFrame = mMsecsPerFrame;
-                mNextOutput->mFlags = mFlags;
-                mNextOutput->mFrameSize = mFrameSize;
-                close_l();
-                mCallbackData = NULL;  // destruction handled by mNextOutput
-            } else {
-                ALOGW("Ignoring gapless playback because next player has already started");
-                // remove track in case resource needed for future players.
-                if (mCallbackData != NULL) {
-                    mCallbackData->endTrackSwitch();  // release lock for callbacks before close.
-                }
-                close_l();
-            }
-        }
-        break;
-    }
-}
-
-ssize_t MediaPlayer2Manager::AudioOutput::write(const void* buffer, size_t size, bool blocking)
-{
-    Mutex::Autolock lock(mLock);
-    LOG_ALWAYS_FATAL_IF(mCallback != NULL, "Don't call write if supplying a callback.");
-
-    //ALOGV("write(%p, %u)", buffer, size);
-    if (mTrack != 0) {
-        return mTrack->write(buffer, size, blocking);
-    }
-    return NO_INIT;
-}
-
-void MediaPlayer2Manager::AudioOutput::stop()
-{
-    ALOGV("stop");
-    Mutex::Autolock lock(mLock);
-    if (mTrack != 0) mTrack->stop();
-}
-
-void MediaPlayer2Manager::AudioOutput::flush()
-{
-    ALOGV("flush");
-    Mutex::Autolock lock(mLock);
-    if (mTrack != 0) mTrack->flush();
-}
-
-void MediaPlayer2Manager::AudioOutput::pause()
-{
-    ALOGV("pause");
-    Mutex::Autolock lock(mLock);
-    if (mTrack != 0) mTrack->pause();
-}
-
-void MediaPlayer2Manager::AudioOutput::close()
-{
-    ALOGV("close");
-    sp<AudioTrack> track;
-    {
-        Mutex::Autolock lock(mLock);
-        track = mTrack;
-        close_l(); // clears mTrack
-    }
-    // destruction of the track occurs outside of mutex.
-}
-
-void MediaPlayer2Manager::AudioOutput::setVolume(float left, float right)
-{
-    ALOGV("setVolume(%f, %f)", left, right);
-    Mutex::Autolock lock(mLock);
-    mLeftVolume = left;
-    mRightVolume = right;
-    if (mTrack != 0) {
-        mTrack->setVolume(left, right);
-    }
-}
-
-status_t MediaPlayer2Manager::AudioOutput::setPlaybackRate(const AudioPlaybackRate &rate)
-{
-    ALOGV("setPlaybackRate(%f %f %d %d)",
-                rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
-    Mutex::Autolock lock(mLock);
-    if (mTrack == 0) {
-        // remember rate so that we can set it when the track is opened
-        mPlaybackRate = rate;
-        return OK;
-    }
-    status_t res = mTrack->setPlaybackRate(rate);
-    if (res != NO_ERROR) {
-        return res;
-    }
-    // rate.mSpeed is always greater than 0 if setPlaybackRate succeeded
-    CHECK_GT(rate.mSpeed, 0.f);
-    mPlaybackRate = rate;
-    if (mSampleRateHz != 0) {
-        mMsecsPerFrame = 1E3f / (rate.mSpeed * mSampleRateHz);
-    }
-    return res;
-}
-
-status_t MediaPlayer2Manager::AudioOutput::getPlaybackRate(AudioPlaybackRate *rate)
-{
-    ALOGV("setPlaybackRate");
-    Mutex::Autolock lock(mLock);
-    if (mTrack == 0) {
-        return NO_INIT;
-    }
-    *rate = mTrack->getPlaybackRate();
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2Manager::AudioOutput::setAuxEffectSendLevel(float level)
-{
-    ALOGV("setAuxEffectSendLevel(%f)", level);
-    Mutex::Autolock lock(mLock);
-    mSendLevel = level;
-    if (mTrack != 0) {
-        return mTrack->setAuxEffectSendLevel(level);
-    }
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2Manager::AudioOutput::attachAuxEffect(int effectId)
-{
-    ALOGV("attachAuxEffect(%d)", effectId);
-    Mutex::Autolock lock(mLock);
-    mAuxEffectId = effectId;
-    if (mTrack != 0) {
-        return mTrack->attachAuxEffect(effectId);
-    }
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2Manager::AudioOutput::setOutputDevice(audio_port_handle_t deviceId)
-{
-    ALOGV("setOutputDevice(%d)", deviceId);
-    Mutex::Autolock lock(mLock);
-    mSelectedDeviceId = deviceId;
-    if (mTrack != 0) {
-        return mTrack->setOutputDevice(deviceId);
-    }
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2Manager::AudioOutput::getRoutedDeviceId(audio_port_handle_t* deviceId)
-{
-    ALOGV("getRoutedDeviceId");
-    Mutex::Autolock lock(mLock);
-    if (mTrack != 0) {
-        mRoutedDeviceId = mTrack->getRoutedDeviceId();
-    }
-    *deviceId = mRoutedDeviceId;
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2Manager::AudioOutput::enableAudioDeviceCallback(bool enabled)
-{
-    ALOGV("enableAudioDeviceCallback, %d", enabled);
-    Mutex::Autolock lock(mLock);
-    mDeviceCallbackEnabled = enabled;
-    if (mTrack != 0) {
-        status_t status;
-        if (enabled) {
-            status = mTrack->addAudioDeviceCallback(mDeviceCallback.promote());
-        } else {
-            status = mTrack->removeAudioDeviceCallback(mDeviceCallback.promote());
-        }
-        return status;
-    }
-    return NO_ERROR;
-}
-
-// static
-void MediaPlayer2Manager::AudioOutput::CallbackWrapper(
-        int event, void *cookie, void *info) {
-    //ALOGV("callbackwrapper");
-    CallbackData *data = (CallbackData*)cookie;
-    // lock to ensure we aren't caught in the middle of a track switch.
-    data->lock();
-    AudioOutput *me = data->getOutput();
-    AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
-    if (me == NULL) {
-        // no output set, likely because the track was scheduled to be reused
-        // by another player, but the format turned out to be incompatible.
-        data->unlock();
-        if (buffer != NULL) {
-            buffer->size = 0;
-        }
-        return;
-    }
-
-    switch(event) {
-    case AudioTrack::EVENT_MORE_DATA: {
-        size_t actualSize = (*me->mCallback)(
-                me, buffer->raw, buffer->size, me->mCallbackCookie,
-                CB_EVENT_FILL_BUFFER);
-
-        // Log when no data is returned from the callback.
-        // (1) We may have no data (especially with network streaming sources).
-        // (2) We may have reached the EOS and the audio track is not stopped yet.
-        // Note that AwesomePlayer/AudioPlayer will only return zero size when it reaches the EOS.
-        // NuPlayer2Renderer will return zero when it doesn't have data (it doesn't block to fill).
-        //
-        // This is a benign busy-wait, with the next data request generated 10 ms or more later;
-        // nevertheless for power reasons, we don't want to see too many of these.
-
-        ALOGV_IF(actualSize == 0 && buffer->size > 0, "callbackwrapper: empty buffer returned");
-
-        buffer->size = actualSize;
-        } break;
-
-    case AudioTrack::EVENT_STREAM_END:
-        // currently only occurs for offloaded callbacks
-        ALOGV("callbackwrapper: deliver EVENT_STREAM_END");
-        (*me->mCallback)(me, NULL /* buffer */, 0 /* size */,
-                me->mCallbackCookie, CB_EVENT_STREAM_END);
-        break;
-
-    case AudioTrack::EVENT_NEW_IAUDIOTRACK :
-        ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN");
-        (*me->mCallback)(me,  NULL /* buffer */, 0 /* size */,
-                me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
-        break;
-
-    case AudioTrack::EVENT_UNDERRUN:
-        // This occurs when there is no data available, typically
-        // when there is a failure to supply data to the AudioTrack.  It can also
-        // occur in non-offloaded mode when the audio device comes out of standby.
-        //
-        // If an AudioTrack underruns it outputs silence. Since this happens suddenly
-        // it may sound like an audible pop or glitch.
-        //
-        // The underrun event is sent once per track underrun; the condition is reset
-        // when more data is sent to the AudioTrack.
-        ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)");
-        break;
-
-    default:
-        ALOGE("received unknown event type: %d inside CallbackWrapper !", event);
-    }
-
-    data->unlock();
-}
-
-audio_session_t MediaPlayer2Manager::AudioOutput::getSessionId() const
-{
-    Mutex::Autolock lock(mLock);
-    return mSessionId;
-}
-
-uint32_t MediaPlayer2Manager::AudioOutput::getSampleRate() const
-{
-    Mutex::Autolock lock(mLock);
-    if (mTrack == 0) return 0;
-    return mTrack->getSampleRate();
-}
-
-int64_t MediaPlayer2Manager::AudioOutput::getBufferDurationInUs() const
-{
-    Mutex::Autolock lock(mLock);
-    if (mTrack == 0) {
-        return 0;
-    }
-    int64_t duration;
-    if (mTrack->getBufferDurationInUs(&duration) != OK) {
-        return 0;
-    }
-    return duration;
-}
-
-} // namespace android
diff --git a/media/libmediaplayer2/MediaPlayer2Manager.h b/media/libmediaplayer2/MediaPlayer2Manager.h
deleted file mode 100644
index 52bb9c6..0000000
--- a/media/libmediaplayer2/MediaPlayer2Manager.h
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
-**
-** Copyright 2017, 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_MEDIAPLAYER2MANAGER_H
-#define ANDROID_MEDIAPLAYER2MANAGER_H
-
-#include <arpa/inet.h>
-
-#include <utils/threads.h>
-#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
-#include <utils/String8.h>
-#include <utils/Vector.h>
-
-#include <media/Metadata.h>
-#include <media/stagefright/foundation/ABase.h>
-#include <mediaplayer2/MediaPlayer2Engine.h>
-#include <mediaplayer2/MediaPlayer2Interface.h>
-
-#include <system/audio.h>
-
-namespace android {
-
-struct ANativeWindowWrapper;
-struct AudioPlaybackRate;
-class AudioTrack;
-struct AVSyncSettings;
-class DataSource;
-struct MediaHTTPService;
-class MediaPlayer2EngineClient;
-
-#define CALLBACK_ANTAGONIZER 0
-#if CALLBACK_ANTAGONIZER
-class Antagonizer {
-public:
-    Antagonizer(
-            MediaPlayer2Interface::NotifyCallback cb,
-            const wp<MediaPlayer2Engine> &client);
-    void start() { mActive = true; }
-    void stop() { mActive = false; }
-    void kill();
-private:
-    static const int interval;
-    Antagonizer();
-    static int callbackThread(void *cookie);
-    Mutex                            mLock;
-    Condition                        mCondition;
-    bool                             mExit;
-    bool                             mActive;
-    wp<MediaPlayer2Engine>           mClient;
-    MediaPlayer2Interface::NotifyCallback mCb;
-};
-#endif
-
-class MediaPlayer2Manager {
-    class Client;
-
-    class AudioOutput : public MediaPlayer2Interface::AudioSink
-    {
-        class CallbackData;
-
-     public:
-                                AudioOutput(
-                                        audio_session_t sessionId,
-                                        uid_t uid,
-                                        int pid,
-                                        const audio_attributes_t * attr,
-                                        const sp<AudioSystem::AudioDeviceCallback>& deviceCallback);
-        virtual                 ~AudioOutput();
-
-        virtual bool            ready() const { return mTrack != 0; }
-        virtual ssize_t         bufferSize() const;
-        virtual ssize_t         frameCount() const;
-        virtual ssize_t         channelCount() const;
-        virtual ssize_t         frameSize() const;
-        virtual uint32_t        latency() const;
-        virtual float           msecsPerFrame() const;
-        virtual status_t        getPosition(uint32_t *position) const;
-        virtual status_t        getTimestamp(AudioTimestamp &ts) const;
-        virtual int64_t         getPlayedOutDurationUs(int64_t nowUs) const;
-        virtual status_t        getFramesWritten(uint32_t *frameswritten) const;
-        virtual audio_session_t getSessionId() const;
-        virtual uint32_t        getSampleRate() const;
-        virtual int64_t         getBufferDurationInUs() const;
-
-        virtual status_t        open(
-                uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
-                audio_format_t format, int bufferCount,
-                AudioCallback cb, void *cookie,
-                audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
-                const audio_offload_info_t *offloadInfo = NULL,
-                bool doNotReconnect = false,
-                uint32_t suggestedFrameCount = 0);
-
-        virtual status_t        start();
-        virtual ssize_t         write(const void* buffer, size_t size, bool blocking = true);
-        virtual void            stop();
-        virtual void            flush();
-        virtual void            pause();
-        virtual void            close();
-                void            setAudioStreamType(audio_stream_type_t streamType);
-        virtual audio_stream_type_t getAudioStreamType() const { return mStreamType; }
-                void            setAudioAttributes(const audio_attributes_t * attributes);
-
-                void            setVolume(float left, float right);
-        virtual status_t        setPlaybackRate(const AudioPlaybackRate& rate);
-        virtual status_t        getPlaybackRate(AudioPlaybackRate* rate /* nonnull */);
-
-                status_t        setAuxEffectSendLevel(float level);
-                status_t        attachAuxEffect(int effectId);
-        virtual status_t        dump(int fd, const Vector<String16>& args) const;
-
-        static bool             isOnEmulator();
-        static int              getMinBufferCount();
-                void            setNextOutput(const sp<AudioOutput>& nextOutput);
-                void            switchToNextOutput();
-        virtual bool            needsTrailingPadding() { return mNextOutput == NULL; }
-        virtual status_t        setParameters(const String8& keyValuePairs);
-        virtual String8         getParameters(const String8& keys);
-
-        // AudioRouting
-        virtual status_t        setOutputDevice(audio_port_handle_t deviceId);
-        virtual status_t        getRoutedDeviceId(audio_port_handle_t* deviceId);
-        virtual status_t        enableAudioDeviceCallback(bool enabled);
-
-    private:
-        static void             setMinBufferCount();
-        static void             CallbackWrapper(
-                int event, void *me, void *info);
-               void             deleteRecycledTrack_l();
-               void             close_l();
-           status_t             updateTrack();
-
-        sp<AudioTrack>          mTrack;
-        sp<AudioTrack>          mRecycledTrack;
-        sp<AudioOutput>         mNextOutput;
-        AudioCallback           mCallback;
-        void *                  mCallbackCookie;
-        CallbackData *          mCallbackData;
-        audio_stream_type_t     mStreamType;
-        audio_attributes_t *    mAttributes;
-        float                   mLeftVolume;
-        float                   mRightVolume;
-        AudioPlaybackRate       mPlaybackRate;
-        uint32_t                mSampleRateHz; // sample rate of the content, as set in open()
-        float                   mMsecsPerFrame;
-        size_t                  mFrameSize;
-        audio_session_t         mSessionId;
-        uid_t                   mUid;
-        int                     mPid;
-        float                   mSendLevel;
-        int                     mAuxEffectId;
-        audio_output_flags_t    mFlags;
-        audio_port_handle_t     mSelectedDeviceId;
-        audio_port_handle_t     mRoutedDeviceId;
-        bool                    mDeviceCallbackEnabled;
-        wp<AudioSystem::AudioDeviceCallback>        mDeviceCallback;
-        mutable Mutex           mLock;
-
-        // static variables below not protected by mutex
-        static bool             mIsOnEmulator;
-        static int              mMinBufferCount;  // 12 for emulator; otherwise 4
-
-        // CallbackData is what is passed to the AudioTrack as the "user" data.
-        // We need to be able to target this to a different Output on the fly,
-        // so we can't use the Output itself for this.
-        class CallbackData {
-            friend AudioOutput;
-        public:
-            explicit CallbackData(AudioOutput *cookie) {
-                mData = cookie;
-                mSwitching = false;
-            }
-            AudioOutput *   getOutput() const { return mData; }
-            void            setOutput(AudioOutput* newcookie) { mData = newcookie; }
-            // lock/unlock are used by the callback before accessing the payload of this object
-            void            lock() const { mLock.lock(); }
-            void            unlock() const { mLock.unlock(); }
-
-            // tryBeginTrackSwitch/endTrackSwitch are used when the CallbackData is handed over
-            // to the next sink.
-
-            // tryBeginTrackSwitch() returns true only if it obtains the lock.
-            bool            tryBeginTrackSwitch() {
-                LOG_ALWAYS_FATAL_IF(mSwitching, "tryBeginTrackSwitch() already called");
-                if (mLock.tryLock() != OK) {
-                    return false;
-                }
-                mSwitching = true;
-                return true;
-            }
-            void            endTrackSwitch() {
-                if (mSwitching) {
-                    mLock.unlock();
-                }
-                mSwitching = false;
-            }
-        private:
-            AudioOutput *   mData;
-            mutable Mutex   mLock; // a recursive mutex might make this unnecessary.
-            bool            mSwitching;
-            DISALLOW_EVIL_CONSTRUCTORS(CallbackData);
-        };
-
-    }; // AudioOutput
-
-
-public:
-    MediaPlayer2Manager();
-    virtual ~MediaPlayer2Manager();
-
-    static MediaPlayer2Manager& get();
-
-    // MediaPlayer2Manager interface
-    virtual sp<MediaPlayer2Engine> create(const sp<MediaPlayer2EngineClient>& client,
-                                          audio_session_t audioSessionId);
-
-    virtual status_t            dump(int fd, const Vector<String16>& args);
-
-            void                removeClient(const wp<Client>& client);
-            bool                hasClient(wp<Client> client);
-
-private:
-    class Client : public MediaPlayer2Engine {
-        // MediaPlayer2Engine interface
-        virtual void            disconnect();
-        virtual status_t        setVideoSurfaceTexture(
-                const sp<ANativeWindowWrapper>& nww) override;
-        virtual status_t        setBufferingSettings(const BufferingSettings& buffering) override;
-        virtual status_t        getBufferingSettings(
-                                        BufferingSettings* buffering /* nonnull */) override;
-        virtual status_t        prepareAsync();
-        virtual status_t        start();
-        virtual status_t        stop();
-        virtual status_t        pause();
-        virtual status_t        isPlaying(bool* state);
-        virtual status_t        setPlaybackSettings(const AudioPlaybackRate& rate);
-        virtual status_t        getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */);
-        virtual status_t        setSyncSettings(const AVSyncSettings& rate, float videoFpsHint);
-        virtual status_t        getSyncSettings(AVSyncSettings* rate /* nonnull */,
-                                                float* videoFps /* nonnull */);
-        virtual status_t        seekTo(
-                int msec,
-                MediaPlayer2SeekMode mode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC);
-        virtual status_t        getCurrentPosition(int* msec);
-        virtual status_t        getDuration(int* msec);
-        virtual status_t        reset();
-        virtual status_t        notifyAt(int64_t mediaTimeUs);
-        virtual status_t        setAudioStreamType(audio_stream_type_t type);
-        virtual status_t        setLooping(int loop);
-        virtual status_t        setVolume(float leftVolume, float rightVolume);
-        virtual status_t        invoke(const Parcel& request, Parcel *reply);
-        virtual status_t        setMetadataFilter(const Parcel& filter);
-        virtual status_t        getMetadata(bool update_only,
-                                            bool apply_filter,
-                                            Parcel *reply);
-        virtual status_t        setAuxEffectSendLevel(float level);
-        virtual status_t        attachAuxEffect(int effectId);
-        virtual status_t        setParameter(int key, const Parcel &request);
-        virtual status_t        getParameter(int key, Parcel *reply);
-        virtual status_t        setNextPlayer(const sp<MediaPlayer2Engine>& player);
-
-        virtual status_t        setDataSource(const sp<DataSourceDesc> &dsd) override;
-        virtual status_t        prepareNextDataSource(const sp<DataSourceDesc> &dsd) override;
-        virtual status_t        playNextDataSource(int64_t srcId) override;
-
-        static  void            notify(const wp<MediaPlayer2Engine> &listener, int64_t srcId,
-                                       int msg, int ext1, int ext2, const Parcel *obj);
-
-                pid_t           pid() const { return mPid; }
-        virtual status_t        dump(int fd, const Vector<String16>& args);
-
-                audio_session_t getAudioSessionId() { return mAudioSessionId; }
-        // Modular DRM
-        virtual status_t prepareDrm(const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId);
-        virtual status_t releaseDrm();
-        // AudioRouting
-        virtual status_t setOutputDevice(audio_port_handle_t deviceId);
-        virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId);
-        virtual status_t enableAudioDeviceCallback(bool enabled);
-
-    private:
-        class AudioDeviceUpdatedNotifier: public AudioSystem::AudioDeviceCallback
-        {
-        public:
-            AudioDeviceUpdatedNotifier(const sp<MediaPlayer2Interface>& listener) {
-                mListener = listener;
-            }
-            ~AudioDeviceUpdatedNotifier() {}
-
-            virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
-                                             audio_port_handle_t deviceId);
-
-        private:
-            wp<MediaPlayer2Interface> mListener;
-        };
-
-        friend class MediaPlayer2Manager;
-                                Client(pid_t pid,
-                                       int32_t connId,
-                                       const sp<MediaPlayer2EngineClient>& client,
-                                       audio_session_t audioSessionId,
-                                       uid_t uid);
-                                Client();
-        virtual                 ~Client();
-        bool init();
-
-                void            deletePlayer();
-
-        sp<MediaPlayer2Interface> getPlayer() const { Mutex::Autolock lock(mLock); return mPlayer; }
-
-
-
-        // @param type Of the metadata to be tested.
-        // @return true if the metadata should be dropped according to
-        //              the filters.
-        bool shouldDropMetadata(media::Metadata::Type type) const;
-
-        // Add a new element to the set of metadata updated. Noop if
-        // the element exists already.
-        // @param type Of the metadata to be recorded.
-        void addNewMetadataUpdate(media::Metadata::Type type);
-
-        // Disconnect from the currently connected ANativeWindow.
-        void disconnectNativeWindow_l();
-
-        status_t setAudioAttributes_l(const Parcel &request);
-
-        mutable     Mutex                        mLock;
-                    sp<MediaPlayer2Interface>    mPlayer;
-                    sp<MediaPlayer2EngineClient> mClient;
-                    sp<AudioOutput>              mAudioOutput;
-                    pid_t                        mPid;
-                    status_t                     mStatus;
-                    bool                         mLoop;
-                    int32_t                      mConnId;
-                    audio_session_t              mAudioSessionId;
-                    audio_attributes_t *         mAudioAttributes;
-                    uid_t                        mUid;
-                    sp<ANativeWindowWrapper>     mConnectedWindow;
-                    sp<Client>                   mNextClient;
-
-        // Metadata filters.
-        media::Metadata::Filter mMetadataAllow;  // protected by mLock
-        media::Metadata::Filter mMetadataDrop;  // protected by mLock
-
-        // Metadata updated. For each MEDIA_INFO_METADATA_UPDATE
-        // notification we try to update mMetadataUpdated which is a
-        // set: no duplicate.
-        // getMetadata clears this set.
-        media::Metadata::Filter mMetadataUpdated;  // protected by mLock
-
-        sp<AudioDeviceUpdatedNotifier> mAudioDeviceUpdatedListener;
-#if CALLBACK_ANTAGONIZER
-                    Antagonizer*                mAntagonizer;
-#endif
-    }; // Client
-
-// ----------------------------------------------------------------------------
-
-    pid_t mPid;
-    uid_t mUid;
-
-    mutable Mutex mLock;
-    SortedVector< wp<Client> > mClients;
-    int32_t mNextConnId;
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_MEDIAPLAYER2MANAGER_H
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h
new file mode 100644
index 0000000..ad4937a
--- /dev/null
+++ b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h
@@ -0,0 +1,192 @@
+/*
+**
+** Copyright 2018, 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_MEDIAPLAYER2AUDIOOUTPUT_H
+#define ANDROID_MEDIAPLAYER2AUDIOOUTPUT_H
+
+#include <mediaplayer2/MediaPlayer2Interface.h>
+
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+class AudioTrack;
+
+class MediaPlayer2AudioOutput : public MediaPlayer2Interface::AudioSink
+{
+    class CallbackData;
+
+public:
+    MediaPlayer2AudioOutput(audio_session_t sessionId,
+                            uid_t uid,
+                            int pid,
+                            const audio_attributes_t * attr,
+                            const sp<AudioSystem::AudioDeviceCallback>& deviceCallback);
+    virtual ~MediaPlayer2AudioOutput();
+
+    virtual bool ready() const {
+        return mTrack != 0;
+    }
+    virtual ssize_t bufferSize() const;
+    virtual ssize_t frameCount() const;
+    virtual ssize_t channelCount() const;
+    virtual ssize_t frameSize() const;
+    virtual uint32_t latency() const;
+    virtual float msecsPerFrame() const;
+    virtual status_t getPosition(uint32_t *position) const;
+    virtual status_t getTimestamp(AudioTimestamp &ts) const;
+    virtual int64_t getPlayedOutDurationUs(int64_t nowUs) const;
+    virtual status_t getFramesWritten(uint32_t *frameswritten) const;
+    virtual audio_session_t getSessionId() const;
+    virtual uint32_t getSampleRate() const;
+    virtual int64_t getBufferDurationInUs() const;
+
+    virtual status_t open(
+            uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
+            audio_format_t format, int bufferCount,
+            AudioCallback cb, void *cookie,
+            audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
+            const audio_offload_info_t *offloadInfo = NULL,
+            bool doNotReconnect = false,
+            uint32_t suggestedFrameCount = 0);
+
+    virtual status_t start();
+    virtual ssize_t write(const void* buffer, size_t size, bool blocking = true);
+    virtual void stop();
+    virtual void flush();
+    virtual void pause();
+    virtual void close();
+    void setAudioStreamType(audio_stream_type_t streamType);
+    virtual audio_stream_type_t getAudioStreamType() const {
+        return mStreamType;
+    }
+    void setAudioAttributes(const audio_attributes_t * attributes);
+
+    void setVolume(float left, float right);
+    virtual status_t setPlaybackRate(const AudioPlaybackRate& rate);
+    virtual status_t getPlaybackRate(AudioPlaybackRate* rate /* nonnull */);
+
+    status_t setAuxEffectSendLevel(float level);
+    status_t attachAuxEffect(int effectId);
+    virtual status_t dump(int fd, const Vector<String16>& args) const;
+
+    static bool isOnEmulator();
+    static int getMinBufferCount();
+    void setNextOutput(const sp<MediaPlayer2AudioOutput>& nextOutput);
+    virtual bool needsTrailingPadding() {
+        return true;
+        // TODO: return correct value.
+        //return mNextOutput == NULL;
+    }
+    virtual status_t setParameters(const String8& keyValuePairs);
+    virtual String8 getParameters(const String8& keys);
+
+    // AudioRouting
+    virtual status_t setOutputDevice(audio_port_handle_t deviceId);
+    virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId);
+    virtual status_t enableAudioDeviceCallback(bool enabled);
+
+private:
+    static void setMinBufferCount();
+    static void CallbackWrapper(int event, void *me, void *info);
+    void deleteRecycledTrack_l();
+    void close_l();
+    status_t updateTrack_l();
+
+    sp<AudioTrack>          mTrack;
+    AudioCallback           mCallback;
+    void *                  mCallbackCookie;
+    CallbackData *          mCallbackData;
+    audio_stream_type_t     mStreamType;
+    audio_attributes_t *    mAttributes;
+    float                   mLeftVolume;
+    float                   mRightVolume;
+    AudioPlaybackRate       mPlaybackRate;
+    uint32_t                mSampleRateHz; // sample rate of the content, as set in open()
+    float                   mMsecsPerFrame;
+    size_t                  mFrameSize;
+    audio_session_t         mSessionId;
+    uid_t                   mUid;
+    int                     mPid;
+    float                   mSendLevel;
+    int                     mAuxEffectId;
+    audio_output_flags_t    mFlags;
+    audio_port_handle_t     mSelectedDeviceId;
+    audio_port_handle_t     mRoutedDeviceId;
+    bool                    mDeviceCallbackEnabled;
+    wp<AudioSystem::AudioDeviceCallback>        mDeviceCallback;
+    mutable Mutex           mLock;
+
+    // static variables below not protected by mutex
+    static bool             mIsOnEmulator;
+    static int              mMinBufferCount;  // 12 for emulator; otherwise 4
+
+    // CallbackData is what is passed to the AudioTrack as the "user" data.
+    // We need to be able to target this to a different Output on the fly,
+    // so we can't use the Output itself for this.
+    class CallbackData {
+        friend MediaPlayer2AudioOutput;
+    public:
+        explicit CallbackData(MediaPlayer2AudioOutput *cookie) {
+            mData = cookie;
+            mSwitching = false;
+        }
+        MediaPlayer2AudioOutput *getOutput() const {
+            return mData;
+        }
+        void setOutput(MediaPlayer2AudioOutput* newcookie) {
+            mData = newcookie;
+        }
+        // lock/unlock are used by the callback before accessing the payload of this object
+        void lock() const {
+            mLock.lock();
+        }
+        void unlock() const {
+            mLock.unlock();
+        }
+
+        // tryBeginTrackSwitch/endTrackSwitch are used when the CallbackData is handed over
+        // to the next sink.
+
+        // tryBeginTrackSwitch() returns true only if it obtains the lock.
+        bool tryBeginTrackSwitch() {
+            LOG_ALWAYS_FATAL_IF(mSwitching, "tryBeginTrackSwitch() already called");
+            if (mLock.tryLock() != OK) {
+                return false;
+            }
+            mSwitching = true;
+            return true;
+        }
+        void endTrackSwitch() {
+            if (mSwitching) {
+                mLock.unlock();
+            }
+            mSwitching = false;
+        }
+
+    private:
+        MediaPlayer2AudioOutput *mData;
+        mutable Mutex mLock; // a recursive mutex might make this unnecessary.
+        bool mSwitching;
+        DISALLOW_EVIL_CONSTRUCTORS(CallbackData);
+    };
+};
+
+}; // namespace android
+
+#endif // ANDROID_MEDIAPLAYER2AUDIOOUTPUT_H
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Engine.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Engine.h
deleted file mode 100644
index 749d83c..0000000
--- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Engine.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2017 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_MEDIAPLAYER2ENGINE_H
-#define ANDROID_MEDIAPLAYER2ENGINE_H
-
-#include <utils/RefBase.h>
-#include <binder/Parcel.h>
-#include <utils/KeyedVector.h>
-#include <system/audio.h>
-
-#include <media/MediaSource.h>
-
-// Fwd decl to make sure everyone agrees that the scope of struct sockaddr_in is
-// global, and not in android::
-struct sockaddr_in;
-
-namespace android {
-
-struct ANativeWindowWrapper;
-struct AVSyncSettings;
-struct AudioPlaybackRate;
-struct BufferingSettings;
-class DataSource;
-struct DataSourceDesc;
-struct IStreamSource;
-struct MediaHTTPService;
-class Parcel;
-
-typedef MediaSource::ReadOptions::SeekMode MediaPlayer2SeekMode;
-
-class MediaPlayer2Engine: public RefBase
-{
-public:
-    virtual void            disconnect() = 0;
-
-    virtual status_t        setDataSource(const sp<DataSourceDesc>& source) = 0;
-    virtual status_t        prepareNextDataSource(const sp<DataSourceDesc>& source) = 0;
-    virtual status_t        playNextDataSource(int64_t srcId) = 0;
-    virtual status_t        setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww) = 0;
-    virtual status_t        getBufferingSettings(
-                                    BufferingSettings* buffering /* nonnull */) = 0;
-    virtual status_t        setBufferingSettings(const BufferingSettings& buffering) = 0;
-    virtual status_t        prepareAsync() = 0;
-    virtual status_t        start() = 0;
-    virtual status_t        stop() = 0;
-    virtual status_t        pause() = 0;
-    virtual status_t        isPlaying(bool* state) = 0;
-    virtual status_t        setPlaybackSettings(const AudioPlaybackRate& rate) = 0;
-    virtual status_t        getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) = 0;
-    virtual status_t        setSyncSettings(const AVSyncSettings& sync, float videoFpsHint) = 0;
-    virtual status_t        getSyncSettings(AVSyncSettings* sync /* nonnull */,
-                                            float* videoFps /* nonnull */) = 0;
-    virtual status_t        seekTo(
-            int msec,
-            MediaPlayer2SeekMode mode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC) = 0;
-    virtual status_t        getCurrentPosition(int* msec) = 0;
-    virtual status_t        getDuration(int* msec) = 0;
-    virtual status_t        notifyAt(int64_t mediaTimeUs) = 0;
-    virtual status_t        reset() = 0;
-    virtual status_t        setAudioStreamType(audio_stream_type_t type) = 0;
-    virtual status_t        setLooping(int loop) = 0;
-    virtual status_t        setVolume(float leftVolume, float rightVolume) = 0;
-    virtual status_t        setAuxEffectSendLevel(float level) = 0;
-    virtual status_t        attachAuxEffect(int effectId) = 0;
-    virtual status_t        setParameter(int key, const Parcel& request) = 0;
-    virtual status_t        getParameter(int key, Parcel* reply) = 0;
-    virtual status_t        setNextPlayer(const sp<MediaPlayer2Engine>& next) = 0;
-
-    // Modular DRM
-    virtual status_t        prepareDrm(const uint8_t uuid[16],
-                                    const Vector<uint8_t>& drmSessionId) = 0;
-    virtual status_t        releaseDrm() = 0;
-
-    // Invoke a generic method on the player by using opaque parcels
-    // for the request and reply.
-    // @param request Parcel that must start with the media player
-    // interface token.
-    // @param[out] reply Parcel to hold the reply data. Cannot be null.
-    // @return OK if the invocation was made successfully.
-    virtual status_t        invoke(const Parcel& request, Parcel *reply) = 0;
-
-    // Set a new metadata filter.
-    // @param filter A set of allow and drop rules serialized in a Parcel.
-    // @return OK if the invocation was made successfully.
-    virtual status_t        setMetadataFilter(const Parcel& filter) = 0;
-
-    // Retrieve a set of metadata.
-    // @param update_only Include only the metadata that have changed
-    //                    since the last invocation of getMetadata.
-    //                    The set is built using the unfiltered
-    //                    notifications the native player sent to the
-    //                    MediaPlayer2Manager during that period of
-    //                    time. If false, all the metadatas are considered.
-    // @param apply_filter If true, once the metadata set has been built based
-    //                     on the value update_only, the current filter is
-    //                     applied.
-    // @param[out] metadata On exit contains a set (possibly empty) of metadata.
-    //                      Valid only if the call returned OK.
-    // @return OK if the invocation was made successfully.
-    virtual status_t        getMetadata(bool update_only,
-                                        bool apply_filter,
-                                        Parcel *metadata) = 0;
-
-    // AudioRouting
-    virtual status_t        setOutputDevice(audio_port_handle_t deviceId) = 0;
-    virtual status_t        getRoutedDeviceId(audio_port_handle_t *deviceId) = 0;
-    virtual status_t        enableAudioDeviceCallback(bool enabled) = 0;
-};
-
-}; // namespace android
-
-#endif // ANDROID_MEDIAPLAYER2ENGINE_H
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2EngineClient.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2EngineClient.h
deleted file mode 100644
index 0b066aa..0000000
--- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2EngineClient.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2017 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_MEDIAPLAYER2ENGINECLIENT_H
-#define ANDROID_MEDIAPLAYER2ENGINECLIENT_H
-
-#include <utils/RefBase.h>
-#include <binder/Parcel.h>
-
-namespace android {
-
-class MediaPlayer2EngineClient: public RefBase
-{
-public:
-    virtual void notify(int64_t srcId, int msg, int ext1, int ext2, const Parcel *obj) = 0;
-};
-
-}; // namespace android
-
-#endif // ANDROID_MEDIAPLAYER2ENGINECLIENT_H
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
index c0c490b..96aea7f 100644
--- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
+++ b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
@@ -21,18 +21,17 @@
 
 #include <sys/types.h>
 #include <utils/Errors.h>
-#include <utils/KeyedVector.h>
 #include <utils/String8.h>
 #include <utils/RefBase.h>
 
+#include <media/AVSyncSettings.h>
 #include <media/AudioResamplerPublic.h>
 #include <media/AudioSystem.h>
 #include <media/AudioTimestamp.h>
-#include <media/AVSyncSettings.h>
 #include <media/BufferingSettings.h>
 #include <media/Metadata.h>
 #include <media/stagefright/foundation/AHandler.h>
-#include <mediaplayer2/mediaplayer2.h>
+#include <mediaplayer2/MediaPlayer2Types.h>
 
 // Fwd decl to make sure everyone agrees that the scope of struct sockaddr_in is
 // global, and not in android::
@@ -40,14 +39,10 @@
 
 namespace android {
 
-class DataSource;
 struct DataSourceDesc;
-struct MediaHTTPService;
 class Parcel;
 struct ANativeWindowWrapper;
 
-template<typename T> class SortedVector;
-
 #define DEFAULT_AUDIOSINK_BUFFERCOUNT 4
 #define DEFAULT_AUDIOSINK_BUFFERSIZE 1200
 #define DEFAULT_AUDIOSINK_SAMPLERATE 44100
@@ -58,14 +53,14 @@
 // duration below which we do not allow deep audio buffering
 #define AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US 5000000
 
-// abstract base class - use MediaPlayer2Interface
-class MediaPlayer2Interface : public AHandler
+class MediaPlayer2InterfaceListener: public RefBase
 {
 public:
-    // callback mechanism for passing messages to MediaPlayer2 object
-    typedef void (*NotifyCallback)(const wp<MediaPlayer2Engine> &listener,
-            int64_t srcId, int msg, int ext1, int ext2, const Parcel *obj);
+    virtual void notify(int64_t srcId, int msg, int ext1, int ext2, const Parcel *obj) = 0;
+};
 
+class MediaPlayer2Interface : public AHandler {
+public:
     // AudioSink: abstraction layer for audio output
     class AudioSink : public RefBase {
     public:
@@ -79,29 +74,28 @@
 
         // Callback returns the number of bytes actually written to the buffer.
         typedef size_t (*AudioCallback)(
-                AudioSink *audioSink, void *buffer, size_t size, void *cookie,
-                        cb_event_t event);
+                AudioSink *audioSink, void *buffer, size_t size, void *cookie, cb_event_t event);
 
-        virtual             ~AudioSink() {}
-        virtual bool        ready() const = 0; // audio output is open and ready
-        virtual ssize_t     bufferSize() const = 0;
-        virtual ssize_t     frameCount() const = 0;
-        virtual ssize_t     channelCount() const = 0;
-        virtual ssize_t     frameSize() const = 0;
-        virtual uint32_t    latency() const = 0;
-        virtual float       msecsPerFrame() const = 0;
-        virtual status_t    getPosition(uint32_t *position) const = 0;
-        virtual status_t    getTimestamp(AudioTimestamp &ts) const = 0;
-        virtual int64_t     getPlayedOutDurationUs(int64_t nowUs) const = 0;
-        virtual status_t    getFramesWritten(uint32_t *frameswritten) const = 0;
+        virtual ~AudioSink() {}
+        virtual bool ready() const = 0; // audio output is open and ready
+        virtual ssize_t bufferSize() const = 0;
+        virtual ssize_t frameCount() const = 0;
+        virtual ssize_t channelCount() const = 0;
+        virtual ssize_t frameSize() const = 0;
+        virtual uint32_t latency() const = 0;
+        virtual float msecsPerFrame() const = 0;
+        virtual status_t getPosition(uint32_t *position) const = 0;
+        virtual status_t getTimestamp(AudioTimestamp &ts) const = 0;
+        virtual int64_t getPlayedOutDurationUs(int64_t nowUs) const = 0;
+        virtual status_t getFramesWritten(uint32_t *frameswritten) const = 0;
         virtual audio_session_t getSessionId() const = 0;
         virtual audio_stream_type_t getAudioStreamType() const = 0;
-        virtual uint32_t    getSampleRate() const = 0;
-        virtual int64_t     getBufferDurationInUs() const = 0;
+        virtual uint32_t getSampleRate() const = 0;
+        virtual int64_t getBufferDurationInUs() const = 0;
 
         // If no callback is specified, use the "write" API below to submit
         // audio data.
-        virtual status_t    open(
+        virtual status_t open(
                 uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
                 audio_format_t format=AUDIO_FORMAT_PCM_16_BIT,
                 int bufferCount=DEFAULT_AUDIOSINK_BUFFERCOUNT,
@@ -112,7 +106,7 @@
                 bool doNotReconnect = false,
                 uint32_t suggestedFrameCount = 0) = 0;
 
-        virtual status_t    start() = 0;
+        virtual status_t start() = 0;
 
         /* Input parameter |size| is in byte units stored in |buffer|.
          * Data is copied over and actual number of bytes written (>= 0)
@@ -124,19 +118,25 @@
          * buffer, unless an error occurs or the copy operation is
          * prematurely stopped.
          */
-        virtual ssize_t     write(const void* buffer, size_t size, bool blocking = true) = 0;
+        virtual ssize_t write(const void* buffer, size_t size, bool blocking = true) = 0;
 
-        virtual void        stop() = 0;
-        virtual void        flush() = 0;
-        virtual void        pause() = 0;
-        virtual void        close() = 0;
+        virtual void stop() = 0;
+        virtual void flush() = 0;
+        virtual void pause() = 0;
+        virtual void close() = 0;
 
-        virtual status_t    setPlaybackRate(const AudioPlaybackRate& rate) = 0;
-        virtual status_t    getPlaybackRate(AudioPlaybackRate* rate /* nonnull */) = 0;
-        virtual bool        needsTrailingPadding() { return true; }
+        virtual status_t setPlaybackRate(const AudioPlaybackRate& rate) = 0;
+        virtual status_t getPlaybackRate(AudioPlaybackRate* rate /* nonnull */) = 0;
+        virtual bool needsTrailingPadding() {
+            return true;
+        }
 
-        virtual status_t    setParameters(const String8& /* keyValuePairs */) { return NO_ERROR; }
-        virtual String8     getParameters(const String8& /* keys */) { return String8::empty(); }
+        virtual status_t setParameters(const String8& /* keyValuePairs */) {
+            return NO_ERROR;
+        }
+        virtual String8 getParameters(const String8& /* keys */) {
+            return String8::empty();
+        }
 
         // AudioRouting
         virtual status_t    setOutputDevice(audio_port_handle_t deviceId);
@@ -144,47 +144,48 @@
         virtual status_t    enableAudioDeviceCallback(bool enabled);
     };
 
-                        MediaPlayer2Interface() : mClient(0), mNotify(0) { }
-    virtual             ~MediaPlayer2Interface() { }
-    virtual status_t    initCheck() = 0;
+    MediaPlayer2Interface() : mListener(NULL) { }
+    virtual ~MediaPlayer2Interface() { }
+    virtual status_t initCheck() = 0;
 
-    virtual void        setAudioSink(const sp<AudioSink>& audioSink) { mAudioSink = audioSink; }
+    virtual void setAudioSink(const sp<AudioSink>& audioSink) {
+        mAudioSink = audioSink;
+    }
 
-    virtual status_t    setDataSource(const sp<DataSourceDesc> &dsd) = 0;
+    virtual status_t setDataSource(const sp<DataSourceDesc> &dsd) = 0;
 
-    virtual status_t    prepareNextDataSource(const sp<DataSourceDesc> &dsd) = 0;
+    virtual status_t prepareNextDataSource(const sp<DataSourceDesc> &dsd) = 0;
 
-    virtual status_t    playNextDataSource(int64_t srcId) = 0;
+    virtual status_t playNextDataSource(int64_t srcId) = 0;
 
     // pass the buffered native window to the media player service
-    virtual status_t    setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww) = 0;
+    virtual status_t setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww) = 0;
 
-    virtual status_t    getBufferingSettings(
-                                BufferingSettings* buffering /* nonnull */) {
+    virtual status_t getBufferingSettings(BufferingSettings* buffering /* nonnull */) {
         *buffering = BufferingSettings();
         return OK;
     }
-    virtual status_t    setBufferingSettings(const BufferingSettings& /* buffering */) {
+    virtual status_t setBufferingSettings(const BufferingSettings& /* buffering */) {
         return OK;
     }
 
-    virtual status_t    prepareAsync() = 0;
-    virtual status_t    start() = 0;
-    virtual status_t    stop() = 0;
-    virtual status_t    pause() = 0;
-    virtual bool        isPlaying() = 0;
-    virtual status_t    setPlaybackSettings(const AudioPlaybackRate& rate) {
+    virtual status_t prepareAsync() = 0;
+    virtual status_t start() = 0;
+    virtual status_t stop() = 0;
+    virtual status_t pause() = 0;
+    virtual bool isPlaying() = 0;
+    virtual status_t setPlaybackSettings(const AudioPlaybackRate& rate) {
         // by default, players only support setting rate to the default
         if (!isAudioPlaybackRateEqual(rate, AUDIO_PLAYBACK_RATE_DEFAULT)) {
             return BAD_VALUE;
         }
         return OK;
     }
-    virtual status_t    getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) {
+    virtual status_t getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) {
         *rate = AUDIO_PLAYBACK_RATE_DEFAULT;
         return OK;
     }
-    virtual status_t    setSyncSettings(const AVSyncSettings& sync, float /* videoFps */) {
+    virtual status_t setSyncSettings(const AVSyncSettings& sync, float /* videoFps */) {
         // By default, players only support setting sync source to default; all other sync
         // settings are ignored. There is no requirement for getters to return set values.
         if (sync.mSource != AVSYNC_SOURCE_DEFAULT) {
@@ -192,27 +193,23 @@
         }
         return OK;
     }
-    virtual status_t    getSyncSettings(
-                                AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */) {
+    virtual status_t getSyncSettings(
+            AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */) {
         *sync = AVSyncSettings();
         *videoFps = -1.f;
         return OK;
     }
-    virtual status_t    seekTo(
+    virtual status_t seekTo(
             int msec, MediaPlayer2SeekMode mode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC) = 0;
-    virtual status_t    getCurrentPosition(int *msec) = 0;
-    virtual status_t    getDuration(int *msec) = 0;
-    virtual status_t    reset() = 0;
-    virtual status_t    notifyAt(int64_t /* mediaTimeUs */) {
+    virtual status_t getCurrentPosition(int *msec) = 0;
+    virtual status_t getDuration(int *msec) = 0;
+    virtual status_t reset() = 0;
+    virtual status_t notifyAt(int64_t /* mediaTimeUs */) {
         return INVALID_OPERATION;
     }
-    virtual status_t    setLooping(int loop) = 0;
-    virtual status_t    setParameter(int key, const Parcel &request) = 0;
-    virtual status_t    getParameter(int key, Parcel *reply) = 0;
-
-    virtual status_t setNextPlayer(const sp<MediaPlayer2Interface>& /* next */) {
-        return OK;
-    }
+    virtual status_t setLooping(int loop) = 0;
+    virtual status_t setParameter(int key, const Parcel &request) = 0;
+    virtual status_t getParameter(int key, Parcel *reply) = 0;
 
     // Invoke a generic method on the player by using opaque parcels
     // for the request and reply.
@@ -221,7 +218,7 @@
     //                data sent by the java layer.
     // @param[out] reply Parcel to hold the reply data. Cannot be null.
     // @return OK if the call was successful.
-    virtual status_t    invoke(const Parcel& request, Parcel *reply) = 0;
+    virtual status_t invoke(const Parcel& request, Parcel *reply) = 0;
 
     // The Client in the MetadataPlayerService calls this method on
     // the native player to retrieve all or a subset of metadata.
@@ -230,28 +227,26 @@
     //            the known metadata should be returned.
     // @param[inout] records Parcel where the player appends its metadata.
     // @return OK if the call was successful.
-    virtual status_t    getMetadata(const media::Metadata::Filter& /* ids */,
-                                    Parcel* /* records */) {
+    virtual status_t getMetadata(const media::Metadata::Filter& /* ids */,
+                                 Parcel* /* records */) {
         return INVALID_OPERATION;
     };
 
-    void        setNotifyCallback(
-            const wp<MediaPlayer2Engine> &client, NotifyCallback notifyFunc) {
-        Mutex::Autolock autoLock(mNotifyLock);
-        mClient = client; mNotify = notifyFunc;
+    void setListener(const sp<MediaPlayer2InterfaceListener> &listener) {
+        Mutex::Autolock autoLock(mListenerLock);
+        mListener = listener;
     }
 
-    void        sendEvent(int64_t srcId, int msg, int ext1=0, int ext2=0,
-                          const Parcel *obj=NULL) {
-        NotifyCallback notifyCB;
-        wp<MediaPlayer2Engine> client;
+    void sendEvent(int64_t srcId, int msg, int ext1=0, int ext2=0, const Parcel *obj=NULL) {
+        sp<MediaPlayer2InterfaceListener> listener;
         {
-            Mutex::Autolock autoLock(mNotifyLock);
-            notifyCB = mNotify;
-            client = mClient;
+            Mutex::Autolock autoLock(mListenerLock);
+            listener = mListener;
         }
 
-        if (notifyCB) notifyCB(client, srcId, msg, ext1, ext2, obj);
+        if (listener) {
+            listener->notify(srcId, msg, ext1, ext2, obj);
+        }
     }
 
     virtual status_t dump(int /* fd */, const Vector<String16>& /* args */) const {
@@ -261,7 +256,8 @@
     virtual void onMessageReceived(const sp<AMessage> & /* msg */) override { }
 
     // Modular DRM
-    virtual status_t prepareDrm(const uint8_t /* uuid */[16], const Vector<uint8_t>& /* drmSessionId */) {
+    virtual status_t prepareDrm(const uint8_t /* uuid */[16],
+                                const Vector<uint8_t>& /* drmSessionId */) {
         return INVALID_OPERATION;
     }
     virtual status_t releaseDrm() {
@@ -269,14 +265,11 @@
     }
 
 protected:
-    sp<AudioSink>       mAudioSink;
+    sp<AudioSink> mAudioSink;
 
 private:
-    friend class MediaPlayer2Manager;
-
-    Mutex                  mNotifyLock;
-    wp<MediaPlayer2Engine> mClient;
-    NotifyCallback         mNotify;
+    Mutex mListenerLock;
+    sp<MediaPlayer2InterfaceListener> mListener;
 };
 
 }; // namespace android
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Types.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Types.h
new file mode 100644
index 0000000..260c7ed
--- /dev/null
+++ b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Types.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2018 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_MEDIAPLAYER2_TYPES_H
+#define ANDROID_MEDIAPLAYER2_TYPES_H
+
+#include <media/mediaplayer_common.h>
+
+#include <media/MediaSource.h>
+
+namespace android {
+
+typedef MediaSource::ReadOptions::SeekMode MediaPlayer2SeekMode;
+
+enum media2_event_type {
+    MEDIA2_NOP               = 0, // interface test message
+    MEDIA2_PREPARED          = 1,
+    MEDIA2_PLAYBACK_COMPLETE = 2,
+    MEDIA2_BUFFERING_UPDATE  = 3,
+    MEDIA2_SEEK_COMPLETE     = 4,
+    MEDIA2_SET_VIDEO_SIZE    = 5,
+    MEDIA2_STARTED           = 6,
+    MEDIA2_PAUSED            = 7,
+    MEDIA2_STOPPED           = 8,
+    MEDIA2_SKIPPED           = 9,
+    MEDIA2_NOTIFY_TIME       = 98,
+    MEDIA2_TIMED_TEXT        = 99,
+    MEDIA2_ERROR             = 100,
+    MEDIA2_INFO              = 200,
+    MEDIA2_SUBTITLE_DATA     = 201,
+    MEDIA2_META_DATA         = 202,
+    MEDIA2_DRM_INFO          = 210,
+    MEDIA2_AUDIO_ROUTING_CHANGED = 10000,
+};
+
+// Generic error codes for the media player framework.  Errors are fatal, the
+// playback must abort.
+//
+// Errors are communicated back to the client using the
+// MediaPlayer2Listener::notify method defined below.
+// In this situation, 'notify' is invoked with the following:
+//   'msg' is set to MEDIA_ERROR.
+//   'ext1' should be a value from the enum media2_error_type.
+//   'ext2' contains an implementation dependant error code to provide
+//          more details. Should default to 0 when not used.
+//
+// The codes are distributed as follow:
+//   0xx: Reserved
+//   1xx: Android Player errors. Something went wrong inside the MediaPlayer2.
+//   2xx: Media errors (e.g Codec not supported). There is a problem with the
+//        media itself.
+//   3xx: Runtime errors. Some extraordinary condition arose making the playback
+//        impossible.
+//
+enum media2_error_type {
+    // 0xx
+    MEDIA2_ERROR_UNKNOWN = 1,
+    // 1xx
+    // MEDIA2_ERROR_SERVER_DIED = 100,
+    // 2xx
+    MEDIA2_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200,
+    // 3xx
+    MEDIA2_ERROR_FAILED_TO_SET_DATA_SOURCE = 300,
+};
+
+
+// Info and warning codes for the media player framework.  These are non fatal,
+// the playback is going on but there might be some user visible issues.
+//
+// Info and warning messages are communicated back to the client using the
+// MediaPlayer2Listener::notify method defined below.  In this situation,
+// 'notify' is invoked with the following:
+//   'msg' is set to MEDIA_INFO.
+//   'ext1' should be a value from the enum media2_info_type.
+//   'ext2' contains an implementation dependant info code to provide
+//          more details. Should default to 0 when not used.
+//
+// The codes are distributed as follow:
+//   0xx: Reserved
+//   7xx: Android Player info/warning (e.g player lagging behind.)
+//   8xx: Media info/warning (e.g media badly interleaved.)
+//
+enum media2_info_type {
+    // 0xx
+    MEDIA2_INFO_UNKNOWN = 1,
+    // The player was started because it was used as the next player for another
+    // player, which just completed playback
+    MEDIA2_INFO_STARTED_AS_NEXT = 2,
+    // The player just pushed the very first video frame for rendering
+    MEDIA2_INFO_VIDEO_RENDERING_START = 3,
+    // The player just pushed the very first audio frame for rendering
+    MEDIA2_INFO_AUDIO_RENDERING_START = 4,
+    // The player just completed the playback of this data source
+    MEDIA2_INFO_PLAYBACK_COMPLETE = 5,
+    // The player just completed the playback of the full play list
+    MEDIA2_INFO_PLAYLIST_END = 6,
+
+    //1xx
+    // The player just prepared a data source.
+    MEDIA2_INFO_PREPARED = 100,
+    // The player just completed a call play().
+    MEDIA2_INFO_COMPLETE_CALL_PLAY = 101,
+    // The player just completed a call pause().
+    MEDIA2_INFO_COMPLETE_CALL_PAUSE = 102,
+    // The player just completed a call seekTo.
+    MEDIA2_INFO_COMPLETE_CALL_SEEK = 103,
+
+    // 7xx
+    // The video is too complex for the decoder: it can't decode frames fast
+    // enough. Possibly only the audio plays fine at this stage.
+    MEDIA2_INFO_VIDEO_TRACK_LAGGING = 700,
+    // MediaPlayer2 is temporarily pausing playback internally in order to
+    // buffer more data.
+    MEDIA2_INFO_BUFFERING_START = 701,
+    // MediaPlayer2 is resuming playback after filling buffers.
+    MEDIA2_INFO_BUFFERING_END = 702,
+    // Bandwidth in recent past
+    MEDIA2_INFO_NETWORK_BANDWIDTH = 703,
+
+    // 8xx
+    // Bad interleaving means that a media has been improperly interleaved or not
+    // interleaved at all, e.g has all the video samples first then all the audio
+    // ones. Video is playing but a lot of disk seek may be happening.
+    MEDIA2_INFO_BAD_INTERLEAVING = 800,
+    // The media is not seekable (e.g live stream).
+    MEDIA2_INFO_NOT_SEEKABLE = 801,
+    // New media metadata is available.
+    MEDIA2_INFO_METADATA_UPDATE = 802,
+    // Audio can not be played.
+    MEDIA2_INFO_PLAY_AUDIO_ERROR = 804,
+    // Video can not be played.
+    MEDIA2_INFO_PLAY_VIDEO_ERROR = 805,
+
+    //9xx
+    MEDIA2_INFO_TIMED_TEXT_ERROR = 900,
+};
+
+enum media_player2_states {
+    MEDIA_PLAYER2_STATE_ERROR        = 0,
+    MEDIA_PLAYER2_IDLE               = 1 << 0,
+    MEDIA_PLAYER2_INITIALIZED        = 1 << 1,
+    MEDIA_PLAYER2_PREPARING          = 1 << 2,
+    MEDIA_PLAYER2_PREPARED           = 1 << 3,
+    MEDIA_PLAYER2_STARTED            = 1 << 4,
+    MEDIA_PLAYER2_PAUSED             = 1 << 5,
+    MEDIA_PLAYER2_STOPPED            = 1 << 6,
+    MEDIA_PLAYER2_PLAYBACK_COMPLETE  = 1 << 7
+};
+
+// Keep KEY_PARAMETER_* in sync with MediaPlayer2.java.
+// The same enum space is used for both set and get, in case there are future keys that
+// can be both set and get.  But as of now, all parameters are either set only or get only.
+enum media2_parameter_keys {
+    // Streaming/buffering parameters
+    MEDIA2_KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS = 1100,            // set only
+
+    // Return a Parcel containing a single int, which is the channel count of the
+    // audio track, or zero for error (e.g. no audio track) or unknown.
+    MEDIA2_KEY_PARAMETER_AUDIO_CHANNEL_COUNT = 1200,                   // get only
+
+    // Playback rate expressed in permille (1000 is normal speed), saved as int32_t, with negative
+    // values used for rewinding or reverse playback.
+    MEDIA2_KEY_PARAMETER_PLAYBACK_RATE_PERMILLE = 1300,                // set only
+
+    // Set a Parcel containing the value of a parcelled Java AudioAttribute instance
+    MEDIA2_KEY_PARAMETER_AUDIO_ATTRIBUTES = 1400                       // set only
+};
+
+// Keep INVOKE_ID_* in sync with MediaPlayer2.java.
+enum media_player2_invoke_ids {
+    MEDIA_PLAYER2_INVOKE_ID_GET_TRACK_INFO = 1,
+    MEDIA_PLAYER2_INVOKE_ID_ADD_EXTERNAL_SOURCE = 2,
+    MEDIA_PLAYER2_INVOKE_ID_ADD_EXTERNAL_SOURCE_FD = 3,
+    MEDIA_PLAYER2_INVOKE_ID_SELECT_TRACK = 4,
+    MEDIA_PLAYER2_INVOKE_ID_UNSELECT_TRACK = 5,
+    MEDIA_PLAYER2_INVOKE_ID_SET_VIDEO_SCALING_MODE = 6,
+    MEDIA_PLAYER2_INVOKE_ID_GET_SELECTED_TRACK = 7
+};
+
+}; // namespace android
+
+#endif // ANDROID_MEDIAPLAYER2_TYPES_H
diff --git a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
index 0afef1e..11e4f42 100644
--- a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
+++ b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
@@ -17,196 +17,27 @@
 #ifndef ANDROID_MEDIAPLAYER2_H
 #define ANDROID_MEDIAPLAYER2_H
 
-#include <media/mediaplayer_common.h>
-
-#include <arpa/inet.h>
-
+#include <media/AVSyncSettings.h>
 #include <media/AudioResamplerPublic.h>
 #include <media/BufferingSettings.h>
-#include <mediaplayer2/MediaPlayer2EngineClient.h>
-#include <mediaplayer2/MediaPlayer2Engine.h>
+#include <media/Metadata.h>
+#include <media/mediaplayer_common.h>
+#include <mediaplayer2/MediaPlayer2Interface.h>
+#include <mediaplayer2/MediaPlayer2Types.h>
 
-#include <utils/Condition.h>
-#include <utils/KeyedVector.h>
-#include <utils/String8.h>
-#include <utils/ThreadDefs.h>
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+#include <system/audio-base.h>
 
 namespace android {
 
-struct AVSyncSettings;
 struct ANativeWindowWrapper;
-class DataSource;
 struct DataSourceDesc;
-struct MediaHTTPService;
+class MediaPlayer2AudioOutput;
 
-enum media2_event_type {
-    MEDIA2_NOP               = 0, // interface test message
-    MEDIA2_PREPARED          = 1,
-    MEDIA2_PLAYBACK_COMPLETE = 2,
-    MEDIA2_BUFFERING_UPDATE  = 3,
-    MEDIA2_SEEK_COMPLETE     = 4,
-    MEDIA2_SET_VIDEO_SIZE    = 5,
-    MEDIA2_STARTED           = 6,
-    MEDIA2_PAUSED            = 7,
-    MEDIA2_STOPPED           = 8,
-    MEDIA2_SKIPPED           = 9,
-    MEDIA2_NOTIFY_TIME       = 98,
-    MEDIA2_TIMED_TEXT        = 99,
-    MEDIA2_ERROR             = 100,
-    MEDIA2_INFO              = 200,
-    MEDIA2_SUBTITLE_DATA     = 201,
-    MEDIA2_META_DATA         = 202,
-    MEDIA2_DRM_INFO          = 210,
-    MEDIA2_AUDIO_ROUTING_CHANGED = 10000,
-};
-
-// Generic error codes for the media player framework.  Errors are fatal, the
-// playback must abort.
-//
-// Errors are communicated back to the client using the
-// MediaPlayer2Listener::notify method defined below.
-// In this situation, 'notify' is invoked with the following:
-//   'msg' is set to MEDIA_ERROR.
-//   'ext1' should be a value from the enum media2_error_type.
-//   'ext2' contains an implementation dependant error code to provide
-//          more details. Should default to 0 when not used.
-//
-// The codes are distributed as follow:
-//   0xx: Reserved
-//   1xx: Android Player errors. Something went wrong inside the MediaPlayer2.
-//   2xx: Media errors (e.g Codec not supported). There is a problem with the
-//        media itself.
-//   3xx: Runtime errors. Some extraordinary condition arose making the playback
-//        impossible.
-//
-enum media2_error_type {
-    // 0xx
-    MEDIA2_ERROR_UNKNOWN = 1,
-    // 1xx
-    // MEDIA2_ERROR_SERVER_DIED = 100,
-    // 2xx
-    MEDIA2_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200,
-    // 3xx
-    MEDIA2_ERROR_FAILED_TO_SET_DATA_SOURCE = 300,
-};
-
-
-// Info and warning codes for the media player framework.  These are non fatal,
-// the playback is going on but there might be some user visible issues.
-//
-// Info and warning messages are communicated back to the client using the
-// MediaPlayer2Listener::notify method defined below.  In this situation,
-// 'notify' is invoked with the following:
-//   'msg' is set to MEDIA_INFO.
-//   'ext1' should be a value from the enum media2_info_type.
-//   'ext2' contains an implementation dependant info code to provide
-//          more details. Should default to 0 when not used.
-//
-// The codes are distributed as follow:
-//   0xx: Reserved
-//   7xx: Android Player info/warning (e.g player lagging behind.)
-//   8xx: Media info/warning (e.g media badly interleaved.)
-//
-enum media2_info_type {
-    // 0xx
-    MEDIA2_INFO_UNKNOWN = 1,
-    // The player was started because it was used as the next player for another
-    // player, which just completed playback
-    MEDIA2_INFO_STARTED_AS_NEXT = 2,
-    // The player just pushed the very first video frame for rendering
-    MEDIA2_INFO_VIDEO_RENDERING_START = 3,
-    // The player just pushed the very first audio frame for rendering
-    MEDIA2_INFO_AUDIO_RENDERING_START = 4,
-    // The player just completed the playback of this data source
-    MEDIA2_INFO_PLAYBACK_COMPLETE = 5,
-    // The player just completed the playback of the full play list
-    MEDIA2_INFO_PLAYLIST_END = 6,
-
-    //1xx
-    // The player just prepared a data source.
-    MEDIA2_INFO_PREPARED = 100,
-    // The player just completed a call play().
-    MEDIA2_INFO_COMPLETE_CALL_PLAY = 101,
-    // The player just completed a call pause().
-    MEDIA2_INFO_COMPLETE_CALL_PAUSE = 102,
-    // The player just completed a call seekTo.
-    MEDIA2_INFO_COMPLETE_CALL_SEEK = 103,
-
-    // 7xx
-    // The video is too complex for the decoder: it can't decode frames fast
-    // enough. Possibly only the audio plays fine at this stage.
-    MEDIA2_INFO_VIDEO_TRACK_LAGGING = 700,
-    // MediaPlayer2 is temporarily pausing playback internally in order to
-    // buffer more data.
-    MEDIA2_INFO_BUFFERING_START = 701,
-    // MediaPlayer2 is resuming playback after filling buffers.
-    MEDIA2_INFO_BUFFERING_END = 702,
-    // Bandwidth in recent past
-    MEDIA2_INFO_NETWORK_BANDWIDTH = 703,
-
-    // 8xx
-    // Bad interleaving means that a media has been improperly interleaved or not
-    // interleaved at all, e.g has all the video samples first then all the audio
-    // ones. Video is playing but a lot of disk seek may be happening.
-    MEDIA2_INFO_BAD_INTERLEAVING = 800,
-    // The media is not seekable (e.g live stream).
-    MEDIA2_INFO_NOT_SEEKABLE = 801,
-    // New media metadata is available.
-    MEDIA2_INFO_METADATA_UPDATE = 802,
-    // Audio can not be played.
-    MEDIA2_INFO_PLAY_AUDIO_ERROR = 804,
-    // Video can not be played.
-    MEDIA2_INFO_PLAY_VIDEO_ERROR = 805,
-
-    //9xx
-    MEDIA2_INFO_TIMED_TEXT_ERROR = 900,
-};
-
-
-
-enum media_player2_states {
-    MEDIA_PLAYER2_STATE_ERROR        = 0,
-    MEDIA_PLAYER2_IDLE               = 1 << 0,
-    MEDIA_PLAYER2_INITIALIZED        = 1 << 1,
-    MEDIA_PLAYER2_PREPARING          = 1 << 2,
-    MEDIA_PLAYER2_PREPARED           = 1 << 3,
-    MEDIA_PLAYER2_STARTED            = 1 << 4,
-    MEDIA_PLAYER2_PAUSED             = 1 << 5,
-    MEDIA_PLAYER2_STOPPED            = 1 << 6,
-    MEDIA_PLAYER2_PLAYBACK_COMPLETE  = 1 << 7
-};
-
-// Keep KEY_PARAMETER_* in sync with MediaPlayer2.java.
-// The same enum space is used for both set and get, in case there are future keys that
-// can be both set and get.  But as of now, all parameters are either set only or get only.
-enum media2_parameter_keys {
-    // Streaming/buffering parameters
-    MEDIA2_KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS = 1100,            // set only
-
-    // Return a Parcel containing a single int, which is the channel count of the
-    // audio track, or zero for error (e.g. no audio track) or unknown.
-    MEDIA2_KEY_PARAMETER_AUDIO_CHANNEL_COUNT = 1200,                   // get only
-
-    // Playback rate expressed in permille (1000 is normal speed), saved as int32_t, with negative
-    // values used for rewinding or reverse playback.
-    MEDIA2_KEY_PARAMETER_PLAYBACK_RATE_PERMILLE = 1300,                // set only
-
-    // Set a Parcel containing the value of a parcelled Java AudioAttribute instance
-    MEDIA2_KEY_PARAMETER_AUDIO_ATTRIBUTES = 1400                       // set only
-};
-
-// Keep INVOKE_ID_* in sync with MediaPlayer2.java.
-enum media_player2_invoke_ids {
-    MEDIA_PLAYER2_INVOKE_ID_GET_TRACK_INFO = 1,
-    MEDIA_PLAYER2_INVOKE_ID_ADD_EXTERNAL_SOURCE = 2,
-    MEDIA_PLAYER2_INVOKE_ID_ADD_EXTERNAL_SOURCE_FD = 3,
-    MEDIA_PLAYER2_INVOKE_ID_SELECT_TRACK = 4,
-    MEDIA_PLAYER2_INVOKE_ID_UNSELECT_TRACK = 5,
-    MEDIA_PLAYER2_INVOKE_ID_SET_VIDEO_SCALING_MODE = 6,
-    MEDIA_PLAYER2_INVOKE_ID_GET_SELECTED_TRACK = 7
-};
-
-// ----------------------------------------------------------------------------
 // ref-counted object for callbacks
 class MediaPlayer2Listener: virtual public RefBase
 {
@@ -214,11 +45,14 @@
     virtual void notify(int64_t srcId, int msg, int ext1, int ext2, const Parcel *obj) = 0;
 };
 
-class MediaPlayer2 : public MediaPlayer2EngineClient
+class MediaPlayer2 : public MediaPlayer2InterfaceListener
 {
 public:
-    MediaPlayer2();
     ~MediaPlayer2();
+
+    static sp<MediaPlayer2> Create();
+    static status_t DumpAll(int fd, const Vector<String16>& args);
+
             void            disconnect();
 
             status_t        getSrcId(int64_t *srcId);
@@ -275,22 +109,43 @@
             audio_port_handle_t getRoutedDeviceId();
             status_t        enableAudioDeviceCallback(bool enabled);
 
-private:
-            void            clear_l();
-            status_t        seekTo_l(int msec, MediaPlayer2SeekMode mode);
-            status_t        prepareAsync_l();
-            status_t        getDuration_l(int *msec);
-            status_t        attachNewPlayer(const sp<MediaPlayer2Engine>& player, long srcId);
-            status_t        reset_l();
-            status_t        checkStateForKeySet_l(int key);
+            status_t        dump(int fd, const Vector<String16>& args);
 
-    sp<MediaPlayer2Engine>      mPlayer;
+private:
+    MediaPlayer2();
+    bool init();
+
+    // @param type Of the metadata to be tested.
+    // @return true if the metadata should be dropped according to
+    //              the filters.
+    bool shouldDropMetadata(media::Metadata::Type type) const;
+
+    // Add a new element to the set of metadata updated. Noop if
+    // the element exists already.
+    // @param type Of the metadata to be recorded.
+    void addNewMetadataUpdate(media::Metadata::Type type);
+
+    // Disconnect from the currently connected ANativeWindow.
+    void disconnectNativeWindow_l();
+
+    status_t setAudioAttributes_l(const Parcel &request);
+
+    void clear_l();
+    status_t seekTo_l(int msec, MediaPlayer2SeekMode mode);
+    status_t prepareAsync_l();
+    status_t getDuration_l(int *msec);
+    status_t reset_l();
+    status_t checkStateForKeySet_l(int key);
+
+    pid_t                       mPid;
+    uid_t                       mUid;
+    sp<MediaPlayer2Interface>   mPlayer;
+    sp<MediaPlayer2AudioOutput> mAudioOutput;
     int64_t                     mSrcId;
     thread_id_t                 mLockThreadId;
-    Mutex                       mLock;
+    mutable Mutex               mLock;
     Mutex                       mNotifyLock;
     sp<MediaPlayer2Listener>    mListener;
-    void*                       mCookie;
     media_player2_states        mCurrentState;
     int                         mCurrentPosition;
     MediaPlayer2SeekMode        mCurrentSeekMode;
@@ -304,7 +159,20 @@
     int                         mVideoWidth;
     int                         mVideoHeight;
     audio_session_t             mAudioSessionId;
+    audio_attributes_t *        mAudioAttributes;
     float                       mSendLevel;
+
+    sp<ANativeWindowWrapper>    mConnectedWindow;
+
+    // Metadata filters.
+    media::Metadata::Filter mMetadataAllow;  // protected by mLock
+    media::Metadata::Filter mMetadataDrop;  // protected by mLock
+
+    // Metadata updated. For each MEDIA_INFO_METADATA_UPDATE
+    // notification we try to update mMetadataUpdated which is a
+    // set: no duplicate.
+    // getMetadata clears this set.
+    media::Metadata::Filter mMetadataUpdated;  // protected by mLock
 };
 
 }; // namespace android
diff --git a/media/libmediaplayer2/mediaplayer2.cpp b/media/libmediaplayer2/mediaplayer2.cpp
index 75d06b8..b401ee8 100644
--- a/media/libmediaplayer2/mediaplayer2.cpp
+++ b/media/libmediaplayer2/mediaplayer2.cpp
@@ -18,44 +18,391 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "MediaPlayer2Native"
 
-#include <fcntl.h>
-#include <inttypes.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <utils/Log.h>
-
 #include <binder/IServiceManager.h>
 #include <binder/IPCThreadState.h>
 
-#include <media/AudioResamplerPublic.h>
 #include <media/AudioSystem.h>
-#include <media/AVSyncSettings.h>
-#include <media/DataSource.h>
 #include <media/DataSourceDesc.h>
 #include <media/MediaAnalyticsItem.h>
+#include <media/MemoryLeakTrackUtil.h>
+#include <media/Metadata.h>
 #include <media/NdkWrapper.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooperRoster.h>
+#include <mediaplayer2/MediaPlayer2AudioOutput.h>
 #include <mediaplayer2/mediaplayer2.h>
 
-#include <binder/MemoryBase.h>
-
-#include <utils/KeyedVector.h>
+#include <utils/Log.h>
+#include <utils/SortedVector.h>
 #include <utils/String8.h>
 
 #include <system/audio.h>
 #include <system/window.h>
 
-#include "MediaPlayer2Manager.h"
+#include <nuplayer2/NuPlayer2Driver.h>
+
+#include <dirent.h>
+#include <sys/stat.h>
 
 namespace android {
 
-MediaPlayer2::MediaPlayer2()
-{
+extern ALooperRoster gLooperRoster;
+
+namespace {
+
+const int kDumpLockRetries = 50;
+const int kDumpLockSleepUs = 20000;
+
+// Max number of entries in the filter.
+const int kMaxFilterSize = 64;  // I pulled that out of thin air.
+
+// FIXME: Move all the metadata related function in the Metadata.cpp
+
+// Unmarshall a filter from a Parcel.
+// Filter format in a parcel:
+//
+//  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// |                       number of entries (n)                   |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// |                       metadata type 1                         |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// |                       metadata type 2                         |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//  ....
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// |                       metadata type n                         |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//
+// @param p Parcel that should start with a filter.
+// @param[out] filter On exit contains the list of metadata type to be
+//                    filtered.
+// @param[out] status On exit contains the status code to be returned.
+// @return true if the parcel starts with a valid filter.
+bool unmarshallFilter(const Parcel& p,
+                      media::Metadata::Filter *filter,
+                      status_t *status) {
+    int32_t val;
+    if (p.readInt32(&val) != OK) {
+        ALOGE("Failed to read filter's length");
+        *status = NOT_ENOUGH_DATA;
+        return false;
+    }
+
+    if (val > kMaxFilterSize || val < 0) {
+        ALOGE("Invalid filter len %d", val);
+        *status = BAD_VALUE;
+        return false;
+    }
+
+    const size_t num = val;
+
+    filter->clear();
+    filter->setCapacity(num);
+
+    size_t size = num * sizeof(media::Metadata::Type);
+
+
+    if (p.dataAvail() < size) {
+        ALOGE("Filter too short expected %zu but got %zu", size, p.dataAvail());
+        *status = NOT_ENOUGH_DATA;
+        return false;
+    }
+
+    const media::Metadata::Type *data =
+        static_cast<const media::Metadata::Type*>(p.readInplace(size));
+
+    if (NULL == data) {
+        ALOGE("Filter had no data");
+        *status = BAD_VALUE;
+        return false;
+    }
+
+    // TODO: The stl impl of vector would be more efficient here
+    // because it degenerates into a memcpy on pod types. Try to
+    // replace later or use stl::set.
+    for (size_t i = 0; i < num; ++i) {
+        filter->add(*data);
+        ++data;
+    }
+    *status = OK;
+    return true;
+}
+
+// @param filter Of metadata type.
+// @param val To be searched.
+// @return true if a match was found.
+bool findMetadata(const media::Metadata::Filter& filter, const int32_t val) {
+    // Deal with empty and ANY right away
+    if (filter.isEmpty()) {
+        return false;
+    }
+    if (filter[0] == media::Metadata::kAny) {
+        return true;
+    }
+
+    return filter.indexOf(val) >= 0;
+}
+
+// marshalling tag indicating flattened utf16 tags
+// keep in sync with frameworks/base/media/java/android/media/AudioAttributes.java
+const int32_t kAudioAttributesMarshallTagFlattenTags = 1;
+
+// Audio attributes format in a parcel:
+//
+//  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// |                       usage                                   |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// |                       content_type                            |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// |                       source                                  |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// |                       flags                                   |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// |                       kAudioAttributesMarshallTagFlattenTags  | // ignore tags if not found
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// |                       flattened tags in UTF16                 |
+// |                         ...                                   |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//
+// @param p Parcel that contains audio attributes.
+// @param[out] attributes On exit points to an initialized audio_attributes_t structure
+// @param[out] status On exit contains the status code to be returned.
+void unmarshallAudioAttributes(const Parcel& parcel, audio_attributes_t *attributes) {
+    attributes->usage = (audio_usage_t) parcel.readInt32();
+    attributes->content_type = (audio_content_type_t) parcel.readInt32();
+    attributes->source = (audio_source_t) parcel.readInt32();
+    attributes->flags = (audio_flags_mask_t) parcel.readInt32();
+    const bool hasFlattenedTag = (parcel.readInt32() == kAudioAttributesMarshallTagFlattenTags);
+    if (hasFlattenedTag) {
+        // the tags are UTF16, convert to UTF8
+        String16 tags = parcel.readString16();
+        ssize_t realTagSize = utf16_to_utf8_length(tags.string(), tags.size());
+        if (realTagSize <= 0) {
+            strcpy(attributes->tags, "");
+        } else {
+            // copy the flattened string into the attributes as the destination for the conversion:
+            // copying array size -1, array for tags was calloc'd, no need to NULL-terminate it
+            size_t tagSize = realTagSize > AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 ?
+                    AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 : realTagSize;
+            utf16_to_utf8(tags.string(), tagSize, attributes->tags,
+                    sizeof(attributes->tags) / sizeof(attributes->tags[0]));
+        }
+    } else {
+        ALOGE("unmarshallAudioAttributes() received unflattened tags, ignoring tag values");
+        strcpy(attributes->tags, "");
+    }
+}
+
+class AudioDeviceUpdatedNotifier: public AudioSystem::AudioDeviceCallback {
+public:
+    AudioDeviceUpdatedNotifier(const sp<MediaPlayer2Interface>& listener)
+        : mListener(listener) { }
+
+    ~AudioDeviceUpdatedNotifier() { }
+
+    virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
+                                     audio_port_handle_t deviceId) override {
+        sp<MediaPlayer2Interface> listener = mListener.promote();
+        if (listener != NULL) {
+            listener->sendEvent(0, MEDIA2_AUDIO_ROUTING_CHANGED, audioIo, deviceId);
+        } else {
+            ALOGW("listener for process %d death is gone", MEDIA2_AUDIO_ROUTING_CHANGED);
+        }
+    }
+
+private:
+    wp<MediaPlayer2Interface> mListener;
+};
+
+class proxyListener : public MediaPlayer2InterfaceListener {
+public:
+    proxyListener(const wp<MediaPlayer2> &player)
+        : mPlayer(player) { }
+
+    ~proxyListener() { };
+
+    virtual void notify(int64_t srcId, int msg, int ext1, int ext2, const Parcel *obj) override {
+        sp<MediaPlayer2> player = mPlayer.promote();
+        if (player != NULL) {
+            player->notify(srcId, msg, ext1, ext2, obj);
+        }
+    }
+
+private:
+    wp<MediaPlayer2> mPlayer;
+};
+
+Mutex sRecordLock;
+SortedVector<wp<MediaPlayer2> > *sPlayers;
+
+void ensureInit_l() {
+    if (sPlayers == NULL) {
+        sPlayers = new SortedVector<wp<MediaPlayer2> >();
+    }
+}
+
+void addPlayer(const wp<MediaPlayer2>& player) {
+    Mutex::Autolock lock(sRecordLock);
+    ensureInit_l();
+    sPlayers->add(player);
+}
+
+void removePlayer(const wp<MediaPlayer2>& player) {
+    Mutex::Autolock lock(sRecordLock);
+    ensureInit_l();
+    sPlayers->remove(player);
+}
+
+/**
+ * The only arguments this understands right now are -c, -von and -voff,
+ * which are parsed by ALooperRoster::dump()
+ */
+status_t dumpPlayers(int fd, const Vector<String16>& args) {
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    SortedVector< sp<MediaPlayer2> > players; //to serialise the mutex unlock & client destruction.
+
+    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
+        snprintf(buffer, SIZE, "Permission Denial: can't dump MediaPlayer2\n");
+        result.append(buffer);
+    } else {
+        {
+            Mutex::Autolock lock(sRecordLock);
+            ensureInit_l();
+            for (int i = 0, n = sPlayers->size(); i < n; ++i) {
+                sp<MediaPlayer2> p = (*sPlayers)[i].promote();
+                if (p != 0) {
+                    p->dump(fd, args);
+                }
+                players.add(p);
+            }
+        }
+
+        result.append(" Files opened and/or mapped:\n");
+        snprintf(buffer, SIZE, "/proc/%d/maps", getpid());
+        FILE *f = fopen(buffer, "r");
+        if (f) {
+            while (!feof(f)) {
+                fgets(buffer, SIZE, f);
+                if (strstr(buffer, " /storage/") ||
+                    strstr(buffer, " /system/sounds/") ||
+                    strstr(buffer, " /data/") ||
+                    strstr(buffer, " /system/media/")) {
+                    result.append("  ");
+                    result.append(buffer);
+                }
+            }
+            fclose(f);
+        } else {
+            result.append("couldn't open ");
+            result.append(buffer);
+            result.append("\n");
+        }
+
+        snprintf(buffer, SIZE, "/proc/%d/fd", getpid());
+        DIR *d = opendir(buffer);
+        if (d) {
+            struct dirent *ent;
+            while((ent = readdir(d)) != NULL) {
+                if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
+                    snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name);
+                    struct stat s;
+                    if (lstat(buffer, &s) == 0) {
+                        if ((s.st_mode & S_IFMT) == S_IFLNK) {
+                            char linkto[256];
+                            int len = readlink(buffer, linkto, sizeof(linkto));
+                            if(len > 0) {
+                                if(len > 255) {
+                                    linkto[252] = '.';
+                                    linkto[253] = '.';
+                                    linkto[254] = '.';
+                                    linkto[255] = 0;
+                                } else {
+                                    linkto[len] = 0;
+                                }
+                                if (strstr(linkto, "/storage/") == linkto ||
+                                    strstr(linkto, "/system/sounds/") == linkto ||
+                                    strstr(linkto, "/data/") == linkto ||
+                                    strstr(linkto, "/system/media/") == linkto) {
+                                    result.append("  ");
+                                    result.append(buffer);
+                                    result.append(" -> ");
+                                    result.append(linkto);
+                                    result.append("\n");
+                                }
+                            }
+                        } else {
+                            result.append("  unexpected type for ");
+                            result.append(buffer);
+                            result.append("\n");
+                        }
+                    }
+                }
+            }
+            closedir(d);
+        } else {
+            result.append("couldn't open ");
+            result.append(buffer);
+            result.append("\n");
+        }
+
+        gLooperRoster.dump(fd, args);
+
+        bool dumpMem = false;
+        bool unreachableMemory = false;
+        for (size_t i = 0; i < args.size(); i++) {
+            if (args[i] == String16("-m")) {
+                dumpMem = true;
+            } else if (args[i] == String16("--unreachable")) {
+                unreachableMemory = true;
+            }
+        }
+        if (dumpMem) {
+            result.append("\nDumping memory:\n");
+            std::string s = dumpMemoryAddresses(100 /* limit */);
+            result.append(s.c_str(), s.size());
+        }
+        if (unreachableMemory) {
+            result.append("\nDumping unreachable memory:\n");
+            // TODO - should limit be an argument parameter?
+            // TODO: enable GetUnreachableMemoryString if it's part of stable API
+            //std::string s = GetUnreachableMemoryString(true /* contents */, 10000 /* limit */);
+            //result.append(s.c_str(), s.size());
+        }
+    }
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+}  // anonymous namespace
+
+//static
+sp<MediaPlayer2> MediaPlayer2::Create() {
+    sp<MediaPlayer2> player = new MediaPlayer2();
+
+    if (!player->init()) {
+        return NULL;
+    }
+
+    ALOGV("Create new player(%p)", player.get());
+
+    addPlayer(player);
+    return player;
+}
+
+// static
+status_t MediaPlayer2::DumpAll(int fd, const Vector<String16>& args) {
+    return dumpPlayers(fd, args);
+}
+
+MediaPlayer2::MediaPlayer2() {
     ALOGV("constructor");
     mSrcId = 0;
+    mLockThreadId = 0;
     mListener = NULL;
-    mCookie = NULL;
     mStreamType = AUDIO_STREAM_MUSIC;
     mAudioAttributesParcel = NULL;
     mCurrentPosition = -1;
@@ -66,14 +413,18 @@
     mLoop = false;
     mLeftVolume = mRightVolume = 1.0;
     mVideoWidth = mVideoHeight = 0;
-    mLockThreadId = 0;
     mAudioSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
     AudioSystem::acquireAudioSessionId(mAudioSessionId, -1);
     mSendLevel = 0;
+
+    // TODO: get pid and uid from JAVA
+    mPid = IPCThreadState::self()->getCallingPid();
+    mUid = IPCThreadState::self()->getCallingUid();
+
+    mAudioAttributes = NULL;
 }
 
-MediaPlayer2::~MediaPlayer2()
-{
+MediaPlayer2::~MediaPlayer2() {
     ALOGV("destructor");
     if (mAudioAttributesParcel != NULL) {
         delete mAudioAttributesParcel;
@@ -81,13 +432,21 @@
     }
     AudioSystem::releaseAudioSessionId(mAudioSessionId, -1);
     disconnect();
-    IPCThreadState::self()->flushCommands();
+    removePlayer(this);
+    if (mAudioAttributes != NULL) {
+        free(mAudioAttributes);
+    }
 }
 
-void MediaPlayer2::disconnect()
-{
+bool MediaPlayer2::init() {
+    // TODO: after merge with NuPlayer2Driver, MediaPlayer2 will have its own
+    // looper for notification.
+    return true;
+}
+
+void MediaPlayer2::disconnect() {
     ALOGV("disconnect");
-    sp<MediaPlayer2Engine> p;
+    sp<MediaPlayer2Interface> p;
     {
         Mutex::Autolock _l(mLock);
         p = mPlayer;
@@ -95,13 +454,17 @@
     }
 
     if (p != 0) {
-        p->disconnect();
+        p->setListener(NULL);
+        p->reset();
+    }
+
+    {
+        Mutex::Autolock _l(mLock);
+        disconnectNativeWindow_l();
     }
 }
 
-// always call with lock held
-void MediaPlayer2::clear_l()
-{
+void MediaPlayer2::clear_l() {
     mCurrentPosition = -1;
     mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
     mSeekPosition = -1;
@@ -109,8 +472,7 @@
     mVideoWidth = mVideoHeight = 0;
 }
 
-status_t MediaPlayer2::setListener(const sp<MediaPlayer2Listener>& listener)
-{
+status_t MediaPlayer2::setListener(const sp<MediaPlayer2Listener>& listener) {
     ALOGV("setListener");
     Mutex::Autolock _l(mLock);
     mListener = listener;
@@ -127,51 +489,54 @@
     return OK;
 }
 
-status_t MediaPlayer2::attachNewPlayer(const sp<MediaPlayer2Engine>& player, long srcId)
-{
-    status_t err = UNKNOWN_ERROR;
-    sp<MediaPlayer2Engine> p;
-    { // scope for the lock
-        Mutex::Autolock _l(mLock);
-
-        if ( !( (mCurrentState & MEDIA_PLAYER2_IDLE) ||
-                (mCurrentState == MEDIA_PLAYER2_STATE_ERROR ) ) ) {
-            ALOGE("attachNewPlayer called in state %d", mCurrentState);
-            return INVALID_OPERATION;
-        }
-
-        clear_l();
-        p = mPlayer;
-        mPlayer = player;
-        mSrcId = srcId;
-        if (player != 0) {
-            mCurrentState = MEDIA_PLAYER2_INITIALIZED;
-            err = NO_ERROR;
-        } else {
-            ALOGE("Unable to create media player");
-        }
-    }
-
-    if (p != 0) {
-        p->disconnect();
-    }
-
-    return err;
-}
-
-status_t MediaPlayer2::setDataSource(const sp<DataSourceDesc> &dsd)
-{
+status_t MediaPlayer2::setDataSource(const sp<DataSourceDesc> &dsd) {
     if (dsd == NULL) {
         return BAD_VALUE;
     }
-    ALOGV("setDataSource type(%d)", dsd->mType);
-    status_t err = UNKNOWN_ERROR;
-    sp<MediaPlayer2Engine> player(MediaPlayer2Manager::get().create(this, mAudioSessionId));
-    if (NO_ERROR != player->setDataSource(dsd)) {
-        player.clear();
+    ALOGV("setDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId);
+
+    sp<MediaPlayer2Interface> oldPlayer;
+
+    Mutex::Autolock _l(mLock);
+    {
+        if (!((mCurrentState & MEDIA_PLAYER2_IDLE)
+              || mCurrentState == MEDIA_PLAYER2_STATE_ERROR)) {
+            ALOGE("setDataSource called in wrong state %d", mCurrentState);
+            return INVALID_OPERATION;
+        }
+
+        sp<MediaPlayer2Interface> player = new NuPlayer2Driver(mPid, mUid);
+        status_t err = player->initCheck();
+        if (err != NO_ERROR) {
+            ALOGE("Failed to create player object, initCheck failed(%d)", err);
+            return err;
+        }
+
+        clear_l();
+
+        player->setListener(new proxyListener(this));
+        mAudioOutput = new MediaPlayer2AudioOutput(mAudioSessionId, mUid,
+                mPid, mAudioAttributes, new AudioDeviceUpdatedNotifier(player));
+        player->setAudioSink(mAudioOutput);
+
+        err = player->setDataSource(dsd);
+        if (err != OK) {
+            ALOGE("setDataSource error: %d", err);
+            return err;
+        }
+
+        sp<MediaPlayer2Interface> oldPlayer = mPlayer;
+        mPlayer = player;
+        mSrcId = dsd->mId;
+        mCurrentState = MEDIA_PLAYER2_INITIALIZED;
     }
-    err = attachNewPlayer(player, dsd->mId);
-    return err;
+
+    if (oldPlayer != NULL) {
+        oldPlayer->setListener(NULL);
+        oldPlayer->reset();
+    }
+
+    return OK;
 }
 
 status_t MediaPlayer2::prepareNextDataSource(const sp<DataSourceDesc> &dsd) {
@@ -181,81 +546,179 @@
     ALOGV("prepareNextDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId);
 
     Mutex::Autolock _l(mLock);
-    if (mPlayer != NULL) {
-        return mPlayer->prepareNextDataSource(dsd);
+    if (mPlayer == NULL) {
+        ALOGE("prepareNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
+        return INVALID_OPERATION;
     }
-    ALOGE("prepareNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
-    return INVALID_OPERATION;
+    return mPlayer->prepareNextDataSource(dsd);
 }
 
 status_t MediaPlayer2::playNextDataSource(int64_t srcId) {
     ALOGV("playNextDataSource srcId(%lld)", (long long)srcId);
 
     Mutex::Autolock _l(mLock);
-    if (mPlayer != NULL) {
-        mSrcId = srcId;
-        return mPlayer->playNextDataSource(srcId);
+    if (mPlayer == NULL) {
+        ALOGE("playNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
+        return INVALID_OPERATION;
     }
-    ALOGE("playNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
-    return INVALID_OPERATION;
+    mSrcId = srcId;
+    return mPlayer->playNextDataSource(srcId);
 }
 
-status_t MediaPlayer2::invoke(const Parcel& request, Parcel *reply)
-{
+status_t MediaPlayer2::invoke(const Parcel& request, Parcel *reply) {
     Mutex::Autolock _l(mLock);
     const bool hasBeenInitialized =
             (mCurrentState != MEDIA_PLAYER2_STATE_ERROR) &&
             ((mCurrentState & MEDIA_PLAYER2_IDLE) != MEDIA_PLAYER2_IDLE);
-    if ((mPlayer != NULL) && hasBeenInitialized) {
-        ALOGV("invoke %zu", request.dataSize());
-        return  mPlayer->invoke(request, reply);
+    if ((mPlayer == NULL) || !hasBeenInitialized) {
+        ALOGE("invoke failed: wrong state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
+        return INVALID_OPERATION;
     }
-    ALOGE("invoke failed: wrong state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
-    return INVALID_OPERATION;
+    ALOGV("invoke %zu", request.dataSize());
+    return mPlayer->invoke(request, reply);
 }
 
-status_t MediaPlayer2::setMetadataFilter(const Parcel& filter)
-{
+// This call doesn't need to access the native player.
+status_t MediaPlayer2::setMetadataFilter(const Parcel& filter) {
     ALOGD("setMetadataFilter");
-    Mutex::Autolock lock(mLock);
-    if (mPlayer == NULL) {
-        return NO_INIT;
+
+    status_t status;
+    media::Metadata::Filter allow, drop;
+
+    if (unmarshallFilter(filter, &allow, &status) &&
+        unmarshallFilter(filter, &drop, &status)) {
+        Mutex::Autolock lock(mLock);
+
+        mMetadataAllow = allow;
+        mMetadataDrop = drop;
     }
-    return mPlayer->setMetadataFilter(filter);
+    return status;
 }
 
-status_t MediaPlayer2::getMetadata(bool update_only, bool apply_filter, Parcel *metadata)
-{
+status_t MediaPlayer2::getMetadata(bool update_only, bool /* apply_filter */, Parcel *reply) {
     ALOGD("getMetadata");
+    sp<MediaPlayer2Interface> player;
+    media::Metadata::Filter ids;
     Mutex::Autolock lock(mLock);
-    if (mPlayer == NULL) {
+    {
+        if (mPlayer == NULL) {
+            return NO_INIT;
+        }
+
+        player = mPlayer;
+        // Placeholder for the return code, updated by the caller.
+        reply->writeInt32(-1);
+
+        // We don't block notifications while we fetch the data. We clear
+        // mMetadataUpdated first so we don't lose notifications happening
+        // during the rest of this call.
+        if (update_only) {
+            ids = mMetadataUpdated;
+        }
+        mMetadataUpdated.clear();
+    }
+
+    media::Metadata metadata(reply);
+
+    metadata.appendHeader();
+    status_t status = player->getMetadata(ids, reply);
+
+    if (status != OK) {
+        metadata.resetParcel();
+        ALOGE("getMetadata failed %d", status);
+        return status;
+    }
+
+    // FIXME: ement filtering on the result. Not critical since
+    // filtering takes place on the update notifications already. This
+    // would be when all the metadata are fetch and a filter is set.
+
+    // Everything is fine, update the metadata length.
+    metadata.updateLength();
+    return OK;
+}
+
+void MediaPlayer2::disconnectNativeWindow_l() {
+    if (mConnectedWindow != NULL && mConnectedWindow->getANativeWindow() != NULL) {
+        status_t err = native_window_api_disconnect(
+                mConnectedWindow->getANativeWindow(), NATIVE_WINDOW_API_MEDIA);
+
+        if (err != OK) {
+            ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
+                  strerror(-err), err);
+        }
+    }
+    mConnectedWindow.clear();
+}
+
+status_t MediaPlayer2::setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww) {
+    ANativeWindow *anw = (nww == NULL ? NULL : nww->getANativeWindow());
+    ALOGV("setVideoSurfaceTexture(%p)", anw);
+    Mutex::Autolock _l(mLock);
+    if (mPlayer == 0) {
         return NO_INIT;
     }
-    return mPlayer->getMetadata(update_only, apply_filter, metadata);
+
+    if (anw != NULL) {
+        if (mConnectedWindow != NULL
+            && mConnectedWindow->getANativeWindow() == anw) {
+            return OK;
+        }
+        status_t err = native_window_api_connect(anw, NATIVE_WINDOW_API_MEDIA);
+
+        if (err != OK) {
+            ALOGE("setVideoSurfaceTexture failed: %d", err);
+            // Note that we must do the reset before disconnecting from the ANW.
+            // Otherwise queue/dequeue calls could be made on the disconnected
+            // ANW, which may result in errors.
+            mPlayer->reset();
+            disconnectNativeWindow_l();
+            return err;
+        }
+    }
+
+    // Note that we must set the player's new GraphicBufferProducer before
+    // disconnecting the old one.  Otherwise queue/dequeue calls could be made
+    // on the disconnected ANW, which may result in errors.
+    status_t err = mPlayer->setVideoSurfaceTexture(nww);
+
+    disconnectNativeWindow_l();
+
+    if (err == OK) {
+        mConnectedWindow = nww;
+        mLock.unlock();
+    } else if (anw != NULL) {
+        mLock.unlock();
+        status_t err = native_window_api_disconnect(anw, NATIVE_WINDOW_API_MEDIA);
+
+        if (err != OK) {
+            ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
+                  strerror(-err), err);
+        }
+    }
+
+    return err;
 }
 
-status_t MediaPlayer2::setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww)
-{
-    ALOGV("setVideoSurfaceTexture");
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == 0) return NO_INIT;
-    return mPlayer->setVideoSurfaceTexture(nww);
-}
-
-status_t MediaPlayer2::getBufferingSettings(BufferingSettings* buffering /* nonnull */)
-{
+status_t MediaPlayer2::getBufferingSettings(BufferingSettings* buffering /* nonnull */) {
     ALOGV("getBufferingSettings");
 
     Mutex::Autolock _l(mLock);
     if (mPlayer == 0) {
         return NO_INIT;
     }
-    return mPlayer->getBufferingSettings(buffering);
+
+    status_t ret = mPlayer->getBufferingSettings(buffering);
+    if (ret == NO_ERROR) {
+        ALOGV("getBufferingSettings{%s}", buffering->toString().string());
+    } else {
+        ALOGE("getBufferingSettings returned %d", ret);
+    }
+    return ret;
 }
 
-status_t MediaPlayer2::setBufferingSettings(const BufferingSettings& buffering)
-{
-    ALOGV("setBufferingSettings");
+status_t MediaPlayer2::setBufferingSettings(const BufferingSettings& buffering) {
+    ALOGV("setBufferingSettings{%s}", buffering.toString().string());
 
     Mutex::Autolock _l(mLock);
     if (mPlayer == 0) {
@@ -264,14 +727,37 @@
     return mPlayer->setBufferingSettings(buffering);
 }
 
-// must call with lock held
-status_t MediaPlayer2::prepareAsync_l()
-{
-    if ( (mPlayer != 0) && ( mCurrentState & (MEDIA_PLAYER2_INITIALIZED | MEDIA_PLAYER2_STOPPED) ) ) {
+status_t MediaPlayer2::setAudioAttributes_l(const Parcel &parcel) {
+    if (mAudioAttributes != NULL) {
+        free(mAudioAttributes);
+    }
+    mAudioAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
+    if (mAudioAttributes == NULL) {
+        return NO_MEMORY;
+    }
+    unmarshallAudioAttributes(parcel, mAudioAttributes);
+
+    ALOGV("setAudioAttributes_l() usage=%d content=%d flags=0x%x tags=%s",
+            mAudioAttributes->usage, mAudioAttributes->content_type, mAudioAttributes->flags,
+            mAudioAttributes->tags);
+
+    if (mAudioOutput != 0) {
+        mAudioOutput->setAudioAttributes(mAudioAttributes);
+    }
+    return NO_ERROR;
+}
+
+status_t MediaPlayer2::prepareAsync() {
+    ALOGV("prepareAsync");
+    Mutex::Autolock _l(mLock);
+    if ((mPlayer != 0) && (mCurrentState & (MEDIA_PLAYER2_INITIALIZED | MEDIA_PLAYER2_STOPPED))) {
         if (mAudioAttributesParcel != NULL) {
-            mPlayer->setParameter(MEDIA2_KEY_PARAMETER_AUDIO_ATTRIBUTES, *mAudioAttributesParcel);
-        } else {
-            mPlayer->setAudioStreamType(mStreamType);
+            status_t err = setAudioAttributes_l(*mAudioAttributesParcel);
+            if (err != OK) {
+                return err;
+            }
+        } else if (mAudioOutput != 0) {
+            mAudioOutput->setAudioStreamType(mStreamType);
         }
         mCurrentState = MEDIA_PLAYER2_PREPARING;
         return mPlayer->prepareAsync();
@@ -280,15 +766,7 @@
     return INVALID_OPERATION;
 }
 
-status_t MediaPlayer2::prepareAsync()
-{
-    ALOGV("prepareAsync");
-    Mutex::Autolock _l(mLock);
-    return prepareAsync_l();
-}
-
-status_t MediaPlayer2::start()
-{
+status_t MediaPlayer2::start() {
     ALOGV("start");
 
     status_t ret = NO_ERROR;
@@ -301,8 +779,14 @@
     } else if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER2_PREPARED |
                     MEDIA_PLAYER2_PLAYBACK_COMPLETE | MEDIA_PLAYER2_PAUSED ) ) ) {
         mPlayer->setLooping(mLoop);
-        mPlayer->setVolume(mLeftVolume, mRightVolume);
-        mPlayer->setAuxEffectSendLevel(mSendLevel);
+
+        if (mAudioOutput != 0) {
+            mAudioOutput->setVolume(mLeftVolume, mRightVolume);
+        }
+
+        if (mAudioOutput != 0) {
+            mAudioOutput->setAuxEffectSendLevel(mSendLevel);
+        }
         mCurrentState = MEDIA_PLAYER2_STARTED;
         ret = mPlayer->start();
         if (ret != NO_ERROR) {
@@ -322,8 +806,7 @@
     return ret;
 }
 
-status_t MediaPlayer2::stop()
-{
+status_t MediaPlayer2::stop() {
     ALOGV("stop");
     Mutex::Autolock _l(mLock);
     if (mCurrentState & MEDIA_PLAYER2_STOPPED) return NO_ERROR;
@@ -341,8 +824,7 @@
     return INVALID_OPERATION;
 }
 
-status_t MediaPlayer2::pause()
-{
+status_t MediaPlayer2::pause() {
     ALOGV("pause");
     Mutex::Autolock _l(mLock);
     if (mCurrentState & (MEDIA_PLAYER2_PAUSED|MEDIA_PLAYER2_PLAYBACK_COMPLETE))
@@ -360,12 +842,10 @@
     return INVALID_OPERATION;
 }
 
-bool MediaPlayer2::isPlaying()
-{
+bool MediaPlayer2::isPlaying() {
     Mutex::Autolock _l(mLock);
     if (mPlayer != 0) {
-        bool temp = false;
-        mPlayer->isPlaying(&temp);
+        bool temp = mPlayer->isPlaying();
         ALOGV("isPlaying: %d", temp);
         if ((mCurrentState & MEDIA_PLAYER2_STARTED) && ! temp) {
             ALOGE("internal/external state mismatch corrected");
@@ -380,13 +860,12 @@
     return false;
 }
 
-status_t MediaPlayer2::setPlaybackSettings(const AudioPlaybackRate& rate)
-{
+status_t MediaPlayer2::setPlaybackSettings(const AudioPlaybackRate& rate) {
     ALOGV("setPlaybackSettings: %f %f %d %d",
             rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
     // Negative speed and pitch does not make sense. Further validation will
     // be done by the respective mediaplayers.
-    if (rate.mSpeed < 0.f || rate.mPitch < 0.f) {
+    if (rate.mSpeed <= 0.f || rate.mPitch < 0.f) {
         return BAD_VALUE;
     }
     Mutex::Autolock _l(mLock);
@@ -394,36 +873,27 @@
         return INVALID_OPERATION;
     }
 
-    if (rate.mSpeed != 0.f && !(mCurrentState & MEDIA_PLAYER2_STARTED)
-            && (mCurrentState & (MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_PAUSED
-                    | MEDIA_PLAYER2_PLAYBACK_COMPLETE))) {
-        mPlayer->setLooping(mLoop);
-        mPlayer->setVolume(mLeftVolume, mRightVolume);
-        mPlayer->setAuxEffectSendLevel(mSendLevel);
-    }
-
     status_t err = mPlayer->setPlaybackSettings(rate);
-    if (err == OK) {
-        if (rate.mSpeed == 0.f && mCurrentState == MEDIA_PLAYER2_STARTED) {
-            mCurrentState = MEDIA_PLAYER2_PAUSED;
-        } else if (rate.mSpeed != 0.f
-                && (mCurrentState & (MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_PAUSED
-                    | MEDIA_PLAYER2_PLAYBACK_COMPLETE))) {
-            mCurrentState = MEDIA_PLAYER2_STARTED;
-        }
-    }
     return err;
 }
 
-status_t MediaPlayer2::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */)
-{
+status_t MediaPlayer2::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) {
     Mutex::Autolock _l(mLock);
-    if (mPlayer == 0) return INVALID_OPERATION;
+    if (mPlayer == 0) {
+        return INVALID_OPERATION;
+    }
     return mPlayer->getPlaybackSettings(rate);
+    status_t ret = mPlayer->getPlaybackSettings(rate);
+    if (ret == NO_ERROR) {
+        ALOGV("getPlaybackSettings(%f, %f, %d, %d)",
+                rate->mSpeed, rate->mPitch, rate->mFallbackMode, rate->mStretchMode);
+    } else {
+        ALOGV("getPlaybackSettings returned %d", ret);
+    }
+    return ret;
 }
 
-status_t MediaPlayer2::setSyncSettings(const AVSyncSettings& sync, float videoFpsHint)
-{
+status_t MediaPlayer2::setSyncSettings(const AVSyncSettings& sync, float videoFpsHint) {
     ALOGV("setSyncSettings: %u %u %f %f",
             sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint);
     Mutex::Autolock _l(mLock);
@@ -432,83 +902,92 @@
 }
 
 status_t MediaPlayer2::getSyncSettings(
-        AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */)
-{
+        AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */) {
     Mutex::Autolock _l(mLock);
     if (mPlayer == 0) return INVALID_OPERATION;
-    return mPlayer->getSyncSettings(sync, videoFps);
+    status_t ret = mPlayer->getSyncSettings(sync, videoFps);
+    if (ret == NO_ERROR) {
+        ALOGV("getSyncSettings(%u, %u, %f, %f)",
+                sync->mSource, sync->mAudioAdjustMode, sync->mTolerance, *videoFps);
+    } else {
+        ALOGV("getSyncSettings returned %d", ret);
+    }
+    return ret;
+
 }
 
-status_t MediaPlayer2::getVideoWidth(int *w)
-{
+status_t MediaPlayer2::getVideoWidth(int *w) {
     ALOGV("getVideoWidth");
     Mutex::Autolock _l(mLock);
-    if (mPlayer == 0) return INVALID_OPERATION;
+    if (mPlayer == 0) {
+        return INVALID_OPERATION;
+    }
     *w = mVideoWidth;
     return NO_ERROR;
 }
 
-status_t MediaPlayer2::getVideoHeight(int *h)
-{
+status_t MediaPlayer2::getVideoHeight(int *h) {
     ALOGV("getVideoHeight");
     Mutex::Autolock _l(mLock);
-    if (mPlayer == 0) return INVALID_OPERATION;
+    if (mPlayer == 0) {
+        return INVALID_OPERATION;
+    }
     *h = mVideoHeight;
     return NO_ERROR;
 }
 
-status_t MediaPlayer2::getCurrentPosition(int *msec)
-{
+status_t MediaPlayer2::getCurrentPosition(int *msec) {
     ALOGV("getCurrentPosition");
     Mutex::Autolock _l(mLock);
-    if (mPlayer != 0) {
-        if (mCurrentPosition >= 0) {
-            ALOGV("Using cached seek position: %d", mCurrentPosition);
-            *msec = mCurrentPosition;
-            return NO_ERROR;
-        }
-        return mPlayer->getCurrentPosition(msec);
+    if (mPlayer == 0) {
+        return INVALID_OPERATION;
     }
-    return INVALID_OPERATION;
+    if (mCurrentPosition >= 0) {
+        ALOGV("Using cached seek position: %d", mCurrentPosition);
+        *msec = mCurrentPosition;
+        return NO_ERROR;
+    }
+    status_t ret = mPlayer->getCurrentPosition(msec);
+    if (ret == NO_ERROR) {
+        ALOGV("getCurrentPosition = %d", *msec);
+    } else {
+        ALOGE("getCurrentPosition returned %d", ret);
+    }
+    return ret;
 }
 
-status_t MediaPlayer2::getDuration_l(int *msec)
-{
+status_t MediaPlayer2::getDuration(int *msec) {
+    Mutex::Autolock _l(mLock);
     ALOGV("getDuration_l");
     bool isValidState = (mCurrentState & (MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
             MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_STOPPED | MEDIA_PLAYER2_PLAYBACK_COMPLETE));
-    if (mPlayer != 0 && isValidState) {
-        int durationMs;
-        status_t ret = mPlayer->getDuration(&durationMs);
-
-        if (ret != OK) {
-            // Do not enter error state just because no duration was available.
-            durationMs = -1;
-            ret = OK;
-        }
-
-        if (msec) {
-            *msec = durationMs;
-        }
-        return ret;
+    if (mPlayer == 0 || !isValidState) {
+        ALOGE("Attempt to call getDuration in wrong state: mPlayer=%p, mCurrentState=%u",
+                mPlayer.get(), mCurrentState);
+        return INVALID_OPERATION;
     }
-    ALOGE("Attempt to call getDuration in wrong state: mPlayer=%p, mCurrentState=%u",
-            mPlayer.get(), mCurrentState);
-    return INVALID_OPERATION;
+    int durationMs;
+    status_t ret = mPlayer->getDuration(&durationMs);
+
+    if (ret == NO_ERROR) {
+        ALOGV("getDuration = %d", durationMs);
+    } else {
+        ALOGE("getDuration returned %d", ret);
+        // Do not enter error state just because no duration was available.
+        durationMs = -1;
+    }
+
+    if (msec) {
+        *msec = durationMs;
+    }
+    return OK;
 }
 
-status_t MediaPlayer2::getDuration(int *msec)
-{
-    Mutex::Autolock _l(mLock);
-    return getDuration_l(msec);
-}
-
-status_t MediaPlayer2::seekTo_l(int msec, MediaPlayer2SeekMode mode)
-{
+status_t MediaPlayer2::seekTo_l(int msec, MediaPlayer2SeekMode mode) {
     ALOGV("seekTo (%d, %d)", msec, mode);
     if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED |
             MEDIA_PLAYER2_PAUSED |  MEDIA_PLAYER2_PLAYBACK_COMPLETE) ) ) {
-        if ( msec < 0 ) {
+        if (msec < 0) {
             ALOGW("Attempt to seek to invalid position: %d", msec);
             msec = 0;
         }
@@ -537,8 +1016,7 @@
             mSeekPosition = msec;
             mSeekMode = mode;
             return mPlayer->seekTo(msec, mode);
-        }
-        else {
+        } else {
             ALOGV("Seek in progress - queue up seekTo[%d, %d]", msec, mode);
             return NO_ERROR;
         }
@@ -548,8 +1026,7 @@
     return INVALID_OPERATION;
 }
 
-status_t MediaPlayer2::seekTo(int msec, MediaPlayer2SeekMode mode)
-{
+status_t MediaPlayer2::seekTo(int msec, MediaPlayer2SeekMode mode) {
     mLockThreadId = getThreadId();
     Mutex::Autolock _l(mLock);
     status_t result = seekTo_l(msec, mode);
@@ -558,26 +1035,27 @@
     return result;
 }
 
-status_t MediaPlayer2::notifyAt(int64_t mediaTimeUs)
-{
+status_t MediaPlayer2::notifyAt(int64_t mediaTimeUs) {
     Mutex::Autolock _l(mLock);
     if (mPlayer != 0) {
-        return mPlayer->notifyAt(mediaTimeUs);
+        return INVALID_OPERATION;
     }
-    return INVALID_OPERATION;
+
+    return mPlayer->notifyAt(mediaTimeUs);
 }
 
-status_t MediaPlayer2::reset_l()
-{
+status_t MediaPlayer2::reset_l() {
     mLoop = false;
-    if (mCurrentState == MEDIA_PLAYER2_IDLE) return NO_ERROR;
+    if (mCurrentState == MEDIA_PLAYER2_IDLE) {
+        return NO_ERROR;
+    }
     if (mPlayer != 0) {
         status_t ret = mPlayer->reset();
         if (ret != NO_ERROR) {
             ALOGE("reset() failed with return code (%d)", ret);
             mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
         } else {
-            mPlayer->disconnect();
+            mPlayer->setListener(NULL);
             mCurrentState = MEDIA_PLAYER2_IDLE;
         }
         // setDataSource has to be called again to create a
@@ -589,8 +1067,7 @@
     return NO_ERROR;
 }
 
-status_t MediaPlayer2::reset()
-{
+status_t MediaPlayer2::reset() {
     ALOGV("reset");
     mLockThreadId = getThreadId();
     Mutex::Autolock _l(mLock);
@@ -600,8 +1077,7 @@
     return result;
 }
 
-status_t MediaPlayer2::setAudioStreamType(audio_stream_type_t type)
-{
+status_t MediaPlayer2::setAudioStreamType(audio_stream_type_t type) {
     ALOGV("MediaPlayer2::setAudioStreamType");
     Mutex::Autolock _l(mLock);
     if (mStreamType == type) return NO_ERROR;
@@ -616,16 +1092,14 @@
     return OK;
 }
 
-status_t MediaPlayer2::getAudioStreamType(audio_stream_type_t *type)
-{
+status_t MediaPlayer2::getAudioStreamType(audio_stream_type_t *type) {
     ALOGV("getAudioStreamType");
     Mutex::Autolock _l(mLock);
     *type = mStreamType;
     return OK;
 }
 
-status_t MediaPlayer2::setLooping(int loop)
-{
+status_t MediaPlayer2::setLooping(int loop) {
     ALOGV("MediaPlayer2::setLooping");
     Mutex::Autolock _l(mLock);
     mLoop = (loop != 0);
@@ -645,20 +1119,18 @@
     return false;
 }
 
-status_t MediaPlayer2::setVolume(float leftVolume, float rightVolume)
-{
+status_t MediaPlayer2::setVolume(float leftVolume, float rightVolume) {
     ALOGV("MediaPlayer2::setVolume(%f, %f)", leftVolume, rightVolume);
     Mutex::Autolock _l(mLock);
     mLeftVolume = leftVolume;
     mRightVolume = rightVolume;
-    if (mPlayer != 0) {
-        return mPlayer->setVolume(leftVolume, rightVolume);
+    if (mAudioOutput != 0) {
+        mAudioOutput->setVolume(leftVolume, rightVolume);
     }
     return OK;
 }
 
-status_t MediaPlayer2::setAudioSessionId(audio_session_t sessionId)
-{
+status_t MediaPlayer2::setAudioSessionId(audio_session_t sessionId) {
     ALOGV("MediaPlayer2::setAudioSessionId(%d)", sessionId);
     Mutex::Autolock _l(mLock);
     if (!(mCurrentState & MEDIA_PLAYER2_IDLE)) {
@@ -676,40 +1148,36 @@
     return NO_ERROR;
 }
 
-audio_session_t MediaPlayer2::getAudioSessionId()
-{
+audio_session_t MediaPlayer2::getAudioSessionId() {
     Mutex::Autolock _l(mLock);
     return mAudioSessionId;
 }
 
-status_t MediaPlayer2::setAuxEffectSendLevel(float level)
-{
+status_t MediaPlayer2::setAuxEffectSendLevel(float level) {
     ALOGV("MediaPlayer2::setAuxEffectSendLevel(%f)", level);
     Mutex::Autolock _l(mLock);
     mSendLevel = level;
-    if (mPlayer != 0) {
-        return mPlayer->setAuxEffectSendLevel(level);
+    if (mAudioOutput != 0) {
+        return mAudioOutput->setAuxEffectSendLevel(level);
     }
     return OK;
 }
 
-status_t MediaPlayer2::attachAuxEffect(int effectId)
-{
+status_t MediaPlayer2::attachAuxEffect(int effectId) {
     ALOGV("MediaPlayer2::attachAuxEffect(%d)", effectId);
     Mutex::Autolock _l(mLock);
-    if (mPlayer == 0 ||
+    if (mAudioOutput == 0 ||
         (mCurrentState & MEDIA_PLAYER2_IDLE) ||
         (mCurrentState == MEDIA_PLAYER2_STATE_ERROR )) {
         ALOGE("attachAuxEffect called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
         return INVALID_OPERATION;
     }
 
-    return mPlayer->attachAuxEffect(effectId);
+    return mAudioOutput->attachAuxEffect(effectId);
 }
 
 // always call with lock held
-status_t MediaPlayer2::checkStateForKeySet_l(int key)
-{
+status_t MediaPlayer2::checkStateForKeySet_l(int key) {
     switch(key) {
     case MEDIA2_KEY_PARAMETER_AUDIO_ATTRIBUTES:
         if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
@@ -726,8 +1194,7 @@
     return OK;
 }
 
-status_t MediaPlayer2::setParameter(int key, const Parcel& request)
-{
+status_t MediaPlayer2::setParameter(int key, const Parcel& request) {
     ALOGV("MediaPlayer2::setParameter(%d)", key);
     status_t status = INVALID_OPERATION;
     Mutex::Autolock _l(mLock);
@@ -737,10 +1204,15 @@
     switch (key) {
     case MEDIA2_KEY_PARAMETER_AUDIO_ATTRIBUTES:
         // save the marshalled audio attributes
-        if (mAudioAttributesParcel != NULL) { delete mAudioAttributesParcel; };
+        if (mAudioAttributesParcel != NULL) {
+            delete mAudioAttributesParcel;
+        }
         mAudioAttributesParcel = new Parcel();
         mAudioAttributesParcel->appendFrom(&request, 0, request.dataSize());
-        status = OK;
+        status = setAudioAttributes_l(request);
+        if (status != OK) {
+            return status;
+        }
         break;
     default:
         ALOGV_IF(mPlayer == NULL, "setParameter: no active player");
@@ -753,25 +1225,59 @@
     return status;
 }
 
-status_t MediaPlayer2::getParameter(int key, Parcel *reply)
-{
+status_t MediaPlayer2::getParameter(int key, Parcel *reply) {
     ALOGV("MediaPlayer2::getParameter(%d)", key);
     Mutex::Autolock _l(mLock);
-    if (mPlayer != NULL) {
-        status_t status =  mPlayer->getParameter(key, reply);
-        if (status != OK) {
-            ALOGD("getParameter returns %d", status);
-        }
-        return status;
+    if (mPlayer == NULL) {
+        ALOGV("getParameter: no active player");
+        return INVALID_OPERATION;
     }
-    ALOGV("getParameter: no active player");
-    return INVALID_OPERATION;
+
+    status_t status =  mPlayer->getParameter(key, reply);
+    if (status != OK) {
+        ALOGD("getParameter returns %d", status);
+    }
+    return status;
 }
 
-void MediaPlayer2::notify(int64_t srcId, int msg, int ext1, int ext2, const Parcel *obj)
-{
+bool MediaPlayer2::shouldDropMetadata(media::Metadata::Type code) const {
+    Mutex::Autolock lock(mLock);
+
+    if (findMetadata(mMetadataDrop, code)) {
+        return true;
+    }
+
+    if (mMetadataAllow.isEmpty() || findMetadata(mMetadataAllow, code)) {
+        return false;
+    } else {
+        return true;
+    }
+}
+
+
+void MediaPlayer2::addNewMetadataUpdate(media::Metadata::Type metadata_type) {
+    Mutex::Autolock lock(mLock);
+    if (mMetadataUpdated.indexOf(metadata_type) < 0) {
+        mMetadataUpdated.add(metadata_type);
+    }
+}
+
+void MediaPlayer2::notify(int64_t srcId, int msg, int ext1, int ext2, const Parcel *obj) {
     ALOGV("message received srcId=%lld, msg=%d, ext1=%d, ext2=%d",
           (long long)srcId, msg, ext1, ext2);
+
+    if (MEDIA2_INFO == msg && MEDIA2_INFO_METADATA_UPDATE == ext1) {
+        const media::Metadata::Type metadata_type = ext2;
+
+        if(shouldDropMetadata(metadata_type)) {
+            return;
+        }
+
+        // Update the list of metadata that have changed. getMetadata
+        // also access mMetadataUpdated and clears it.
+        addNewMetadataUpdate(metadata_type);
+    }
+
     bool send = true;
     bool locked = false;
 
@@ -881,24 +1387,12 @@
     }
 }
 
-status_t MediaPlayer2::setNextMediaPlayer(const sp<MediaPlayer2>& next) {
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == NULL) {
-        return NO_INIT;
-    }
-
-    if (next != NULL && !(next->mCurrentState &
-            (MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE))) {
-        ALOGE("next player is not prepared");
-        return INVALID_OPERATION;
-    }
-
-    return mPlayer->setNextPlayer(next == NULL ? NULL : next->mPlayer);
+status_t MediaPlayer2::setNextMediaPlayer(const sp<MediaPlayer2>& /* next */) {
+    return INVALID_OPERATION;
 }
 
 // Modular DRM
-status_t MediaPlayer2::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId)
-{
+status_t MediaPlayer2::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId) {
     // TODO change to ALOGV
     ALOGD("prepareDrm: uuid: %p  drmSessionId: %p(%zu)", uuid,
             drmSessionId.array(), drmSessionId.size());
@@ -931,8 +1425,7 @@
     return status;
 }
 
-status_t MediaPlayer2::releaseDrm()
-{
+status_t MediaPlayer2::releaseDrm() {
     Mutex::Autolock _l(mLock);
     if (mPlayer == NULL) {
         return NO_INIT;
@@ -960,39 +1453,74 @@
     return status;
 }
 
-status_t MediaPlayer2::setOutputDevice(audio_port_handle_t deviceId)
-{
+status_t MediaPlayer2::setOutputDevice(audio_port_handle_t deviceId) {
     Mutex::Autolock _l(mLock);
-    if (mPlayer == NULL) {
-        ALOGV("setOutputDevice: player not init");
+    if (mAudioOutput == NULL) {
+        ALOGV("setOutputDevice: audio sink not init");
         return NO_INIT;
     }
-    return mPlayer->setOutputDevice(deviceId);
+    return mAudioOutput->setOutputDevice(deviceId);
 }
 
-audio_port_handle_t MediaPlayer2::getRoutedDeviceId()
-{
+audio_port_handle_t MediaPlayer2::getRoutedDeviceId() {
     Mutex::Autolock _l(mLock);
-    if (mPlayer == NULL) {
-        ALOGV("getRoutedDeviceId: player not init");
+    if (mAudioOutput == NULL) {
+        ALOGV("getRoutedDeviceId: audio sink not init");
         return AUDIO_PORT_HANDLE_NONE;
     }
     audio_port_handle_t deviceId;
-    status_t status = mPlayer->getRoutedDeviceId(&deviceId);
+    status_t status = mAudioOutput->getRoutedDeviceId(&deviceId);
     if (status != NO_ERROR) {
         return AUDIO_PORT_HANDLE_NONE;
     }
     return deviceId;
 }
 
-status_t MediaPlayer2::enableAudioDeviceCallback(bool enabled)
-{
+status_t MediaPlayer2::enableAudioDeviceCallback(bool enabled) {
     Mutex::Autolock _l(mLock);
-    if (mPlayer == NULL) {
+    if (mAudioOutput == NULL) {
         ALOGV("addAudioDeviceCallback: player not init");
         return NO_INIT;
     }
-    return mPlayer->enableAudioDeviceCallback(enabled);
+    return mAudioOutput->enableAudioDeviceCallback(enabled);
+}
+
+status_t MediaPlayer2::dump(int fd, const Vector<String16>& args) {
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    result.append(" MediaPlayer2\n");
+    snprintf(buffer, 255, "  pid(%d), looping(%s)\n", mPid, mLoop?"true": "false");
+    result.append(buffer);
+
+    sp<MediaPlayer2Interface> player;
+    sp<MediaPlayer2AudioOutput> audioOutput;
+    bool locked = false;
+    for (int i = 0; i < kDumpLockRetries; ++i) {
+        if (mLock.tryLock() == NO_ERROR) {
+            locked = true;
+            break;
+        }
+        usleep(kDumpLockSleepUs);
+    }
+
+    if (locked) {
+        player = mPlayer;
+        audioOutput = mAudioOutput;
+        mLock.unlock();
+    } else {
+        result.append("  lock is taken, no dump from player and audio output\n");
+    }
+    write(fd, result.string(), result.size());
+
+    if (player != NULL) {
+        player->dump(fd, args);
+    }
+    if (audioOutput != 0) {
+        audioOutput->dump(fd, args);
+    }
+    write(fd, "\n", 1);
+    return NO_ERROR;
 }
 
 } // namespace android