Merge "aaudio: clip bufferSize at top of MMAP code"
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 7623d6d..c62833d 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -10,7 +10,7 @@
 LOCAL_SHARED_LIBRARIES := \
         libstagefright libmedia libmedia_omx libmediaextractor libutils libbinder \
         libstagefright_foundation libjpeg libui libgui libcutils liblog \
-        libhidlmemory \
+        libhidlbase \
         android.hardware.media.omx@1.0 \
 
 LOCAL_C_INCLUDES:= \
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 50b034a..ddc4b16 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -36,7 +36,6 @@
 #include <media/MediaSource.h>
 #include <media/ICrypto.h>
 #include <media/IMediaHTTPService.h>
-#include <media/IMediaCodecService.h>
 #include <media/IMediaPlayerService.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ALooper.h>
@@ -68,7 +67,6 @@
 #include <gui/SurfaceComposerClient.h>
 
 #include <android/hardware/media/omx/1.0/IOmx.h>
-#include <media/omx/1.0/WOmx.h>
 
 using namespace android;
 
@@ -912,37 +910,24 @@
     }
 
     if (listComponents) {
-        sp<IOMX> omx;
-        if (property_get_bool("persist.media.treble_omx", true)) {
-            using namespace ::android::hardware::media::omx::V1_0;
-            sp<IOmx> tOmx = IOmx::getService();
+        using ::android::hardware::hidl_vec;
+        using ::android::hardware::hidl_string;
+        using namespace ::android::hardware::media::omx::V1_0;
+        sp<IOmx> omx = IOmx::getService();
+        CHECK(omx.get() != nullptr);
 
-            CHECK(tOmx.get() != NULL);
-
-            omx = new utils::LWOmx(tOmx);
-        } else {
-            sp<IServiceManager> sm = defaultServiceManager();
-            sp<IBinder> binder = sm->getService(String16("media.codec"));
-            sp<IMediaCodecService> service = interface_cast<IMediaCodecService>(binder);
-
-            CHECK(service.get() != NULL);
-
-            omx = service->getOMX();
-        }
-        CHECK(omx.get() != NULL);
-
-        List<IOMX::ComponentInfo> list;
-        omx->listNodes(&list);
-
-        for (List<IOMX::ComponentInfo>::iterator it = list.begin();
-             it != list.end(); ++it) {
-            printf("%s\t Roles: ", (*it).mName.string());
-            for (List<String8>::iterator itRoles = (*it).mRoles.begin() ;
-                    itRoles != (*it).mRoles.end() ; ++itRoles) {
-                printf("%s\t", (*itRoles).string());
-            }
-            printf("\n");
-        }
+        hidl_vec<IOmx::ComponentInfo> nodeList;
+        auto transStatus = omx->listNodes([](
+                const auto& status, const auto& nodeList) {
+                    CHECK(status == Status::OK);
+                    for (const auto& info : nodeList) {
+                        printf("%s\t Roles: ", info.mName.c_str());
+                        for (const auto& role : info.mRoles) {
+                            printf("%s\t", role.c_str());
+                        }
+                    }
+                });
+        CHECK(transStatus.isOk());
     }
 
     sp<SurfaceComposerClient> composerClient;
diff --git a/include/media/AudioClient.h b/include/media/AudioClient.h
deleted file mode 100644
index 9efd76d..0000000
--- a/include/media/AudioClient.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 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_AUDIO_CLIENT_H
-#define ANDROID_AUDIO_CLIENT_H
-
-#include <system/audio.h>
-#include <utils/String16.h>
-
-namespace android {
-
-class AudioClient {
- public:
-    AudioClient() :
-        clientUid(-1), clientPid(-1), packageName("") {}
-
-    uid_t clientUid;
-    pid_t clientPid;
-    String16 packageName;
-};
-
-}; // namespace android
-
-#endif  // ANDROID_AUDIO_CLIENT_H
diff --git a/include/media/AudioClient.h b/include/media/AudioClient.h
new file mode 120000
index 0000000..feac9b9
--- /dev/null
+++ b/include/media/AudioClient.h
@@ -0,0 +1 @@
+media/libaudioclient/include/media/AudioClient.h
\ No newline at end of file
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
index 1cf2c72..8d7a01e 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
@@ -219,8 +219,7 @@
             // Data conversion.
             float levelFrom;
             float levelTo;
-            bool ramping = mVolumeRamp.nextSegment(framesToWrite * getSamplesPerFrame(),
-                                                   &levelFrom, &levelTo);
+            bool ramping = mVolumeRamp.nextSegment(framesToWrite, &levelFrom, &levelTo);
             // The formats are validated when the stream is opened so we do not have to
             // check for illegal combinations here.
             // TODO factor this out into a utility function
diff --git a/media/libaaudio/src/utility/LinearRamp.h b/media/libaaudio/src/utility/LinearRamp.h
index ff09dce..2b1b8e0 100644
--- a/media/libaaudio/src/utility/LinearRamp.h
+++ b/media/libaaudio/src/utility/LinearRamp.h
@@ -87,7 +87,7 @@
 
     std::atomic<float>   mTarget;
 
-    int32_t mLengthInFrames  = 48000 / 50; // 20 msec at 48000 Hz
+    int32_t mLengthInFrames  = 48000 / 100; // 10 msec at 48000 Hz
     int32_t mRemaining       = 0;
     float   mLevelFrom       = 0.0f;
     float   mLevelTo         = 0.0f;
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 58330ae..c284f73 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -20,6 +20,7 @@
 #include <utils/Log.h>
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
+#include <media/AudioResamplerPublic.h>
 #include <media/AudioSystem.h>
 #include <media/IAudioFlinger.h>
 #include <media/IAudioPolicyService.h>
@@ -253,6 +254,31 @@
     return volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0;
 }
 
+/* static */ size_t AudioSystem::calculateMinFrameCount(
+        uint32_t afLatencyMs, uint32_t afFrameCount, uint32_t afSampleRate,
+        uint32_t sampleRate, float speed /*, uint32_t notificationsPerBufferReq*/)
+{
+    // Ensure that buffer depth covers at least audio hardware latency
+    uint32_t minBufCount = afLatencyMs / ((1000 * afFrameCount) / afSampleRate);
+    if (minBufCount < 2) {
+        minBufCount = 2;
+    }
+#if 0
+    // The notificationsPerBufferReq parameter is not yet used for non-fast tracks,
+    // but keeping the code here to make it easier to add later.
+    if (minBufCount < notificationsPerBufferReq) {
+        minBufCount = notificationsPerBufferReq;
+    }
+#endif
+    ALOGV("calculateMinFrameCount afLatency %u  afFrameCount %u  afSampleRate %u  "
+            "sampleRate %u  speed %f  minBufCount: %u" /*"  notificationsPerBufferReq %u"*/,
+            afLatencyMs, afFrameCount, afSampleRate, sampleRate, speed, minBufCount
+            /*, notificationsPerBufferReq*/);
+    return minBufCount * sourceFramesNeededWithTimestretch(
+            sampleRate, afFrameCount, afSampleRate, speed);
+}
+
+
 status_t AudioSystem::getOutputSamplingRate(uint32_t* samplingRate, audio_stream_type_t streamType)
 {
     audio_io_handle_t output;
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 356b321..36961d6 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -99,32 +99,6 @@
     return kFixPitch ? AUDIO_TIMESTRETCH_PITCH_NORMAL : pitch;
 }
 
-// Must match similar computation in createTrack_l in Threads.cpp.
-// TODO: Move to a common library
-static size_t calculateMinFrameCount(
-        uint32_t afLatencyMs, uint32_t afFrameCount, uint32_t afSampleRate,
-        uint32_t sampleRate, float speed /*, uint32_t notificationsPerBufferReq*/)
-{
-    // Ensure that buffer depth covers at least audio hardware latency
-    uint32_t minBufCount = afLatencyMs / ((1000 * afFrameCount) / afSampleRate);
-    if (minBufCount < 2) {
-        minBufCount = 2;
-    }
-#if 0
-    // The notificationsPerBufferReq parameter is not yet used for non-fast tracks,
-    // but keeping the code here to make it easier to add later.
-    if (minBufCount < notificationsPerBufferReq) {
-        minBufCount = notificationsPerBufferReq;
-    }
-#endif
-    ALOGV("calculateMinFrameCount afLatency %u  afFrameCount %u  afSampleRate %u  "
-            "sampleRate %u  speed %f  minBufCount: %u" /*"  notificationsPerBufferReq %u"*/,
-            afLatencyMs, afFrameCount, afSampleRate, sampleRate, speed, minBufCount
-            /*, notificationsPerBufferReq*/);
-    return minBufCount * sourceFramesNeededWithTimestretch(
-            sampleRate, afFrameCount, afSampleRate, speed);
-}
-
 // static
 status_t AudioTrack::getMinFrameCount(
         size_t* frameCount,
@@ -165,8 +139,8 @@
 
     // When called from createTrack, speed is 1.0f (normal speed).
     // This is rechecked again on setting playback rate (TODO: on setting sample rate, too).
-    *frameCount = calculateMinFrameCount(afLatency, afFrameCount, afSampleRate, sampleRate, 1.0f
-            /*, 0 notificationsPerBufferReq*/);
+    *frameCount = AudioSystem::calculateMinFrameCount(afLatency, afFrameCount, afSampleRate,
+                                              sampleRate, 1.0f /*, 0 notificationsPerBufferReq*/);
 
     // The formula above should always produce a non-zero value under normal circumstances:
     // AudioTrack.SAMPLE_RATE_HZ_MIN <= sampleRate <= AudioTrack.SAMPLE_RATE_HZ_MAX.
@@ -190,8 +164,7 @@
       mPreviousSchedulingGroup(SP_DEFAULT),
       mPausedPosition(0),
       mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
-      mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE),
-      mPortId(AUDIO_PORT_HANDLE_NONE)
+      mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE)
 {
     mAttributes.content_type = AUDIO_CONTENT_TYPE_UNKNOWN;
     mAttributes.usage = AUDIO_USAGE_UNKNOWN;
@@ -222,8 +195,7 @@
       mState(STATE_STOPPED),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
       mPreviousSchedulingGroup(SP_DEFAULT),
-      mPausedPosition(0),
-      mPortId(AUDIO_PORT_HANDLE_NONE)
+      mPausedPosition(0)
 {
     mStatus = set(streamType, sampleRate, format, channelMask,
             frameCount, flags, cbf, user, notificationFrames,
@@ -254,8 +226,7 @@
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
       mPreviousSchedulingGroup(SP_DEFAULT),
       mPausedPosition(0),
-      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
-      mPortId(AUDIO_PORT_HANDLE_NONE)
+      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE)
 {
     mStatus = set(streamType, sampleRate, format, channelMask,
             0 /*frameCount*/, flags, cbf, user, notificationFrames,
@@ -320,6 +291,7 @@
 
     mThreadCanCallJava = threadCanCallJava;
     mSelectedDeviceId = selectedDeviceId;
+    mSessionId = sessionId;
 
     switch (transferType) {
     case TRANSFER_DEFAULT:
@@ -500,11 +472,6 @@
                 notificationFrames, minNotificationsPerBuffer, maxNotificationsPerBuffer);
     }
     mNotificationFramesAct = 0;
-    if (sessionId == AUDIO_SESSION_ALLOCATE) {
-        mSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
-    } else {
-        mSessionId = sessionId;
-    }
     int callingpid = IPCThreadState::self()->getCallingPid();
     int mypid = getpid();
     if (uid == AUDIO_UID_INVALID || (callingpid != mypid)) {
@@ -1317,70 +1284,12 @@
         return NO_INIT;
     }
 
-    audio_io_handle_t output;
-    audio_stream_type_t streamType = mStreamType;
-    audio_attributes_t *attr = (mStreamType == AUDIO_STREAM_DEFAULT) ? &mAttributes : NULL;
+    status_t status;
     bool callbackAdded = false;
 
+    {
     // mFlags (not mOrigFlags) is modified depending on whether fast request is accepted.
     // After fast request is denied, we will request again if IAudioTrack is re-created.
-
-    status_t status;
-    audio_config_t config = AUDIO_CONFIG_INITIALIZER;
-    config.sample_rate = mSampleRate;
-    config.channel_mask = mChannelMask;
-    config.format = mFormat;
-    config.offload_info = mOffloadInfoCopy;
-    mRoutedDeviceId = mSelectedDeviceId;
-    status = AudioSystem::getOutputForAttr(attr, &output,
-                                           mSessionId, &streamType, mClientUid,
-                                           &config,
-                                           mFlags, &mRoutedDeviceId, &mPortId);
-
-    if (status != NO_ERROR || output == AUDIO_IO_HANDLE_NONE) {
-        ALOGE("Could not get audio output for session %d, stream type %d, usage %d, sample rate %u,"
-              " format %#x, channel mask %#x, flags %#x",
-              mSessionId, streamType, mAttributes.usage, mSampleRate, mFormat, mChannelMask,
-              mFlags);
-        return BAD_VALUE;
-    }
-    {
-    // Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger,
-    // we must release it ourselves if anything goes wrong.
-
-    // Not all of these values are needed under all conditions, but it is easier to get them all
-    status = AudioSystem::getLatency(output, &mAfLatency);
-    if (status != NO_ERROR) {
-        ALOGE("getLatency(%d) failed status %d", output, status);
-        goto release;
-    }
-    ALOGV("createTrack_l() output %d afLatency %u", output, mAfLatency);
-
-    status = AudioSystem::getFrameCount(output, &mAfFrameCount);
-    if (status != NO_ERROR) {
-        ALOGE("getFrameCount(output=%d) status %d", output, status);
-        goto release;
-    }
-
-    // TODO consider making this a member variable if there are other uses for it later
-    size_t afFrameCountHAL;
-    status = AudioSystem::getFrameCountHAL(output, &afFrameCountHAL);
-    if (status != NO_ERROR) {
-        ALOGE("getFrameCountHAL(output=%d) status %d", output, status);
-        goto release;
-    }
-    ALOG_ASSERT(afFrameCountHAL > 0);
-
-    status = AudioSystem::getSamplingRate(output, &mAfSampleRate);
-    if (status != NO_ERROR) {
-        ALOGE("getSamplingRate(output=%d) status %d", output, status);
-        goto release;
-    }
-    if (mSampleRate == 0) {
-        mSampleRate = mAfSampleRate;
-        mOriginalSampleRate = mAfSampleRate;
-    }
-
     // Client can only express a preference for FAST.  Server will perform additional tests.
     if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
         // either of these use cases:
@@ -1394,130 +1303,78 @@
             // use case 4: synchronous write
             ((mTransfer == TRANSFER_SYNC) && mThreadCanCallJava);
 
-        bool useCaseAllowed = sharedBuffer || transferAllowed;
-        if (!useCaseAllowed) {
+        bool fastAllowed = sharedBuffer || transferAllowed;
+        if (!fastAllowed) {
             ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client, not shared buffer and transfer = %s",
                   convertTransferToText(mTransfer));
-        }
-
-        // sample rates must also match
-        bool sampleRateAllowed = mSampleRate == mAfSampleRate;
-        if (!sampleRateAllowed) {
-            ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client, sample rate %u Hz but HAL needs %u Hz",
-                  mSampleRate, mAfSampleRate);
-        }
-
-        bool fastAllowed = useCaseAllowed && sampleRateAllowed;
-        if (!fastAllowed) {
             mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_FAST);
         }
     }
 
-    mNotificationFramesAct = mNotificationFramesReq;
-
-    size_t frameCount = mReqFrameCount;
-    if (!audio_has_proportional_frames(mFormat)) {
-
-        if (mSharedBuffer != 0) {
-            // Same comment as below about ignoring frameCount parameter for set()
-            frameCount = mSharedBuffer->size();
-        } else if (frameCount == 0) {
-            frameCount = mAfFrameCount;
-        }
-        if (mNotificationFramesAct != frameCount) {
-            mNotificationFramesAct = frameCount;
-        }
-    } else if (mSharedBuffer != 0) {
-        // FIXME: Ensure client side memory buffers need
-        // not have additional alignment beyond sample
-        // (e.g. 16 bit stereo accessed as 32 bit frame).
-        size_t alignment = audio_bytes_per_sample(mFormat);
-        if (alignment & 1) {
-            // for AUDIO_FORMAT_PCM_24_BIT_PACKED (not exposed through Java).
-            alignment = 1;
-        }
-        if (mChannelCount > 1) {
-            // More than 2 channels does not require stronger alignment than stereo
-            alignment <<= 1;
-        }
-        if (((uintptr_t)mSharedBuffer->pointer() & (alignment - 1)) != 0) {
-            ALOGE("Invalid buffer alignment: address %p, channel count %u",
-                    mSharedBuffer->pointer(), mChannelCount);
-            status = BAD_VALUE;
-            goto release;
-        }
-
-        // When initializing a shared buffer AudioTrack via constructors,
-        // there's no frameCount parameter.
-        // But when initializing a shared buffer AudioTrack via set(),
-        // there _is_ a frameCount parameter.  We silently ignore it.
-        frameCount = mSharedBuffer->size() / mFrameSize;
+    IAudioFlinger::CreateTrackInput input;
+    if (mStreamType != AUDIO_STREAM_DEFAULT) {
+        stream_type_to_audio_attributes(mStreamType, &input.attr);
     } else {
-        size_t minFrameCount = 0;
-        // For fast tracks the frame count calculations and checks are mostly done by server,
-        // but we try to respect the application's request for notifications per buffer.
-        if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
-            if (mNotificationsPerBufferReq > 0) {
-                // Avoid possible arithmetic overflow during multiplication.
-                // mNotificationsPerBuffer is clamped to a small integer earlier, so it is unlikely.
-                if (mNotificationsPerBufferReq > SIZE_MAX / afFrameCountHAL) {
-                    ALOGE("Requested notificationPerBuffer=%u ignored for HAL frameCount=%zu",
-                            mNotificationsPerBufferReq, afFrameCountHAL);
-                } else {
-                    minFrameCount = afFrameCountHAL * mNotificationsPerBufferReq;
-                }
-            }
-        } else {
-            // for normal tracks precompute the frame count based on speed.
-            const float speed = !isPurePcmData_l() || isOffloadedOrDirect_l() ? 1.0f :
-                            max(mMaxRequiredSpeed, mPlaybackRate.mSpeed);
-            minFrameCount = calculateMinFrameCount(
-                    mAfLatency, mAfFrameCount, mAfSampleRate, mSampleRate,
-                    speed /*, 0 mNotificationsPerBufferReq*/);
-        }
-        if (frameCount < minFrameCount) {
-            frameCount = minFrameCount;
-        }
+        input.attr = mAttributes;
     }
-
-    audio_output_flags_t flags = mFlags;
-
-    pid_t tid = -1;
+    input.config = AUDIO_CONFIG_INITIALIZER;
+    input.config.sample_rate = mSampleRate;
+    input.config.channel_mask = mChannelMask;
+    input.config.format = mFormat;
+    input.config.offload_info = mOffloadInfoCopy;
+    input.clientInfo.clientUid = mClientUid;
+    input.clientInfo.clientPid = mClientPid;
+    input.clientInfo.clientTid = -1;
     if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
         // It is currently meaningless to request SCHED_FIFO for a Java thread.  Even if the
         // application-level code follows all non-blocking design rules, the language runtime
         // doesn't also follow those rules, so the thread will not benefit overall.
         if (mAudioTrackThread != 0 && !mThreadCanCallJava) {
-            tid = mAudioTrackThread->getTid();
+            input.clientInfo.clientTid = mAudioTrackThread->getTid();
         }
     }
+    input.sharedBuffer = mSharedBuffer;
+    input.notificationsPerBuffer = mNotificationsPerBufferReq;
+    input.speed = 1.0;
+    if (audio_has_proportional_frames(mFormat) && mSharedBuffer == 0 &&
+            (mFlags & AUDIO_OUTPUT_FLAG_FAST) == 0) {
+        input.speed  = !isPurePcmData_l() || isOffloadedOrDirect_l() ? 1.0f :
+                        max(mMaxRequiredSpeed, mPlaybackRate.mSpeed);
+    }
+    input.flags = mFlags;
+    input.frameCount = mReqFrameCount;
+    input.notificationFrameCount = mNotificationFramesReq;
+    input.selectedDeviceId = mSelectedDeviceId;
+    input.sessionId = mSessionId;
 
-    size_t temp = frameCount;   // temp may be replaced by a revised value of frameCount,
-                                // but we will still need the original value also
-    audio_session_t originalSessionId = mSessionId;
-    sp<IAudioTrack> track = audioFlinger->createTrack(streamType,
-                                                      mSampleRate,
-                                                      mFormat,
-                                                      mChannelMask,
-                                                      &temp,
-                                                      &flags,
-                                                      mSharedBuffer,
+    IAudioFlinger::CreateTrackOutput output;
+
+    sp<IAudioTrack> track = audioFlinger->createTrack(input,
                                                       output,
-                                                      mClientPid,
-                                                      tid,
-                                                      &mSessionId,
-                                                      mClientUid,
-                                                      &status,
-                                                      mPortId);
-    ALOGE_IF(originalSessionId != AUDIO_SESSION_ALLOCATE && mSessionId != originalSessionId,
-            "session ID changed from %d to %d", originalSessionId, mSessionId);
+                                                      &status);
 
-    if (status != NO_ERROR) {
-        ALOGE("AudioFlinger could not create track, status: %d", status);
-        goto release;
+    if (status != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
+        ALOGE("AudioFlinger could not create track, status: %d output %d", status, output.outputId);
+        goto error;
     }
     ALOG_ASSERT(track != 0);
 
+    mFrameCount = output.frameCount;
+    mNotificationFramesAct = (uint32_t)output.notificationFrameCount;
+    mRoutedDeviceId = output.selectedDeviceId;
+    mSessionId = output.sessionId;
+
+    mSampleRate = output.sampleRate;
+    if (mOriginalSampleRate == 0) {
+        mOriginalSampleRate = mSampleRate;
+    }
+
+    mAfFrameCount = output.afFrameCount;
+    mAfSampleRate = output.afSampleRate;
+    mAfLatency = output.afLatencyMs;
+
+    mLatency = mAfLatency + (1000LL * mFrameCount) / mSampleRate;
+
     // AudioFlinger now owns the reference to the I/O handle,
     // so we are no longer responsible for releasing it.
 
@@ -1526,13 +1383,13 @@
     if (iMem == 0) {
         ALOGE("Could not get control block");
         status = NO_INIT;
-        goto release;
+        goto error;
     }
     void *iMemPointer = iMem->pointer();
     if (iMemPointer == NULL) {
         ALOGE("Could not get control block pointer");
         status = NO_INIT;
-        goto release;
+        goto error;
     }
     // invariant that mAudioTrack != 0 is true only after set() returns successfully
     if (mAudioTrack != 0) {
@@ -1545,75 +1402,33 @@
 
     audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
     mCblk = cblk;
-    // note that temp is the (possibly revised) value of frameCount
-    if (temp < frameCount || (frameCount == 0 && temp == 0)) {
-        // In current design, AudioTrack client checks and ensures frame count validity before
-        // passing it to AudioFlinger so AudioFlinger should not return a different value except
-        // for fast track as it uses a special method of assigning frame count.
-        ALOGW("Requested frameCount %zu but received frameCount %zu", frameCount, temp);
-    }
-    frameCount = temp;
 
     mAwaitBoost = false;
     if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
-        if (flags & AUDIO_OUTPUT_FLAG_FAST) {
-            ALOGI("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %zu -> %zu", frameCount, temp);
+        if (output.flags & AUDIO_OUTPUT_FLAG_FAST) {
+            ALOGI("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %zu -> %zu",
+                  mReqFrameCount, mFrameCount);
             if (!mThreadCanCallJava) {
                 mAwaitBoost = true;
             }
         } else {
-            ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %zu -> %zu", frameCount,
-                    temp);
+            ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %zu -> %zu", mReqFrameCount,
+                  mFrameCount);
         }
     }
-    mFlags = flags;
-
-    // Make sure that application is notified with sufficient margin before underrun.
-    // The client can divide the AudioTrack buffer into sub-buffers,
-    // and expresses its desire to server as the notification frame count.
-    if (mSharedBuffer == 0 && audio_is_linear_pcm(mFormat)) {
-        size_t maxNotificationFrames;
-        if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
-            // notify every HAL buffer, regardless of the size of the track buffer
-            maxNotificationFrames = afFrameCountHAL;
-        } else {
-            // For normal tracks, use at least double-buffering if no sample rate conversion,
-            // or at least triple-buffering if there is sample rate conversion
-            const int nBuffering = mOriginalSampleRate == mAfSampleRate ? 2 : 3;
-            maxNotificationFrames = frameCount / nBuffering;
-            // If client requested a fast track but this was denied, then use the smaller maximum.
-            // FMS_20 is the minimum task wakeup period in ms for which CFS operates reliably.
-#define FMS_20 20   // FIXME share a common declaration with the same symbol in Threads.cpp
-            if (mOrigFlags & AUDIO_OUTPUT_FLAG_FAST) {
-                size_t maxNotificationFramesFastDenied = FMS_20 * mSampleRate / 1000;
-                if (maxNotificationFrames > maxNotificationFramesFastDenied) {
-                    maxNotificationFrames = maxNotificationFramesFastDenied;
-                }
-            }
-        }
-        if (mNotificationFramesAct == 0 || mNotificationFramesAct > maxNotificationFrames) {
-            if (mNotificationFramesAct == 0) {
-                ALOGD("Client defaulted notificationFrames to %zu for frameCount %zu",
-                    maxNotificationFrames, frameCount);
-            } else {
-                ALOGW("Client adjusted notificationFrames from %u to %zu for frameCount %zu",
-                    mNotificationFramesAct, maxNotificationFrames, frameCount);
-            }
-            mNotificationFramesAct = (uint32_t) maxNotificationFrames;
-        }
-    }
+    mFlags = output.flags;
 
     //mOutput != output includes the case where mOutput == AUDIO_IO_HANDLE_NONE for first creation
-    if (mDeviceCallback != 0 && mOutput != output) {
+    if (mDeviceCallback != 0 && mOutput != output.outputId) {
         if (mOutput != AUDIO_IO_HANDLE_NONE) {
             AudioSystem::removeAudioDeviceCallback(this, mOutput);
         }
-        AudioSystem::addAudioDeviceCallback(this, output);
+        AudioSystem::addAudioDeviceCallback(this, output.outputId);
         callbackAdded = true;
     }
 
     // We retain a copy of the I/O handle, but don't own the reference
-    mOutput = output;
+    mOutput = output.outputId;
     mRefreshRemaining = true;
 
     // Starting address of buffers in shared memory.  If there is a shared buffer, buffers
@@ -1628,18 +1443,16 @@
         if (buffers == NULL) {
             ALOGE("Could not get buffer pointer");
             status = NO_INIT;
-            goto release;
+            goto error;
         }
     }
 
     mAudioTrack->attachAuxEffect(mAuxEffectId);
-    mFrameCount = frameCount;
-    updateLatency_l();  // this refetches mAfLatency and sets mLatency
 
     // If IAudioTrack is re-created, don't let the requested frameCount
     // decrease.  This can confuse clients that cache frameCount().
-    if (frameCount > mReqFrameCount) {
-        mReqFrameCount = frameCount;
+    if (mFrameCount > mReqFrameCount) {
+        mReqFrameCount = mFrameCount;
     }
 
     // reset server position to 0 as we have new cblk.
@@ -1648,9 +1461,9 @@
     // update proxy
     if (mSharedBuffer == 0) {
         mStaticProxy.clear();
-        mProxy = new AudioTrackClientProxy(cblk, buffers, frameCount, mFrameSize);
+        mProxy = new AudioTrackClientProxy(cblk, buffers, mFrameCount, mFrameSize);
     } else {
-        mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, frameCount, mFrameSize);
+        mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, mFrameCount, mFrameSize);
         mProxy = mStaticProxy;
     }
 
@@ -1676,8 +1489,7 @@
     return NO_ERROR;
     }
 
-release:
-    AudioSystem::releaseOutput(output, streamType, mSessionId);
+error:
     if (callbackAdded) {
         // note: mOutput is always valid is callbackAdded is true
         AudioSystem::removeAudioDeviceCallback(this, mOutput);
@@ -1685,6 +1497,8 @@
     if (status == NO_ERROR) {
         status = NO_INIT;
     }
+
+    // sp<IAudioTrack> track destructor will cause releaseOutput() to be called by AudioFlinger
     return status;
 }
 
@@ -2420,8 +2234,8 @@
         return true; // static tracks do not have issues with buffer sizing.
     }
     const size_t minFrameCount =
-            calculateMinFrameCount(mAfLatency, mAfFrameCount, mAfSampleRate, sampleRate, speed
-                /*, 0 mNotificationsPerBufferReq*/);
+            AudioSystem::calculateMinFrameCount(mAfLatency, mAfFrameCount, mAfSampleRate,
+                                            sampleRate, speed /*, 0 mNotificationsPerBufferReq*/);
     const bool allowed = mFrameCount >= minFrameCount;
     ALOGD_IF(!allowed,
             "isSampleRateSpeedAllowed_l denied "
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index fc8c11a..5cf2bdb 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -95,83 +95,38 @@
     {
     }
 
-    virtual sp<IAudioTrack> createTrack(
-                                audio_stream_type_t streamType,
-                                uint32_t sampleRate,
-                                audio_format_t format,
-                                audio_channel_mask_t channelMask,
-                                size_t *pFrameCount,
-                                audio_output_flags_t *flags,
-                                const sp<IMemory>& sharedBuffer,
-                                audio_io_handle_t output,
-                                pid_t pid,
-                                pid_t tid,
-                                audio_session_t *sessionId,
-                                int clientUid,
-                                status_t *status,
-                                audio_port_handle_t portId)
+    virtual sp<IAudioTrack> createTrack(const CreateTrackInput& input,
+                                        CreateTrackOutput& output,
+                                        status_t *status)
     {
         Parcel data, reply;
         sp<IAudioTrack> track;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) streamType);
-        data.writeInt32(sampleRate);
-        data.writeInt32(format);
-        data.writeInt32(channelMask);
-        size_t frameCount = pFrameCount != NULL ? *pFrameCount : 0;
-        data.writeInt64(frameCount);
-        audio_output_flags_t lFlags = flags != NULL ? *flags : AUDIO_OUTPUT_FLAG_NONE;
-        data.writeInt32(lFlags);
-        // haveSharedBuffer
-        if (sharedBuffer != 0) {
-            data.writeInt32(true);
-            data.writeStrongBinder(IInterface::asBinder(sharedBuffer));
-        } else {
-            data.writeInt32(false);
+
+        if (status == nullptr) {
+            return track;
         }
-        data.writeInt32((int32_t) output);
-        data.writeInt32((int32_t) pid);
-        data.writeInt32((int32_t) tid);
-        audio_session_t lSessionId = AUDIO_SESSION_ALLOCATE;
-        if (sessionId != NULL) {
-            lSessionId = *sessionId;
-        }
-        data.writeInt32(lSessionId);
-        data.writeInt32(clientUid);
-        data.writeInt32(portId);
+
+        input.writeToParcel(&data);
+
         status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply);
         if (lStatus != NO_ERROR) {
-            ALOGE("createTrack error: %s", strerror(-lStatus));
-        } else {
-            frameCount = reply.readInt64();
-            if (pFrameCount != NULL) {
-                *pFrameCount = frameCount;
-            }
-            lFlags = (audio_output_flags_t)reply.readInt32();
-            if (flags != NULL) {
-                *flags = lFlags;
-            }
-            lSessionId = (audio_session_t) reply.readInt32();
-            if (sessionId != NULL) {
-                *sessionId = lSessionId;
-            }
-            lStatus = reply.readInt32();
-            track = interface_cast<IAudioTrack>(reply.readStrongBinder());
-            if (lStatus == NO_ERROR) {
-                if (track == 0) {
-                    ALOGE("createTrack should have returned an IAudioTrack");
-                    lStatus = UNKNOWN_ERROR;
-                }
-            } else {
-                if (track != 0) {
-                    ALOGE("createTrack returned an IAudioTrack but with status %d", lStatus);
-                    track.clear();
-                }
-            }
+            ALOGE("createTrack transaction error %d", lStatus);
+            *status = DEAD_OBJECT;
+            return track;
         }
-        if (status != NULL) {
-            *status = lStatus;
+        *status = reply.readInt32();
+        if (*status != NO_ERROR) {
+            ALOGE("createTrack returned error %d", *status);
+            return track;
         }
+        track = interface_cast<IAudioTrack>(reply.readStrongBinder());
+        if (track == 0) {
+            ALOGE("createTrack returned an NULL IAudioTrack with status OK");
+            *status = DEAD_OBJECT;
+            return track;
+        }
+        output.readFromParcel(&reply);
         return track;
     }
 
@@ -970,41 +925,27 @@
     switch (code) {
         case CREATE_TRACK: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int streamType = data.readInt32();
-            uint32_t sampleRate = data.readInt32();
-            audio_format_t format = (audio_format_t) data.readInt32();
-            audio_channel_mask_t channelMask = data.readInt32();
-            size_t frameCount = data.readInt64();
-            audio_output_flags_t flags = (audio_output_flags_t) data.readInt32();
-            bool haveSharedBuffer = data.readInt32() != 0;
-            sp<IMemory> buffer;
-            if (haveSharedBuffer) {
-                buffer = interface_cast<IMemory>(data.readStrongBinder());
+
+            CreateTrackInput input;
+            if (input.readFromParcel((Parcel*)&data) != NO_ERROR) {
+                reply->writeInt32(DEAD_OBJECT);
+                return NO_ERROR;
             }
-            audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
-            pid_t pid = (pid_t) data.readInt32();
-            pid_t tid = (pid_t) data.readInt32();
-            audio_session_t sessionId = (audio_session_t) data.readInt32();
-            int clientUid = data.readInt32();
-            audio_port_handle_t portId = (audio_port_handle_t) data.readInt32();
-            status_t status = NO_ERROR;
-            sp<IAudioTrack> track;
-            if ((haveSharedBuffer && (buffer == 0)) ||
-                    ((buffer != 0) && (buffer->pointer() == NULL))) {
-                ALOGW("CREATE_TRACK: cannot retrieve shared memory");
-                status = DEAD_OBJECT;
-            } else {
-                track = createTrack(
-                        (audio_stream_type_t) streamType, sampleRate, format,
-                        channelMask, &frameCount, &flags, buffer, output, pid, tid,
-                        &sessionId, clientUid, &status, portId);
-                LOG_ALWAYS_FATAL_IF((track != 0) != (status == NO_ERROR));
-            }
-            reply->writeInt64(frameCount);
-            reply->writeInt32(flags);
-            reply->writeInt32(sessionId);
+
+            status_t status;
+            CreateTrackOutput output;
+
+            sp<IAudioTrack> track= createTrack(input,
+                                               output,
+                                               &status);
+
+            LOG_ALWAYS_FATAL_IF((track != 0) != (status == NO_ERROR));
             reply->writeInt32(status);
+            if (status != NO_ERROR) {
+                return NO_ERROR;
+            }
             reply->writeStrongBinder(IInterface::asBinder(track));
+            output.writeToParcel(reply);
             return NO_ERROR;
         } break;
         case OPEN_RECORD: {
diff --git a/media/libaudioclient/include/media/AudioClient.h b/media/libaudioclient/include/media/AudioClient.h
index 9efd76d..108e326 100644
--- a/media/libaudioclient/include/media/AudioClient.h
+++ b/media/libaudioclient/include/media/AudioClient.h
@@ -18,6 +18,7 @@
 #ifndef ANDROID_AUDIO_CLIENT_H
 #define ANDROID_AUDIO_CLIENT_H
 
+#include <binder/Parcel.h>
 #include <system/audio.h>
 #include <utils/String16.h>
 
@@ -26,11 +27,28 @@
 class AudioClient {
  public:
     AudioClient() :
-        clientUid(-1), clientPid(-1), packageName("") {}
+        clientUid(-1), clientPid(-1), clientTid(-1), packageName("") {}
 
     uid_t clientUid;
     pid_t clientPid;
+    pid_t clientTid;
     String16 packageName;
+
+    status_t readFromParcel(Parcel *parcel) {
+        clientUid = parcel->readInt32();
+        clientPid = parcel->readInt32();
+        clientTid = parcel->readInt32();
+        packageName = parcel->readString16();
+        return NO_ERROR;
+    }
+
+    status_t writeToParcel(Parcel *parcel) const {
+        parcel->writeInt32(clientUid);
+        parcel->writeInt32(clientPid);
+        parcel->writeInt32(clientTid);
+        parcel->writeString16(packageName);
+        return NO_ERROR;
+    }
 };
 
 }; // namespace android
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 327eba8..66601da 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -106,6 +106,9 @@
 
     static float linearToLog(int volume);
     static int logToLinear(float volume);
+    static size_t calculateMinFrameCount(
+            uint32_t afLatencyMs, uint32_t afFrameCount, uint32_t afSampleRate,
+            uint32_t sampleRate, float speed /*, uint32_t notificationsPerBufferReq*/);
 
     // Returned samplingRate and frameCount output values are guaranteed
     // to be non-zero if status == NO_ERROR
@@ -209,8 +212,6 @@
     static status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
     static audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
 
-    // Client must successfully hand off the handle reference to AudioFlinger via createTrack(),
-    // or release it with releaseOutput().
     static status_t getOutputForAttr(const audio_attributes_t *attr,
                                      audio_io_handle_t *output,
                                      audio_session_t session,
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 8973133..9fbd04b 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -1182,7 +1182,6 @@
     pid_t                   mClientPid;
 
     wp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
-    audio_port_handle_t     mPortId;  // unique ID allocated by audio policy
 };
 
 }; // namespace android
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 133d6c9..9061c26 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -24,6 +24,8 @@
 #include <utils/RefBase.h>
 #include <utils/Errors.h>
 #include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <media/AudioClient.h>
 #include <media/IAudioTrack.h>
 #include <media/IAudioFlingerClient.h>
 #include <system/audio.h>
@@ -44,6 +46,135 @@
 public:
     DECLARE_META_INTERFACE(AudioFlinger);
 
+    /* CreateTrackInput contains all input arguments sent by AudioTrack to AudioFlinger
+     * when calling createTrack() including arguments that will be updated by AudioFlinger
+     * and returned in CreateTrackOutput object
+     */
+    class CreateTrackInput {
+    public:
+        status_t readFromParcel(Parcel *parcel) {
+            /* input arguments*/
+            memset(&attr, 0, sizeof(audio_attributes_t));
+            if (parcel->read(&attr, sizeof(audio_attributes_t)) != NO_ERROR) {
+                return DEAD_OBJECT;
+            }
+            attr.tags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE -1] = '\0';
+            memset(&config, 0, sizeof(audio_config_t));
+            if (parcel->read(&config, sizeof(audio_config_t)) != NO_ERROR) {
+                return DEAD_OBJECT;
+            }
+            (void)clientInfo.readFromParcel(parcel);
+            if (parcel->readInt32() != 0) {
+                sharedBuffer = interface_cast<IMemory>(parcel->readStrongBinder());
+                if (sharedBuffer == 0 || sharedBuffer->pointer() == NULL) {
+                    return BAD_VALUE;
+                }
+            }
+            notificationsPerBuffer = parcel->readInt32();
+            speed = parcel->readFloat();
+
+            /* input/output arguments*/
+            (void)parcel->read(&flags, sizeof(audio_output_flags_t));
+            frameCount = parcel->readInt64();
+            notificationFrameCount = parcel->readInt64();
+            (void)parcel->read(&selectedDeviceId, sizeof(audio_port_handle_t));
+            (void)parcel->read(&sessionId, sizeof(audio_session_t));
+            return NO_ERROR;
+        }
+
+        status_t writeToParcel(Parcel *parcel) const {
+            /* input arguments*/
+            (void)parcel->write(&attr, sizeof(audio_attributes_t));
+            (void)parcel->write(&config, sizeof(audio_config_t));
+            (void)clientInfo.writeToParcel(parcel);
+            if (sharedBuffer != 0) {
+                (void)parcel->writeInt32(1);
+                (void)parcel->writeStrongBinder(IInterface::asBinder(sharedBuffer));
+            } else {
+                (void)parcel->writeInt32(0);
+            }
+            (void)parcel->writeInt32(notificationsPerBuffer);
+            (void)parcel->writeFloat(speed);
+
+            /* input/output arguments*/
+            (void)parcel->write(&flags, sizeof(audio_output_flags_t));
+            (void)parcel->writeInt64(frameCount);
+            (void)parcel->writeInt64(notificationFrameCount);
+            (void)parcel->write(&selectedDeviceId, sizeof(audio_port_handle_t));
+            (void)parcel->write(&sessionId, sizeof(audio_session_t));
+            return NO_ERROR;
+        }
+
+        /* input */
+        audio_attributes_t attr;
+        audio_config_t config;
+        AudioClient clientInfo;
+        sp<IMemory> sharedBuffer;
+        uint32_t notificationsPerBuffer;
+        float speed;
+
+        /* input/output */
+        audio_output_flags_t flags;
+        size_t frameCount;
+        size_t notificationFrameCount;
+        audio_port_handle_t selectedDeviceId;
+        audio_session_t sessionId;
+    };
+
+    /* CreateTrackOutput contains all output arguments returned by AudioFlinger to AudioTrack
+     * when calling createTrack() including arguments that were passed as I/O for update by
+     * CreateTrackInput.
+     */
+    class CreateTrackOutput {
+    public:
+        status_t readFromParcel(Parcel *parcel) {
+            /* input/output arguments*/
+            (void)parcel->read(&flags, sizeof(audio_output_flags_t));
+            frameCount = parcel->readInt64();
+            notificationFrameCount = parcel->readInt64();
+            (void)parcel->read(&selectedDeviceId, sizeof(audio_port_handle_t));
+            (void)parcel->read(&sessionId, sizeof(audio_session_t));
+
+            /* output arguments*/
+            sampleRate = parcel->readUint32();
+            afFrameCount = parcel->readInt64();
+            afSampleRate = parcel->readInt64();
+            afLatencyMs = parcel->readInt32();
+            (void)parcel->read(&outputId, sizeof(audio_io_handle_t));
+            return NO_ERROR;
+        }
+
+        status_t writeToParcel(Parcel *parcel) const {
+            /* input/output arguments*/
+            (void)parcel->write(&flags, sizeof(audio_output_flags_t));
+            (void)parcel->writeInt64(frameCount);
+            (void)parcel->writeInt64(notificationFrameCount);
+            (void)parcel->write(&selectedDeviceId, sizeof(audio_port_handle_t));
+            (void)parcel->write(&sessionId, sizeof(audio_session_t));
+
+            /* output arguments*/
+            (void)parcel->writeUint32(sampleRate);
+            (void)parcel->writeInt64(afFrameCount);
+            (void)parcel->writeInt64(afSampleRate);
+            (void)parcel->writeInt32(afLatencyMs);
+            (void)parcel->write(&outputId, sizeof(audio_io_handle_t));
+            return NO_ERROR;
+        }
+
+        /* input/output */
+        audio_output_flags_t flags;
+        size_t frameCount;
+        size_t notificationFrameCount;
+        audio_port_handle_t selectedDeviceId;
+        audio_session_t sessionId;
+
+        /* output */
+        uint32_t sampleRate;
+        size_t   afFrameCount;
+        uint32_t afSampleRate;
+        uint32_t afLatencyMs;
+        audio_io_handle_t outputId;
+    };
 
     // invariant on exit for all APIs that return an sp<>:
     //   (return value != 0) == (*status == NO_ERROR)
@@ -51,24 +182,9 @@
     /* create an audio track and registers it with AudioFlinger.
      * return null if the track cannot be created.
      */
-    virtual sp<IAudioTrack> createTrack(
-                                audio_stream_type_t streamType,
-                                uint32_t sampleRate,
-                                audio_format_t format,
-                                audio_channel_mask_t channelMask,
-                                size_t *pFrameCount,
-                                audio_output_flags_t *flags,
-                                const sp<IMemory>& sharedBuffer,
-                                // On successful return, AudioFlinger takes over the handle
-                                // reference and will release it when the track is destroyed.
-                                // However on failure, the client is responsible for release.
-                                audio_io_handle_t output,
-                                pid_t pid,
-                                pid_t tid,  // -1 means unused, otherwise must be valid non-0
-                                audio_session_t *sessionId,
-                                int clientUid,
-                                status_t *status,
-                                audio_port_handle_t portId) = 0;
+    virtual sp<IAudioTrack> createTrack(const CreateTrackInput& input,
+                                        CreateTrackOutput& output,
+                                        status_t *status) = 0;
 
     virtual sp<media::IAudioRecord> openRecord(
                                 // On successful return, AudioFlinger takes over the handle
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 1381d27..1f4bd0a 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -45,9 +45,7 @@
         "aidl/android/IOMXBufferSource.aidl",
 
         "IMediaCodecList.cpp",
-        "IMediaCodecService.cpp",
         "IOMX.cpp",
-        "IOMXStore.cpp",
         "MediaCodecBuffer.cpp",
         "MediaCodecInfo.cpp",
         "OMXBuffer.cpp",
diff --git a/media/libmedia/IMediaCodecService.cpp b/media/libmedia/IMediaCodecService.cpp
deleted file mode 100644
index adfa93d..0000000
--- a/media/libmedia/IMediaCodecService.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
-**
-** Copyright 2015, 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_TAG "IMediaCodecService"
-//#define LOG_NDEBUG 0
-
-#include <utils/Log.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <binder/Parcel.h>
-#include <media/IMediaCodecService.h>
-
-namespace android {
-
-enum {
-    GET_OMX = IBinder::FIRST_CALL_TRANSACTION,
-    GET_OMX_STORE
-};
-
-class BpMediaCodecService : public BpInterface<IMediaCodecService>
-{
-public:
-    explicit BpMediaCodecService(const sp<IBinder>& impl)
-        : BpInterface<IMediaCodecService>(impl)
-    {
-    }
-
-    virtual sp<IOMX> getOMX() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaCodecService::getInterfaceDescriptor());
-        remote()->transact(GET_OMX, data, &reply);
-        return interface_cast<IOMX>(reply.readStrongBinder());
-    }
-
-    virtual sp<IOMXStore> getOMXStore() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaCodecService::getInterfaceDescriptor());
-        remote()->transact(GET_OMX_STORE, data, &reply);
-        return interface_cast<IOMXStore>(reply.readStrongBinder());
-    }
-
-};
-
-IMPLEMENT_META_INTERFACE(MediaCodecService, "android.media.IMediaCodecService");
-
-// ----------------------------------------------------------------------
-
-status_t BnMediaCodecService::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch (code) {
-
-        case GET_OMX: {
-            CHECK_INTERFACE(IMediaCodecService, data, reply);
-            sp<IOMX> omx = getOMX();
-            reply->writeStrongBinder(IInterface::asBinder(omx));
-            return NO_ERROR;
-        }
-        case GET_OMX_STORE: {
-            CHECK_INTERFACE(IMediaCodecService, data, reply);
-            sp<IOMXStore> omxStore = getOMXStore();
-            reply->writeStrongBinder(IInterface::asBinder(omxStore));
-            return NO_ERROR;
-        }
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-} // namespace android
diff --git a/media/libmedia/IOMXStore.cpp b/media/libmedia/IOMXStore.cpp
deleted file mode 100644
index 4948f1a..0000000
--- a/media/libmedia/IOMXStore.cpp
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright (c) 2009 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 "IOMXStore"
-
-#include <utils/Log.h>
-
-#include <media/IOMX.h>
-#include <media/IOMXStore.h>
-#include <android/hardware/media/omx/1.0/IOmxStore.h>
-
-#include <binder/IInterface.h>
-#include <binder/IBinder.h>
-#include <binder/Parcel.h>
-
-#include <vector>
-#include <string>
-
-namespace android {
-
-namespace {
-
-enum {
-    CONNECT = IBinder::FIRST_CALL_TRANSACTION,
-    LIST_SERVICE_ATTRIBUTES,
-    GET_NODE_PREFIX,
-    LIST_ROLES,
-    GET_OMX,
-};
-
-// Forward declarations of std::vector<T> <-> Parcel conversion funcitons that
-// depend on writeToParcel() and readToParcel() for T <-> Parcel.
-
-template <typename T>
-status_t writeToParcel(const std::vector<T>& v, Parcel* p);
-
-template <typename T>
-status_t readFromParcel(std::vector<T>* v, const Parcel& p);
-
-// std::string <-> Parcel
-
-status_t writeToParcel(const std::string& s, Parcel* p) {
-    if (s.size() > INT32_MAX) {
-        return BAD_VALUE;
-    }
-    return p->writeByteArray(
-            s.size(), reinterpret_cast<const uint8_t*>(s.c_str()));
-}
-
-status_t readFromParcel(std::string* s, const Parcel& p) {
-    int32_t len;
-    status_t status = p.readInt32(&len);
-    if (status != NO_ERROR) {
-        return status;
-    } else if ((len < 0) || (static_cast<uint64_t>(len) > SIZE_MAX)) {
-        return BAD_VALUE;
-    }
-    s->resize(len);
-    if (len == 0) {
-        return NO_ERROR;
-    }
-    return p.read(static_cast<void*>(&s->front()), static_cast<size_t>(len));
-}
-
-// IOMXStore::Attribute <-> Parcel
-
-status_t writeToParcel(const IOMXStore::Attribute& a, Parcel* p) {
-    status_t status = writeToParcel(a.key, p);
-    if (status != NO_ERROR) {
-        return status;
-    }
-    return writeToParcel(a.value, p);
-}
-
-status_t readFromParcel(IOMXStore::Attribute* a, const Parcel& p) {
-    status_t status = readFromParcel(&(a->key), p);
-    if (status != NO_ERROR) {
-        return status;
-    }
-    return readFromParcel(&(a->value), p);
-}
-
-// IOMXStore::NodeInfo <-> Parcel
-
-status_t writeToParcel(const IOMXStore::NodeInfo& n, Parcel* p) {
-    status_t status = writeToParcel(n.name, p);
-    if (status != NO_ERROR) {
-        return status;
-    }
-    status = writeToParcel(n.owner, p);
-    if (status != NO_ERROR) {
-        return status;
-    }
-    return writeToParcel(n.attributes, p);
-}
-
-status_t readFromParcel(IOMXStore::NodeInfo* n, const Parcel& p) {
-    status_t status = readFromParcel(&(n->name), p);
-    if (status != NO_ERROR) {
-        return status;
-    }
-    status = readFromParcel(&(n->owner), p);
-    if (status != NO_ERROR) {
-        return status;
-    }
-    return readFromParcel(&(n->attributes), p);
-}
-
-// IOMXStore::RoleInfo <-> Parcel
-
-status_t writeToParcel(const IOMXStore::RoleInfo& r, Parcel* p) {
-    status_t status = writeToParcel(r.role, p);
-    if (status != NO_ERROR) {
-        return status;
-    }
-    status = writeToParcel(r.type, p);
-    if (status != NO_ERROR) {
-        return status;
-    }
-    status = p->writeBool(r.isEncoder);
-    if (status != NO_ERROR) {
-        return status;
-    }
-    status = p->writeBool(r.preferPlatformNodes);
-    if (status != NO_ERROR) {
-        return status;
-    }
-    return writeToParcel(r.nodes, p);
-}
-
-status_t readFromParcel(IOMXStore::RoleInfo* r, const Parcel& p) {
-    status_t status = readFromParcel(&(r->role), p);
-    if (status != NO_ERROR) {
-        return status;
-    }
-    status = readFromParcel(&(r->type), p);
-    if (status != NO_ERROR) {
-        return status;
-    }
-    status = p.readBool(&(r->isEncoder));
-    if (status != NO_ERROR) {
-        return status;
-    }
-    status = p.readBool(&(r->preferPlatformNodes));
-    if (status != NO_ERROR) {
-        return status;
-    }
-    return readFromParcel(&(r->nodes), p);
-}
-
-// std::vector<NodeInfo> <-> Parcel
-// std::vector<RoleInfo> <-> Parcel
-
-template <typename T>
-status_t writeToParcel(const std::vector<T>& v, Parcel* p) {
-    status_t status = p->writeVectorSize(v);
-    if (status != NO_ERROR) {
-        return status;
-    }
-    for (const T& x : v) {
-        status = writeToParcel(x, p);
-        if (status != NO_ERROR) {
-            return status;
-        }
-    }
-    return NO_ERROR;
-}
-
-template <typename T>
-status_t readFromParcel(std::vector<T>* v, const Parcel& p) {
-    status_t status = p.resizeOutVector(v);
-    if (status != NO_ERROR) {
-        return status;
-    }
-    for (T& x : *v) {
-        status = readFromParcel(&x, p);
-        if (status != NO_ERROR) {
-            return status;
-        }
-    }
-    return NO_ERROR;
-}
-
-} // unnamed namespace
-
-////////////////////////////////////////////////////////////////////////////////
-
-class BpOMXStore : public BpInterface<IOMXStore> {
-public:
-    explicit BpOMXStore(const sp<IBinder> &impl)
-        : BpInterface<IOMXStore>(impl) {
-    }
-
-    status_t listServiceAttributes(
-            std::vector<Attribute>* attributes) override {
-        Parcel data, reply;
-        status_t status;
-        status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
-        if (status != NO_ERROR) {
-            return status;
-        }
-        status = remote()->transact(LIST_SERVICE_ATTRIBUTES, data, &reply);
-        if (status != NO_ERROR) {
-            return status;
-        }
-        return readFromParcel(attributes, reply);
-    }
-
-    status_t getNodePrefix(std::string* prefix) override {
-        Parcel data, reply;
-        status_t status;
-        status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
-        if (status != NO_ERROR) {
-            return status;
-        }
-        status = remote()->transact(GET_NODE_PREFIX, data, &reply);
-        if (status != NO_ERROR) {
-            return status;
-        }
-        return readFromParcel(prefix, reply);
-    }
-
-    status_t listRoles(std::vector<RoleInfo>* roleList) override {
-        Parcel data, reply;
-        status_t status;
-        status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
-        if (status != NO_ERROR) {
-            return status;
-        }
-        status = remote()->transact(LIST_ROLES, data, &reply);
-        if (status != NO_ERROR) {
-            return status;
-        }
-        return readFromParcel(roleList, reply);
-    }
-
-    status_t getOmx(const std::string& name, sp<IOMX>* omx) override {
-        Parcel data, reply;
-        status_t status;
-        status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
-        if (status != NO_ERROR) {
-            return status;
-        }
-        status = writeToParcel(name, &data);
-        if (status != NO_ERROR) {
-            return status;
-        }
-        status = remote()->transact(GET_OMX, data, &reply);
-        if (status != NO_ERROR) {
-            return status;
-        }
-        return reply.readStrongBinder(omx);
-    }
-
-};
-
-IMPLEMENT_META_INTERFACE(OMXStore, "android.hardware.IOMXStore");
-
-////////////////////////////////////////////////////////////////////////////////
-
-#define CHECK_OMX_INTERFACE(interface, data, reply) \
-        do { if (!(data).enforceInterface(interface::getInterfaceDescriptor())) { \
-            ALOGW("Call incorrectly routed to " #interface); \
-            return PERMISSION_DENIED; \
-        } } while (0)
-
-status_t BnOMXStore::onTransact(
-    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
-    switch (code) {
-        case LIST_SERVICE_ATTRIBUTES: {
-            CHECK_OMX_INTERFACE(IOMXStore, data, reply);
-            status_t status;
-            std::vector<Attribute> attributes;
-
-            status = listServiceAttributes(&attributes);
-            if (status != NO_ERROR) {
-                ALOGE("listServiceAttributes() fails with status %d",
-                        static_cast<int>(status));
-                return NO_ERROR;
-            }
-            status = writeToParcel(attributes, reply);
-            if (status != NO_ERROR) {
-                ALOGE("listServiceAttributes() fails to send reply");
-                return NO_ERROR;
-            }
-            return NO_ERROR;
-        }
-        case GET_NODE_PREFIX: {
-            CHECK_OMX_INTERFACE(IOMXStore, data, reply);
-            status_t status;
-            std::string prefix;
-
-            status = getNodePrefix(&prefix);
-            if (status != NO_ERROR) {
-                ALOGE("getNodePrefix() fails with status %d",
-                        static_cast<int>(status));
-                return NO_ERROR;
-            }
-            status = writeToParcel(prefix, reply);
-            if (status != NO_ERROR) {
-                ALOGE("getNodePrefix() fails to send reply");
-                return NO_ERROR;
-            }
-            return NO_ERROR;
-        }
-        case LIST_ROLES: {
-            CHECK_OMX_INTERFACE(IOMXStore, data, reply);
-            status_t status;
-            std::vector<RoleInfo> roleList;
-
-            status = listRoles(&roleList);
-            if (status != NO_ERROR) {
-                ALOGE("listRoles() fails with status %d",
-                        static_cast<int>(status));
-                return NO_ERROR;
-            }
-            status = writeToParcel(roleList, reply);
-            if (status != NO_ERROR) {
-                ALOGE("listRoles() fails to send reply");
-                return NO_ERROR;
-            }
-            return NO_ERROR;
-        }
-        case GET_OMX: {
-            CHECK_OMX_INTERFACE(IOMXStore, data, reply);
-            status_t status;
-            std::string name;
-            sp<IOMX> omx;
-
-            status = readFromParcel(&name, data);
-            if (status != NO_ERROR) {
-                ALOGE("getOmx() fails to retrieve name");
-                return NO_ERROR;
-            }
-            status = getOmx(name, &omx);
-            if (status != NO_ERROR) {
-                ALOGE("getOmx() fails with status %d",
-                        static_cast<int>(status));
-                return NO_ERROR;
-            }
-            status = reply->writeStrongBinder(IInterface::asBinder(omx));
-            if (status != NO_ERROR) {
-                ALOGE("getOmx() fails to send reply");
-                return NO_ERROR;
-            }
-            return NO_ERROR;
-        }
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-}  // namespace android
diff --git a/media/libmedia/include/media/IMediaCodecService.h b/media/libmedia/include/media/IMediaCodecService.h
deleted file mode 100644
index 59fb1c0..0000000
--- a/media/libmedia/include/media/IMediaCodecService.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2015 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_IMEDIACODECSERVICE_H
-#define ANDROID_IMEDIACODECSERVICE_H
-
-#include <binder/IInterface.h>
-#include <binder/IMemory.h>
-#include <binder/Parcel.h>
-#include <media/IDataSource.h>
-#include <media/IOMX.h>
-#include <media/IOMXStore.h>
-
-namespace android {
-
-class IMediaCodecService: public IInterface
-{
-public:
-    DECLARE_META_INTERFACE(MediaCodecService);
-
-    virtual sp<IOMX> getOMX() = 0;
-    virtual sp<IOMXStore> getOMXStore() = 0;
-};
-
-class BnMediaCodecService: public BnInterface<IMediaCodecService>
-{
-public:
-    virtual status_t    onTransact(uint32_t code, const Parcel& data, Parcel* reply,
-                                uint32_t flags = 0);
-};
-
-}   // namespace android
-
-#endif  // ANDROID_IMEDIACODECSERVICE_H
diff --git a/media/libmedia/include/media/IOMXStore.h b/media/libmedia/include/media/IOMXStore.h
deleted file mode 100644
index 628db70..0000000
--- a/media/libmedia/include/media/IOMXStore.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2009 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_IOMXSTORE_H_
-
-#define ANDROID_IOMXSTORE_H_
-
-#include <media/IOMX.h>
-#include <android/hardware/media/omx/1.0/IOmxStore.h>
-
-#include <binder/IInterface.h>
-#include <binder/IBinder.h>
-
-#include <vector>
-#include <string>
-
-namespace android {
-
-using hardware::media::omx::V1_0::IOmxStore;
-
-class IOMXStore : public IInterface {
-public:
-    DECLARE_META_INTERFACE(OMXStore);
-
-    struct Attribute {
-        std::string key;
-        std::string value;
-    };
-
-    struct NodeInfo {
-        std::string name;
-        std::string owner;
-        std::vector<Attribute> attributes;
-    };
-
-    struct RoleInfo {
-        std::string role;
-        std::string type;
-        bool isEncoder;
-        bool preferPlatformNodes;
-        std::vector<NodeInfo> nodes;
-    };
-
-    virtual status_t listServiceAttributes(
-            std::vector<Attribute>* attributes) = 0;
-
-    virtual status_t getNodePrefix(std::string* prefix) = 0;
-
-    virtual status_t listRoles(std::vector<RoleInfo>* roleList) = 0;
-
-    virtual status_t getOmx(const std::string& name, sp<IOMX>* omx) = 0;
-};
-
-
-////////////////////////////////////////////////////////////////////////////////
-
-class BnOMXStore : public BnInterface<IOMXStore> {
-public:
-    virtual status_t onTransact(
-            uint32_t code, const Parcel &data, Parcel *reply,
-            uint32_t flags = 0);
-};
-
-}  // namespace android
-
-#endif  // ANDROID_IOMX_H_
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 6b2c81d..495c418 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -741,26 +741,14 @@
             new ServiceDeathNotifier(binder, p, MEDIAEXTRACTOR_PROCESS_DEATH);
     binder->linkToDeath(extractorDeathListener);
 
-    sp<ServiceDeathNotifier> codecDeathListener;
-    if (property_get_bool("persist.media.treble_omx", true)) {
-        // Treble IOmx
-        sp<IOmx> omx = IOmx::getService();
-        if (omx == nullptr) {
-            ALOGE("Treble IOmx not available");
-            return NULL;
-        }
-        codecDeathListener = new ServiceDeathNotifier(omx, p, MEDIACODEC_PROCESS_DEATH);
-        omx->linkToDeath(codecDeathListener, 0);
-    } else {
-        // Legacy IOMX
-        binder = sm->getService(String16("media.codec"));
-        if (binder == NULL) {
-            ALOGE("codec service not available");
-            return NULL;
-        }
-        codecDeathListener = new ServiceDeathNotifier(binder, p, MEDIACODEC_PROCESS_DEATH);
-        binder->linkToDeath(codecDeathListener);
+    sp<IOmx> omx = IOmx::getService();
+    if (omx == nullptr) {
+        ALOGE("IOmx service is not available");
+        return NULL;
     }
+    sp<ServiceDeathNotifier> codecDeathListener =
+            new ServiceDeathNotifier(omx, p, MEDIACODEC_PROCESS_DEATH);
+    omx->linkToDeath(codecDeathListener, 0);
 
     Mutex::Autolock lock(mLock);
 
@@ -1634,6 +1622,7 @@
       mFlags(AUDIO_OUTPUT_FLAG_NONE),
       mVolumeHandler(new media::VolumeHandler()),
       mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
+      mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE),
       mDeviceCallbackEnabled(false),
       mDeviceCallback(deviceCallback)
 {
@@ -2380,10 +2369,10 @@
     ALOGV("getRoutedDeviceId");
     Mutex::Autolock lock(mLock);
     if (mTrack != 0) {
-        *deviceId = mTrack->getRoutedDeviceId();
-        return NO_ERROR;
+        mRoutedDeviceId = mTrack->getRoutedDeviceId();
     }
-    return NO_INIT;
+    *deviceId = mRoutedDeviceId;
+    return NO_ERROR;
 }
 
 status_t MediaPlayerService::AudioOutput::enableAudioDeviceCallback(bool enabled)
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 71e87a0..eefdd7d 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -176,6 +176,7 @@
         audio_output_flags_t    mFlags;
         sp<media::VolumeHandler>       mVolumeHandler;
         audio_port_handle_t     mSelectedDeviceId;
+        audio_port_handle_t     mRoutedDeviceId;
         bool                    mDeviceCallbackEnabled;
         wp<AudioSystem::AudioDeviceCallback>        mDeviceCallback;
         mutable Mutex           mLock;
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 9b9b3bb..a423fee 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -450,27 +450,14 @@
     }
     sCameraChecked = true;
 
-    if (property_get_bool("persist.media.treble_omx", true)) {
-        // Treble IOmx
-        sp<IOmx> omx = IOmx::getService();
-        if (omx == nullptr) {
-            ALOGE("Treble IOmx not available");
-            return NO_INIT;
-        }
-        mCodecDeathListener = new ServiceDeathNotifier(omx, listener,
-                MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
-        omx->linkToDeath(mCodecDeathListener, 0);
-    } else {
-        // Legacy IOMX
-        binder = sm->getService(String16("media.codec"));
-        if (binder == NULL) {
-           ALOGE("Unable to connect to media codec service");
-           return NO_INIT;
-        }
-        mCodecDeathListener = new ServiceDeathNotifier(binder, listener,
-                MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
-        binder->linkToDeath(mCodecDeathListener);
+    sp<IOmx> omx = IOmx::getService();
+    if (omx == nullptr) {
+        ALOGE("IOmx service is not available");
+        return NO_INIT;
     }
+    mCodecDeathListener = new ServiceDeathNotifier(omx, listener,
+            MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
+    omx->linkToDeath(mCodecDeathListener, 0);
 
     return OK;
 }
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index a7a1b05..d9fdfe3 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -28,8 +28,6 @@
 
 #include <media/stagefright/ACodec.h>
 
-#include <binder/MemoryDealer.h>
-
 #include <media/stagefright/foundation/avc_utils.h>
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/foundation/ABuffer.h>
@@ -575,8 +573,6 @@
     memset(&mLastNativeWindowCrop, 0, sizeof(mLastNativeWindowCrop));
 
     changeState(mUninitializedState);
-
-    mTrebleFlag = false;
 }
 
 ACodec::~ACodec() {
@@ -828,11 +824,7 @@
 status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
 
-    if (getTrebleFlag()) {
-        CHECK(mAllocator[portIndex] == NULL);
-    } else {
-        CHECK(mDealer[portIndex] == NULL);
-    }
+    CHECK(mAllocator[portIndex] == NULL);
     CHECK(mBuffers[portIndex].isEmpty());
 
     status_t err;
@@ -874,7 +866,10 @@
                 }
             }
 
-            size_t alignment = MemoryDealer::getAllocationAlignment();
+            size_t alignment = 32; // This is the value currently returned by
+                                   // MemoryDealer::getAllocationAlignment().
+                                   // TODO: Fix this when Treble has
+                                   // MemoryHeap/MemoryDealer.
 
             ALOGV("[%s] Allocating %u buffers of size %zu (from %u using %s) on %s port",
                     mComponentName.c_str(),
@@ -896,18 +891,15 @@
             }
 
             if (mode != IOMX::kPortModePresetSecureBuffer) {
-                if (getTrebleFlag()) {
-                    mAllocator[portIndex] = TAllocator::getService("ashmem");
-                    if (mAllocator[portIndex] == nullptr) {
-                        ALOGE("hidl allocator on port %d is null",
-                                (int)portIndex);
-                        return NO_MEMORY;
-                    }
-                } else {
-                    size_t totalSize = def.nBufferCountActual *
-                            (alignedSize + alignedConvSize);
-                    mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
+                mAllocator[portIndex] = TAllocator::getService("ashmem");
+                if (mAllocator[portIndex] == nullptr) {
+                    ALOGE("hidl allocator on port %d is null",
+                            (int)portIndex);
+                    return NO_MEMORY;
                 }
+                // TODO: When Treble has MemoryHeap/MemoryDealer, we should
+                // specify the heap size to be
+                // def.nBufferCountActual * (alignedSize + alignedConvSize).
             }
 
             const sp<AMessage> &format =
@@ -936,23 +928,55 @@
                             : new SecureBuffer(format, native_handle, bufSize);
                     info.mCodecData = info.mData;
                 } else {
-                    if (getTrebleFlag()) {
+                    bool success;
+                    auto transStatus = mAllocator[portIndex]->allocate(
+                            bufSize,
+                            [&success, &hidlMemToken](
+                                    bool s,
+                                    hidl_memory const& m) {
+                                success = s;
+                                hidlMemToken = m;
+                            });
+
+                    if (!transStatus.isOk()) {
+                        ALOGE("hidl's AshmemAllocator failed at the "
+                                "transport: %s",
+                                transStatus.description().c_str());
+                        return NO_MEMORY;
+                    }
+                    if (!success) {
+                        return NO_MEMORY;
+                    }
+                    hidlMem = mapMemory(hidlMemToken);
+                    if (hidlMem == nullptr) {
+                        return NO_MEMORY;
+                    }
+                    err = mOMXNode->useBuffer(
+                            portIndex, hidlMemToken, &info.mBufferID);
+
+                    if (mode == IOMX::kPortModeDynamicANWBuffer) {
+                        VideoNativeMetadata* metaData = (VideoNativeMetadata*)(
+                                (void*)hidlMem->getPointer());
+                        metaData->nFenceFd = -1;
+                    }
+
+                    info.mCodecData = new SharedMemoryBuffer(
+                            format, hidlMem);
+                    info.mCodecRef = hidlMem;
+
+                    // if we require conversion, allocate conversion buffer for client use;
+                    // otherwise, reuse codec buffer
+                    if (mConverter[portIndex] != NULL) {
+                        CHECK_GT(conversionBufferSize, (size_t)0);
                         bool success;
-                        auto transStatus = mAllocator[portIndex]->allocate(
-                                bufSize,
+                        mAllocator[portIndex]->allocate(
+                                conversionBufferSize,
                                 [&success, &hidlMemToken](
                                         bool s,
                                         hidl_memory const& m) {
                                     success = s;
                                     hidlMemToken = m;
                                 });
-
-                        if (!transStatus.isOk()) {
-                            ALOGE("hidl's AshmemAllocator failed at the "
-                                    "transport: %s",
-                                    transStatus.description().c_str());
-                            return NO_MEMORY;
-                        }
                         if (!success) {
                             return NO_MEMORY;
                         }
@@ -960,67 +984,8 @@
                         if (hidlMem == nullptr) {
                             return NO_MEMORY;
                         }
-                        err = mOMXNode->useBuffer(
-                                portIndex, hidlMemToken, &info.mBufferID);
-                    } else {
-                        mem = mDealer[portIndex]->allocate(bufSize);
-                        if (mem == NULL || mem->pointer() == NULL) {
-                            return NO_MEMORY;
-                        }
-
-                        err = mOMXNode->useBuffer(
-                                portIndex, mem, &info.mBufferID);
-                    }
-
-                    if (mode == IOMX::kPortModeDynamicANWBuffer) {
-                        VideoNativeMetadata* metaData = (VideoNativeMetadata*)(
-                                getTrebleFlag() ?
-                                (void*)hidlMem->getPointer() : mem->pointer());
-                        metaData->nFenceFd = -1;
-                    }
-
-                    if (getTrebleFlag()) {
-                        info.mCodecData = new SharedMemoryBuffer(
-                                format, hidlMem);
-                        info.mCodecRef = hidlMem;
-                    } else {
-                        info.mCodecData = new SharedMemoryBuffer(
-                                format, mem);
-                        info.mCodecRef = mem;
-                    }
-
-                    // if we require conversion, allocate conversion buffer for client use;
-                    // otherwise, reuse codec buffer
-                    if (mConverter[portIndex] != NULL) {
-                        CHECK_GT(conversionBufferSize, (size_t)0);
-                        if (getTrebleFlag()) {
-                            bool success;
-                            mAllocator[portIndex]->allocate(
-                                    conversionBufferSize,
-                                    [&success, &hidlMemToken](
-                                            bool s,
-                                            hidl_memory const& m) {
-                                        success = s;
-                                        hidlMemToken = m;
-                                    });
-                            if (!success) {
-                                return NO_MEMORY;
-                            }
-                            hidlMem = mapMemory(hidlMemToken);
-                            if (hidlMem == nullptr) {
-                                return NO_MEMORY;
-                            }
-                            info.mData = new SharedMemoryBuffer(format, hidlMem);
-                            info.mMemRef = hidlMem;
-                        } else {
-                            mem = mDealer[portIndex]->allocate(
-                                    conversionBufferSize);
-                            if (mem == NULL|| mem->pointer() == NULL) {
-                                return NO_MEMORY;
-                            }
-                            info.mData = new SharedMemoryBuffer(format, mem);
-                            info.mMemRef = mem;
-                        }
+                        info.mData = new SharedMemoryBuffer(format, hidlMem);
+                        info.mMemRef = hidlMem;
                     } else {
                         info.mData = info.mCodecData;
                         info.mMemRef = info.mCodecRef;
@@ -1581,11 +1546,7 @@
         }
     }
 
-    if (getTrebleFlag()) {
-        mAllocator[portIndex].clear();
-    } else {
-        mDealer[portIndex].clear();
-    }
+    mAllocator[portIndex].clear();
     return err;
 }
 
@@ -6251,13 +6212,8 @@
 
     if (mDeathNotifier != NULL) {
         if (mCodec->mOMXNode != NULL) {
-            if (mCodec->getTrebleFlag()) {
-                auto tOmxNode = mCodec->mOMXNode->getHalInterface();
-                tOmxNode->unlinkToDeath(mDeathNotifier);
-            } else {
-                sp<IBinder> binder = IInterface::asBinder(mCodec->mOMXNode);
-                binder->unlinkToDeath(mDeathNotifier);
-            }
+            auto tOmxNode = mCodec->mOMXNode->getHalInterface();
+            tOmxNode->unlinkToDeath(mDeathNotifier);
         }
         mDeathNotifier.clear();
     }
@@ -6405,8 +6361,7 @@
         componentName = matchingCodecs[matchIndex];
 
         OMXClient client;
-        bool trebleFlag;
-        if (client.connect(owners[matchIndex].c_str(), &trebleFlag) != OK) {
+        if (client.connect(owners[matchIndex].c_str()) != OK) {
             mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
             return false;
         }
@@ -6419,7 +6374,6 @@
         androidSetThreadPriority(tid, prevPriority);
 
         if (err == OK) {
-            mCodec->setTrebleFlag(trebleFlag);
             break;
         } else {
             ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
@@ -6441,17 +6395,9 @@
     }
 
     mDeathNotifier = new DeathNotifier(notify);
-    if (mCodec->getTrebleFlag()) {
-        auto tOmxNode = omxNode->getHalInterface();
-        if (!tOmxNode->linkToDeath(mDeathNotifier, 0)) {
-            mDeathNotifier.clear();
-        }
-    } else {
-        if (IInterface::asBinder(omxNode)->linkToDeath(mDeathNotifier) != OK) {
-            // This was a local binder, if it dies so do we, we won't care
-            // about any notifications in the afterlife.
-            mDeathNotifier.clear();
-        }
+    auto tOmxNode = omxNode->getHalInterface();
+    if (!tOmxNode->linkToDeath(mDeathNotifier, 0)) {
+        mDeathNotifier.clear();
     }
 
     notify = new AMessage(kWhatOMXMessageList, mCodec);
@@ -7858,11 +7804,7 @@
                             mCodec->mBuffers[kPortIndexOutput].size());
                     err = FAILED_TRANSACTION;
                 } else {
-                    if (mCodec->getTrebleFlag()) {
-                        mCodec->mAllocator[kPortIndexOutput].clear();
-                    } else {
-                        mCodec->mDealer[kPortIndexOutput].clear();
-                    }
+                    mCodec->mAllocator[kPortIndexOutput].clear();
                 }
 
                 if (err == OK) {
@@ -8464,12 +8406,4 @@
     return OK;
 }
 
-void ACodec::setTrebleFlag(bool trebleFlag) {
-    mTrebleFlag = trebleFlag;
-}
-
-bool ACodec::getTrebleFlag() const {
-    return mTrebleFlag;
-}
-
 }  // namespace android
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 7ba4b7d..0c71487 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -100,8 +100,10 @@
         "libui",
         "libutils",
         "libmedia_helper",
-        "libstagefright_omx_utils",
         "libstagefright_foundation",
+        "libstagefright_omx",
+        "libstagefright_omx_utils",
+        "libstagefright_xmlparser",
         "libdl",
         "libRScpp",
         "libhidlbase",
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 4feba37..54265a4 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -24,7 +24,6 @@
 
 #include <media/IMediaCodecList.h>
 #include <media/IMediaPlayerService.h>
-#include <media/IMediaCodecService.h>
 #include <media/MediaCodecInfo.h>
 
 #include <media/stagefright/foundation/ADebug.h>
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index 5f50e46..9375de1 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -25,7 +25,6 @@
 #include <cutils/properties.h>
 
 #include <binder/IServiceManager.h>
-#include <media/IMediaCodecService.h>
 #include <media/stagefright/OMXClient.h>
 
 #include <media/IOMX.h>
@@ -38,70 +37,25 @@
 }
 
 status_t OMXClient::connect() {
-    return connect("default", nullptr);
+    return connect("default");
 }
 
-status_t OMXClient::connect(bool* trebleFlag) {
-    if (property_get_bool("persist.media.treble_omx", true)) {
-        if (trebleFlag != nullptr) {
-            *trebleFlag = true;
-        }
-        return connectTreble();
-    }
-    if (trebleFlag != nullptr) {
-        *trebleFlag = false;
-    }
-    return connectLegacy();
-}
-
-status_t OMXClient::connect(const char* name, bool* trebleFlag) {
-    if (property_get_bool("persist.media.treble_omx", true)) {
-        if (trebleFlag != nullptr) {
-            *trebleFlag = true;
-        }
-        return connectTreble(name);
-    }
-    if (trebleFlag != nullptr) {
-        *trebleFlag = false;
-    }
-    return connectLegacy();
-}
-
-status_t OMXClient::connectLegacy() {
-    sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> codecbinder = sm->getService(String16("media.codec"));
-    sp<IMediaCodecService> codecservice = interface_cast<IMediaCodecService>(codecbinder);
-
-    if (codecservice.get() == NULL) {
-        ALOGE("Cannot obtain IMediaCodecService");
-        return NO_INIT;
-    }
-
-    mOMX = codecservice->getOMX();
-    if (mOMX.get() == NULL) {
-        ALOGE("Cannot obtain mediacodec IOMX");
-        return NO_INIT;
-    }
-
-    return OK;
-}
-
-status_t OMXClient::connectTreble(const char* name) {
+status_t OMXClient::connect(const char* name) {
     using namespace ::android::hardware::media::omx::V1_0;
     if (name == nullptr) {
         name = "default";
     }
     sp<IOmx> tOmx = IOmx::getService(name);
     if (tOmx.get() == nullptr) {
-        ALOGE("Cannot obtain Treble IOmx.");
+        ALOGE("Cannot obtain IOmx service.");
         return NO_INIT;
     }
     if (!tOmx->isRemote()) {
-        ALOGE("Treble IOmx is in passthrough mode.");
+        ALOGE("IOmx service running in passthrough mode.");
         return NO_INIT;
     }
     mOMX = new utils::LWOmx(tOmx);
-    ALOGI("Treble IOmx obtained");
+    ALOGI("IOmx service obtained");
     return OK;
 }
 
@@ -109,4 +63,8 @@
     mOMX.clear();
 }
 
+sp<IOMX> OMXClient::interface() {
+    return mOMX;
+}
+
 }  // namespace android
diff --git a/media/libstagefright/OmxInfoBuilder.cpp b/media/libstagefright/OmxInfoBuilder.cpp
index 063d13e..a6ebadd 100644
--- a/media/libstagefright/OmxInfoBuilder.cpp
+++ b/media/libstagefright/OmxInfoBuilder.cpp
@@ -24,8 +24,6 @@
 #include <utils/Log.h>
 #include <cutils/properties.h>
 
-#include <binder/IServiceManager.h>
-#include <media/IMediaCodecService.h>
 #include <media/stagefright/foundation/MediaDefs.h>
 #include <media/stagefright/OmxInfoBuilder.h>
 #include <media/stagefright/ACodec.h>
@@ -35,9 +33,9 @@
 #include <android/hardware/media/omx/1.0/IOmxNode.h>
 #include <media/stagefright/omx/OMXUtils.h>
 
-#include <media/IOMXStore.h>
 #include <media/IOMX.h>
 #include <media/omx/1.0/WOmx.h>
+#include <media/stagefright/omx/1.0/OmxStore.h>
 
 #include <media/openmax/OMX_Index.h>
 #include <media/openmax/OMX_IndexExt.h>
@@ -48,10 +46,18 @@
 
 namespace android {
 
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using namespace ::android::hardware::media::omx::V1_0;
+
 namespace /* unnamed */ {
 
+bool hasPrefix(const hidl_string& s, const char* prefix) {
+    return strncmp(s.c_str(), prefix, strlen(prefix)) == 0;
+}
+
 status_t queryCapabilities(
-        const IOMXStore::NodeInfo& node, const char* mime, bool isEncoder,
+        const IOmxStore::NodeInfo& node, const char* mime, bool isEncoder,
         MediaCodecInfo::CapabilitiesWriter* caps) {
     sp<ACodec> codec = new ACodec();
     status_t err = codec->queryCapabilities(
@@ -62,14 +68,13 @@
     for (const auto& attribute : node.attributes) {
         // All features have an int32 value except
         // "feature-bitrate-modes", which has a string value.
-        if ((attribute.key.compare(0, 8, "feature-") == 0) &&
-                (attribute.key.compare(8, 15, "bitrate-modes")
-                 != 0)) {
-            // If this attribute.key is a feature that is not a bitrate
-            // control, add an int32 value.
+        if (hasPrefix(attribute.key, "feature-") &&
+                !hasPrefix(attribute.key, "feature-bitrate-modes")) {
+            // If this attribute.key is a feature that is not bitrate modes,
+            // add an int32 value.
             caps->addDetail(
                     attribute.key.c_str(),
-                    attribute.value == "1" ? 1 : 0);
+                    hasPrefix(attribute.value, "1") ? 1 : 0);
         } else {
             // Non-feature attributes
             caps->addDetail(
@@ -85,138 +90,70 @@
 }
 
 status_t OmxInfoBuilder::buildMediaCodecList(MediaCodecListWriter* writer) {
-    bool treble;
-    sp<IOMX> omx;
-    std::vector<IOMXStore::RoleInfo> roles;
+    // Obtain IOmxStore
+    sp<IOmxStore> omxStore = IOmxStore::getService();
+    if (omxStore == nullptr) {
+        ALOGE("Cannot find an IOmxStore service.");
+        return NO_INIT;
+    }
 
-    treble = property_get_bool("persist.media.treble_omx", true);
-    if (treble) {
-        using namespace ::android::hardware::media::omx::V1_0;
-        using ::android::hardware::hidl_vec;
-        using ::android::hardware::hidl_string;
-
-        // Obtain IOmxStore
-        sp<IOmxStore> omxStore = IOmxStore::getService();
+    // List service attributes (global settings)
+    Status status;
+    hidl_vec<IOmxStore::RoleInfo> roles;
+    auto transStatus = omxStore->listRoles(
+            [&roles] (
+            const hidl_vec<IOmxStore::RoleInfo>& inRoleList) {
+                roles = inRoleList;
+            });
+    if (!transStatus.isOk()) {
+        ALOGE("Fail to obtain codec roles from IOmxStore.");
+        return NO_INIT;
+    } else if (roles.size() == 0) {
+        ALOGW("IOmxStore has empty implementation. "
+                "Creating a local default instance...");
+        omxStore = new implementation::OmxStore();
         if (omxStore == nullptr) {
-            ALOGE("Cannot connect to an IOmxStore instance.");
+            ALOGE("Cannot create a local default instance.");
             return NO_INIT;
         }
-
-        // List service attributes (global settings)
-        Status status;
-        hidl_vec<IOmxStore::ServiceAttribute> serviceAttributes;
-        auto transStatus = omxStore->listServiceAttributes(
-                [&status, &serviceAttributes]
-                (Status inStatus, const hidl_vec<IOmxStore::ServiceAttribute>&
-                        inAttributes) {
-                    status = inStatus;
-                    serviceAttributes = inAttributes;
-                });
-        if (!transStatus.isOk()) {
-            ALOGE("Fail to obtain global settings from IOmxStore.");
-            return NO_INIT;
-        }
-        if (status != Status::OK) {
-            ALOGE("IOmxStore reports parsing error.");
-            return NO_INIT;
-        }
-        for (const auto& p : serviceAttributes) {
-            writer->addGlobalSetting(
-                    p.key.c_str(), p.value.c_str());
-        }
-
-        // List roles and convert to IOMXStore's format
+        ALOGI("IOmxStore local default instance created.");
         transStatus = omxStore->listRoles(
-                [&roles]
-                (const hidl_vec<IOmxStore::RoleInfo>& inRoleList) {
-                    roles.reserve(inRoleList.size());
-                    for (const auto& inRole : inRoleList) {
-                        IOMXStore::RoleInfo role;
-                        role.role = inRole.role;
-                        role.type = inRole.type;
-                        role.isEncoder = inRole.isEncoder;
-                        role.preferPlatformNodes = inRole.preferPlatformNodes;
-                        std::vector<IOMXStore::NodeInfo>& nodes =
-                                role.nodes;
-                        nodes.reserve(inRole.nodes.size());
-                        for (const auto& inNode : inRole.nodes) {
-                            IOMXStore::NodeInfo node;
-                            node.name = inNode.name;
-                            node.owner = inNode.owner;
-                            std::vector<IOMXStore::Attribute>& attributes =
-                                    node.attributes;
-                            attributes.reserve(inNode.attributes.size());
-                            for (const auto& inAttr : inNode.attributes) {
-                                IOMXStore::Attribute attr;
-                                attr.key = inAttr.key;
-                                attr.value = inAttr.value;
-                                attributes.push_back(std::move(attr));
-                            }
-                            nodes.push_back(std::move(node));
-                        }
-                        roles.push_back(std::move(role));
-                    }
+                [&roles] (
+                const hidl_vec<IOmxStore::RoleInfo>& inRoleList) {
+                    roles = inRoleList;
                 });
         if (!transStatus.isOk()) {
-            ALOGE("Fail to obtain codec roles from IOmxStore.");
-            return NO_INIT;
-        }
-    } else {
-        // Obtain IOMXStore
-        sp<IServiceManager> sm = defaultServiceManager();
-        if (sm == nullptr) {
-            ALOGE("Cannot obtain the default service manager.");
-            return NO_INIT;
-        }
-        sp<IBinder> codecBinder = sm->getService(String16("media.codec"));
-        if (codecBinder == nullptr) {
-            ALOGE("Cannot obtain the media codec service.");
-            return NO_INIT;
-        }
-        sp<IMediaCodecService> codecService =
-                interface_cast<IMediaCodecService>(codecBinder);
-        if (codecService == nullptr) {
-            ALOGE("Wrong type of media codec service obtained.");
-            return NO_INIT;
-        }
-        omx = codecService->getOMX();
-        if (omx == nullptr) {
-            ALOGE("Cannot connect to an IOMX instance.");
-        }
-        sp<IOMXStore> omxStore = codecService->getOMXStore();
-        if (omxStore == nullptr) {
-            ALOGE("Cannot connect to an IOMXStore instance.");
-            return NO_INIT;
-        }
-
-        // List service attributes (global settings)
-        std::vector<IOMXStore::Attribute> serviceAttributes;
-        status_t status = omxStore->listServiceAttributes(&serviceAttributes);
-        if (status != OK) {
-            ALOGE("Fail to obtain global settings from IOMXStore.");
-            return NO_INIT;
-        }
-        for (const auto& p : serviceAttributes) {
-            writer->addGlobalSetting(
-                    p.key.c_str(), p.value.c_str());
-        }
-
-        // List roles
-        status = omxStore->listRoles(&roles);
-        if (status != OK) {
-            ALOGE("Fail to obtain codec roles from IOMXStore.");
+            ALOGE("Fail to obtain codec roles from local IOmxStore.");
             return NO_INIT;
         }
     }
 
+    hidl_vec<IOmxStore::ServiceAttribute> serviceAttributes;
+    transStatus = omxStore->listServiceAttributes(
+            [&status, &serviceAttributes] (
+            Status inStatus,
+            const hidl_vec<IOmxStore::ServiceAttribute>& inAttributes) {
+                status = inStatus;
+                serviceAttributes = inAttributes;
+            });
+    if (!transStatus.isOk()) {
+        ALOGE("Fail to obtain global settings from IOmxStore.");
+        return NO_INIT;
+    }
+    if (status != Status::OK) {
+        ALOGE("IOmxStore reports parsing error.");
+        return NO_INIT;
+    }
+    for (const auto& p : serviceAttributes) {
+        writer->addGlobalSetting(
+                p.key.c_str(), p.value.c_str());
+    }
+
     // Convert roles to lists of codecs
 
-    // codec name -> index into swCodecs
-    std::map<std::string, std::unique_ptr<MediaCodecInfoWriter> >
-            swCodecName2Info;
-    // codec name -> index into hwCodecs
-    std::map<std::string, std::unique_ptr<MediaCodecInfoWriter> >
-            hwCodecName2Info;
+    // codec name -> index into swCodecs/hwCodecs
+    std::map<hidl_string, std::unique_ptr<MediaCodecInfoWriter>>
+            swCodecName2Info, hwCodecName2Info;
     // owner name -> MediaCodecInfo
     // This map will be used to obtain the correct IOmx service(s) needed for
     // creating IOmxNode instances and querying capabilities.
@@ -230,10 +167,10 @@
         // If preferPlatformNodes is true, hardware nodes must be added after
         // platform (software) nodes. hwCodecs is used to hold hardware nodes
         // that need to be added after software nodes for the same role.
-        std::vector<const IOMXStore::NodeInfo*> hwCodecs;
+        std::vector<const IOmxStore::NodeInfo*> hwCodecs;
         for (const auto& node : role.nodes) {
             const auto& nodeName = node.name;
-            bool isSoftware = nodeName.compare(0, 10, "OMX.google") == 0;
+            bool isSoftware = hasPrefix(nodeName, "OMX.google");
             MediaCodecInfoWriter* info;
             if (isSoftware) {
                 auto c2i = swCodecName2Info.find(nodeName);
diff --git a/media/libstagefright/codec2/Android.bp b/media/libstagefright/codec2/Android.bp
index f79e058..311a20b 100644
--- a/media/libstagefright/codec2/Android.bp
+++ b/media/libstagefright/codec2/Android.bp
@@ -17,9 +17,9 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
-        cfi: true,
+        cfi: false, // true,
         diag: {
-            cfi: true,
+            cfi: false, // true,
         },
     },
 
diff --git a/media/libstagefright/codec2/include/C2Buffer.h b/media/libstagefright/codec2/include/C2Buffer.h
index cb8c2d2..22e4360 100644
--- a/media/libstagefright/codec2/include/C2Buffer.h
+++ b/media/libstagefright/codec2/include/C2Buffer.h
@@ -1529,17 +1529,71 @@
 class C2Allocator {
 public:
     /**
+     * Allocator ID type.
+     */
+    typedef uint32_t id_t;
+
+    /**
+     * Allocation types. This is a bitmask and is used in C2Allocator::Info
+     * to list the supported allocation types of an allocator.
+     */
+    enum type_t : uint32_t {
+        LINEAR  = 1 << 0, //
+        GRAPHIC = 1 << 1,
+    };
+
+    /**
+     * Information about an allocator.
+     */
+    struct Info {
+        C2String name;              ///< allocator name
+        id_t id;                    ///< allocator ID
+        type_t supportedTypes;      ///< supported allocation types
+        C2MemoryUsage minimumUsage; ///< usage that is minimally required for allocations
+        C2MemoryUsage maximumUsage; ///< usage that is maximally allowed for allocations
+    };
+
+    /**
+     * Returns the unique name of this allocator.
+     *
+     * This method MUST be "non-blocking" and return within 1ms.
+     *
+     * \return the name of this allocator.
+     * \retval an empty string if there was not enough memory to allocate the actual name.
+     */
+    virtual C2String getName() const = 0;
+
+    /**
+     * Returns a unique ID for this allocator. This ID is used to get this allocator from the
+     * allocator store, and to identify this allocator across all processes.
+     *
+     * This method MUST be "non-blocking" and return within 1ms.
+     *
+     * \return a unique ID for this allocator.
+     */
+    virtual id_t getId() const = 0;
+
+    /**
+     * Returns the allocator information.
+     *
+     * This method MUST be "non-blocking" and return within 1ms.
+     *
+     * \return allocator information
+     */
+    virtual std::shared_ptr<const Info> getInfo() const = 0;
+
+    /**
      * Allocates a 1D allocation of given |capacity| and |usage|. If successful, the allocation is
      * stored in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
      *
-     * \param capacity        the size of requested allocation (the allocation could be slightly
+     * \param capacity      the size of requested allocation (the allocation could be slightly
      *                      larger, e.g. to account for any system-required alignment)
-     * \param usage           the memory usage info for the requested allocation. \note that the
+     * \param usage         the memory usage info for the requested allocation. \note that the
      *                      returned allocation may be later used/mapped with different usage.
      *                      The allocator should layout the buffer to be optimized for this usage,
      *                      but must support any usage. One exception: protected buffers can
      *                      only be used in a protected scenario.
-     * \param allocation      pointer to where the allocation shall be stored on success. nullptr
+     * \param allocation    pointer to where the allocation shall be stored on success. nullptr
      *                      will be stored here on failure
      *
      * \retval C2_OK        the allocation was successful
@@ -1550,7 +1604,7 @@
      * \retval C2_OMITTED   this allocator does not support 1D allocations
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
      */
-    virtual C2Status allocateLinearBuffer(
+    virtual C2Status newLinearAllocation(
             uint32_t capacity __unused, C2MemoryUsage usage __unused,
             std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
         *allocation = nullptr;
@@ -1563,7 +1617,7 @@
      *
      * \param handle      the handle for the existing allocation
      * \param allocation  pointer to where the allocation shall be stored on success. nullptr
-     *                  will be stored here on failure
+     *                    will be stored here on failure
      *
      * \retval C2_OK        the allocation was recreated successfully
      * \retval C2_NO_MEMORY not enough memory to recreate the allocation
@@ -1573,7 +1627,7 @@
      * \retval C2_OMITTED   this allocator does not support 1D allocations
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
      */
-    virtual C2Status recreateLinearBuffer(
+    virtual C2Status priorLinearAllocation(
             const C2Handle *handle __unused,
             std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
         *allocation = nullptr;
@@ -1584,18 +1638,18 @@
      * Allocates a 2D allocation of given |width|, |height|, |format| and |usage|. If successful,
      * the allocation is stored in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
      *
-     * \param width           the width of requested allocation (the allocation could be slightly
+     * \param width         the width of requested allocation (the allocation could be slightly
      *                      larger, e.g. to account for any system-required alignment)
-     * \param height          the height of requested allocation (the allocation could be slightly
+     * \param height        the height of requested allocation (the allocation could be slightly
      *                      larger, e.g. to account for any system-required alignment)
-     * \param format          the pixel format of requested allocation. This could be a vendor
+     * \param format        the pixel format of requested allocation. This could be a vendor
      *                      specific format.
-     * \param usage           the memory usage info for the requested allocation. \note that the
+     * \param usage         the memory usage info for the requested allocation. \note that the
      *                      returned allocation may be later used/mapped with different usage.
      *                      The allocator should layout the buffer to be optimized for this usage,
      *                      but must support any usage. One exception: protected buffers can
      *                      only be used in a protected scenario.
-     * \param allocation      pointer to where the allocation shall be stored on success. nullptr
+     * \param allocation    pointer to where the allocation shall be stored on success. nullptr
      *                      will be stored here on failure
      *
      * \retval C2_OK        the allocation was successful
@@ -1606,7 +1660,7 @@
      * \retval C2_OMITTED   this allocator does not support 2D allocations
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
      */
-    virtual C2Status allocateGraphicBuffer(
+    virtual C2Status newGraphicAllocation(
             uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
             C2MemoryUsage usage __unused,
             std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
@@ -1620,7 +1674,7 @@
      *
      * \param handle      the handle for the existing allocation
      * \param allocation  pointer to where the allocation shall be stored on success. nullptr
-     *                  will be stored here on failure
+     *                    will be stored here on failure
      *
      * \retval C2_OK        the allocation was recreated successfully
      * \retval C2_NO_MEMORY not enough memory to recreate the allocation
@@ -1630,7 +1684,7 @@
      * \retval C2_OMITTED   this allocator does not support 2D allocations
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during recreation (unexpected)
      */
-    virtual C2Status recreateGraphicBuffer(
+    virtual C2Status priorGraphicAllocation(
             const C2Handle *handle __unused,
             std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
         *allocation = nullptr;
@@ -1644,37 +1698,73 @@
 };
 
 /**
- *  Block allocators are used by components to allocate memory for output buffers. They can
- *  support either linear (1D), circular (1D) or graphic (2D) allocations.
+ *  Block pools are used by components to obtain output buffers in an efficient way. They can
+ *  support either linear (1D), circular (1D) or graphic (2D) blocks.
+ *
+ *  Block pools decouple the recycling of memory/allocations from the components. They are meant to
+ *  be an opaque service (there are no public APIs other than obtaining blocks) provided by the
+ *  platform. Block pools are also meant to decouple allocations from memory used by buffers. This
+ *  is accomplished by allowing pools to allot multiple memory 'blocks' on a single allocation. As
+ *  their name suggest, block pools maintain a pool of memory blocks. When a component asks for
+ *  a memory block, pools will try to return a free memory block already in the pool. If no such
+ *  block exists, they will allocate memory using the backing allocator and allot a block on that
+ *  allocation. When blocks are no longer used in the system, they are recycled back to the block
+ *  pool and are available as free blocks.
  *
  *  Never constructed on stack.
- *
- *  Block allocators are provided by the framework.
  */
-class C2BlockAllocator {
+class C2BlockPool {
 public:
     /**
-     * Allocates a linear writeable block of given |capacity| and |usage|. If successful, the
+     * Block pool ID type.
+     */
+    typedef uint64_t local_id_t;
+
+    enum : local_id_t {
+        BASIC_LINEAR = 0,  ///< ID of basic (unoptimized) block pool for fetching 1D blocks
+        BASIC_GRAPHIC = 1, ///< ID of basic (unoptimized) block pool for fetching 2D blocks
+        PLATFORM_START = 0x10,
+    };
+
+    /**
+     * Returns the ID for this block pool. This ID is used to get this block pool from the platform.
+     * It is only valid in the current process.
+     *
+     * This method MUST be "non-blocking" and return within 1ms.
+     *
+     * \return a local ID for this block pool.
+     */
+    virtual local_id_t getLocalId() const = 0;
+
+    /**
+     * Returns the ID of the backing allocator of this block pool.
+     *
+     * This method MUST be "non-blocking" and return within 1ms.
+     *
+     * \return the ID of the backing allocator of this block pool.
+     */
+    virtual C2Allocator::id_t getAllocatorId() const = 0;
+
+    /**
+     * Obtains a linear writeable block of given |capacity| and |usage|. If successful, the
      * block is stored in |block|. Otherwise, |block| is set to 'nullptr'.
      *
-     * \param capacity        the size of requested block.
-     * \param usage           the memory usage info for the requested allocation. \note that the
-     *                      returned allocation may be later used/mapped with different usage.
-     *                      The allocator shall lay out the buffer to be optimized for this usage,
-     *                      but must support any usage. One exception: protected buffers can
-     *                      only be used in a protected scenario.
-     * \param block      pointer to where the allocated block shall be stored on success. nullptr
-     *                      will be stored here on failure
+     * \param capacity the size of requested block.
+     * \param usage    the memory usage info for the requested block. Returned blocks will be
+     *                 optimized for this usage, but may be used with any usage. One exception:
+     *                 protected blocks/buffers can only be used in a protected scenario.
+     * \param block    pointer to where the obtained block shall be stored on success. nullptr will
+     *                 be stored here on failure
      *
-     * \retval C2_OK        the allocation was successful
-     * \retval C2_NO_MEMORY not enough memory to complete the allocation
-     * \retval C2_TIMED_OUT the allocation timed out
-     * \retval C2_REFUSED   no permission to complete the allocation
+     * \retval C2_OK        the operation was successful
+     * \retval C2_NO_MEMORY not enough memory to complete any required allocation
+     * \retval C2_TIMED_OUT the operation timed out
+     * \retval C2_REFUSED   no permission to complete any required allocation
      * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
-     * \retval C2_OMITTED   this allocator does not support linear allocations
-     * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
+     * \retval C2_OMITTED   this pool does not support linear blocks
+     * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
      */
-    virtual C2Status allocateLinearBlock(
+    virtual C2Status fetchLinearBlock(
             uint32_t capacity __unused, C2MemoryUsage usage __unused,
             std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
         *block = nullptr;
@@ -1682,28 +1772,27 @@
     }
 
     /**
-     * Allocates a circular writeable block of given |capacity| and |usage|. If successful, the
+     * Obtains a circular writeable block of given |capacity| and |usage|. If successful, the
      * block is stored in |block|. Otherwise, |block| is set to 'nullptr'.
      *
-     * \param capacity        the size of requested circular block. (the allocation could be slightly
-     *                      larger, e.g. to account for any system-required alignment)
-     * \param usage           the memory usage info for the requested allocation. \note that the
-     *                      returned allocation may be later used/mapped with different usage.
-     *                      The allocator shall lay out the buffer to be optimized for this usage,
-     *                      but must support any usage. One exception: protected buffers can
-     *                      only be used in a protected scenario.
-     * \param block      pointer to where the allocated block shall be stored on success. nullptr
-     *                      will be stored here on failure
+     * \param capacity the size of requested circular block. (note: the size of the obtained
+     *                 block could be slightly larger, e.g. to accommodate any system-required
+     *                 alignment)
+     * \param usage    the memory usage info for the requested block. Returned blocks will be
+     *                 optimized for this usage, but may be used with any usage. One exception:
+     *                 protected blocks/buffers can only be used in a protected scenario.
+     * \param block    pointer to where the obtained block shall be stored on success. nullptr
+     *                 will be stored here on failure
      *
-     * \retval C2_OK            the allocation was successful
-     * \retval C2_NO_MEMORY     not enough memory to complete the allocation
-     * \retval C2_TIMED_OUT     the allocation timed out
-     * \retval C2_REFUSED       no permission to complete the allocation
-     * \retval C2_BAD_VALUE     capacity or usage are not supported (invalid) (caller error)
-     * \retval C2_OMITTED       this allocator does not support circular allocations
-     * \retval C2_CORRUPTED     some unknown, unrecoverable error occured during allocation (unexpected)
+     * \retval C2_OK        the operation was successful
+     * \retval C2_NO_MEMORY not enough memory to complete any required allocation
+     * \retval C2_TIMED_OUT the operation timed out
+     * \retval C2_REFUSED   no permission to complete any required allocation
+     * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
+     * \retval C2_OMITTED   this pool does not support circular blocks
+     * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
      */
-    virtual C2Status allocateCircularBlock(
+    virtual C2Status fetchCircularBlock(
             uint32_t capacity __unused, C2MemoryUsage usage __unused,
             std::shared_ptr<C2CircularBlock> *block /* nonnull */) {
         *block = nullptr;
@@ -1711,32 +1800,30 @@
     }
 
     /**
-     * Allocates a 2D graphic block of given |width|, |height|, |format| and |usage|. If successful,
-     * the allocation is stored in |block|. Otherwise, |block| is set to 'nullptr'.
+     * Obtains a 2D graphic block of given |width|, |height|, |format| and |usage|. If successful,
+     * the block is stored in |block|. Otherwise, |block| is set to 'nullptr'.
      *
-     * \param width           the width of requested allocation (the allocation could be slightly
-     *                      larger, e.g. to account for any system-required alignment)
-     * \param height          the height of requested allocation (the allocation could be slightly
-     *                      larger, e.g. to account for any system-required alignment)
-     * \param format          the pixel format of requested allocation. This could be a vendor
-     *                      specific format.
-     * \param usage           the memory usage info for the requested allocation. \note that the
-     *                      returned allocation may be later used/mapped with different usage.
-     *                      The allocator should layout the buffer to be optimized for this usage,
-     *                      but must support any usage. One exception: protected buffers can
-     *                      only be used in a protected scenario.
-     * \param block      pointer to where the allocation shall be stored on success. nullptr
-     *                      will be stored here on failure
+     * \param width  the width of requested block (the obtained block could be slightly larger, e.g.
+     *               to accommodate any system-required alignment)
+     * \param height the height of requested block (the obtained block could be slightly larger,
+     *               e.g. to accommodate any system-required alignment)
+     * \param format the pixel format of requested block. This could be a vendor specific format.
+     * \param usage  the memory usage info for the requested block. Returned blocks will be
+     *               optimized for this usage, but may be used with any usage. One exception:
+     *               protected blocks/buffers can only be used in a protected scenario.
+     * \param block  pointer to where the obtained block shall be stored on success. nullptr
+     *               will be stored here on failure
      *
-     * \retval C2_OK            the allocation was successful
-     * \retval C2_NO_MEMORY     not enough memory to complete the allocation
-     * \retval C2_TIMED_OUT     the allocation timed out
-     * \retval C2_REFUSED       no permission to complete the allocation
-     * \retval C2_BAD_VALUE     width, height, format or usage are not supported (invalid) (caller error)
-     * \retval C2_OMITTED       this allocator does not support 2D allocations
-     * \retval C2_CORRUPTED     some unknown, unrecoverable error occured during allocation (unexpected)
+     * \retval C2_OK        the operation was successful
+     * \retval C2_NO_MEMORY not enough memory to complete any required allocation
+     * \retval C2_TIMED_OUT the operation timed out
+     * \retval C2_REFUSED   no permission to complete any required allocation
+     * \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller
+     *                      error)
+     * \retval C2_OMITTED   this pool does not support 2D blocks
+     * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
      */
-    virtual C2Status allocateGraphicBlock(
+    virtual C2Status fetchGraphicBlock(
             uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
             C2MemoryUsage usage __unused,
             std::shared_ptr<C2GraphicBlock> *block /* nonnull */) {
@@ -1745,9 +1832,9 @@
     }
 
 protected:
-    C2BlockAllocator() = default;
+    C2BlockPool() = default;
 
-    virtual ~C2BlockAllocator() = default;
+    virtual ~C2BlockPool() = default;
 };
 
 /// @}
diff --git a/media/libstagefright/codec2/include/C2Component.h b/media/libstagefright/codec2/include/C2Component.h
index 2ac9c72..c88de62 100644
--- a/media/libstagefright/codec2/include/C2Component.h
+++ b/media/libstagefright/codec2/include/C2Component.h
@@ -542,11 +542,9 @@
 
 class C2AllocatorStore {
 public:
-    // TBD
+    typedef C2Allocator::id_t id_t;
 
-    typedef uint32_t ID;
-
-    enum ID_ : uint32_t {
+    enum : C2Allocator::id_t {
         DEFAULT_LINEAR,     ///< basic linear allocator type
         DEFAULT_GRAPHIC,    ///< basic graphic allocator type
         PLATFORM_START = 0x10,
@@ -554,7 +552,30 @@
     };
 
     /**
-     * Creates an allocator.
+     * Returns the unique name of this allocator store.
+     *
+     * This method MUST be "non-blocking" and return within 1ms.
+     *
+     * \return the name of this allocator store.
+     * \retval an empty string if there was not enough memory to allocate the actual name.
+     */
+    virtual C2String getName() const = 0;
+
+    /**
+     * Returns the set of allocators supported by this allocator store.
+     *
+     * This method SHALL return within 1ms.
+     *
+     * \retval vector of allocator information (as shared pointers)
+     * \retval an empty vector if there was not enough memory to allocate the whole vector.
+     */
+    virtual std::vector<std::shared_ptr<const C2Allocator::Info>> listAllocators() const = 0;
+
+    /**
+     * Retrieves/creates a shared allocator object.
+     *
+     * The allocator is created on first use, and the same allocator is returned on subsequent
+     * concurrent uses in the same process. The allocator is freed when it is no longer referenced.
      *
      * \param id      the ID of the allocator to create. This is defined by the store, but
      *                the ID of the default linear and graphic allocators is formalized.
@@ -568,7 +589,7 @@
      * \retval C2_NOT_FOUND no such allocator
      * \retval C2_NO_MEMORY not enough memory to create the allocator
      */
-    virtual C2Status createAllocator(ID id, std::shared_ptr<C2Allocator>* const allocator) = 0;
+    virtual C2Status getAllocator(id_t id, std::shared_ptr<C2Allocator>* const allocator) = 0;
 
     virtual ~C2AllocatorStore() = default;
 };
diff --git a/media/libstagefright/codec2/include/C2Config.h b/media/libstagefright/codec2/include/C2Config.h
index d4294c4..0568432 100644
--- a/media/libstagefright/codec2/include/C2Config.h
+++ b/media/libstagefright/codec2/include/C2Config.h
@@ -61,13 +61,15 @@
     kParamIndexMime,
     kParamIndexStreamCount,
     kParamIndexFormat,
+    kParamIndexBlockPools,
+
+    kParamIndexMaxVideoSizeHint,
+    kParamIndexVideoSizeTuning,
 
     // video info
 
     kParamIndexStructStart = 0x1,
     kParamIndexVideoSize,
-    kParamIndexMaxVideoSizeHint,
-    kParamIndexVideoSizeTuning,
 
     kParamIndexParamStart = 0x800,
 };
@@ -125,6 +127,8 @@
 
 typedef C2StreamParam<C2Tuning, C2Uint32Value, kParamIndexFormat> C2StreamFormatConfig;
 
+typedef C2PortParam<C2Tuning, C2Uint64Array, kParamIndexBlockPools> C2PortBlockPoolsTuning;
+
 /*
    Component description fields:
 
diff --git a/media/libstagefright/codec2/include/C2Work.h b/media/libstagefright/codec2/include/C2Work.h
index 69c16ab..52c00d5 100644
--- a/media/libstagefright/codec2/include/C2Work.h
+++ b/media/libstagefright/codec2/include/C2Work.h
@@ -118,8 +118,8 @@
     std::list<std::unique_ptr<C2Param>> tunings; //< tunings to be applied before processing this
                                                  // worklet
     std::list<C2Param::Type> requestedInfos;
-    std::vector<std::shared_ptr<C2BlockAllocator>> allocators; //< This vector shall be the same size as
-                                                          //< output.buffers.
+    std::vector<std::shared_ptr<C2BlockPool>> allocators; //< This vector shall be the same size as
+                                                          //< output.buffers. \deprecated
 
     // OUT
     C2BufferPack output;
diff --git a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
index 8c78334..3d23c23 100644
--- a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
+++ b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
@@ -38,13 +38,13 @@
     ~C2BufferTest() = default;
 
     void allocateLinear(size_t capacity) {
-        C2Status err = mLinearAllocator->allocateLinearBuffer(
+        C2Status err = mLinearAllocator->newLinearAllocation(
                 capacity,
                 { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
                 &mLinearAllocation);
         if (err != C2_OK) {
             mLinearAllocation.reset();
-            FAIL() << "C2Allocator::allocateLinearBuffer() failed: " << err;
+            FAIL() << "C2Allocator::newLinearAllocation() failed: " << err;
         }
     }
 
@@ -77,12 +77,12 @@
         mAddr = nullptr;
     }
 
-    std::shared_ptr<C2BlockAllocator> makeLinearBlockAllocator() {
-        return std::make_shared<C2DefaultBlockAllocator>(mLinearAllocator);
+    std::shared_ptr<C2BlockPool> makeLinearBlockPool() {
+        return std::make_shared<C2BasicLinearBlockPool>(mLinearAllocator);
     }
 
     void allocateGraphic(uint32_t width, uint32_t height) {
-        C2Status err = mGraphicAllocator->allocateGraphicBuffer(
+        C2Status err = mGraphicAllocator->newGraphicAllocation(
                 width,
                 height,
                 HAL_PIXEL_FORMAT_YCBCR_420_888,
@@ -90,7 +90,7 @@
                 &mGraphicAllocation);
         if (err != C2_OK) {
             mGraphicAllocation.reset();
-            FAIL() << "C2Allocator::allocateLinearBuffer() failed: " << err;
+            FAIL() << "C2Allocator::newGraphicAllocation() failed: " << err;
         }
     }
 
@@ -118,8 +118,8 @@
         ASSERT_EQ(C2_OK, mGraphicAllocation->unmap(nullptr));
     }
 
-    std::shared_ptr<C2BlockAllocator> makeGraphicBlockAllocator() {
-        return std::make_shared<C2DefaultGraphicBlockAllocator>(mGraphicAllocator);
+    std::shared_ptr<C2BlockPool> makeGraphicBlockPool() {
+        return std::make_shared<C2BasicGraphicBlockPool>(mGraphicAllocator);
     }
 
 private:
@@ -155,13 +155,13 @@
     }
 }
 
-TEST_F(C2BufferTest, BlockAllocatorTest) {
+TEST_F(C2BufferTest, BlockPoolTest) {
     constexpr size_t kCapacity = 1024u * 1024u;
 
-    std::shared_ptr<C2BlockAllocator> blockAllocator(makeLinearBlockAllocator());
+    std::shared_ptr<C2BlockPool> blockPool(makeLinearBlockPool());
 
     std::shared_ptr<C2LinearBlock> block;
-    ASSERT_EQ(C2_OK, blockAllocator->allocateLinearBlock(
+    ASSERT_EQ(C2_OK, blockPool->fetchLinearBlock(
             kCapacity,
             { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
             &block));
@@ -285,14 +285,14 @@
     ASSERT_TRUE(verifyPlane({ 0, 0, kWidth / 4, kHeight }, vInfo, v, 0));
 }
 
-TEST_F(C2BufferTest, GraphicBlockAllocatorTest) {
+TEST_F(C2BufferTest, GraphicBlockPoolTest) {
     constexpr uint32_t kWidth = 320;
     constexpr uint32_t kHeight = 240;
 
-    std::shared_ptr<C2BlockAllocator> blockAllocator(makeGraphicBlockAllocator());
+    std::shared_ptr<C2BlockPool> blockPool(makeGraphicBlockPool());
 
     std::shared_ptr<C2GraphicBlock> block;
-    ASSERT_EQ(C2_OK, blockAllocator->allocateGraphicBlock(
+    ASSERT_EQ(C2_OK, blockPool->fetchGraphicBlock(
             kWidth,
             kHeight,
             HAL_PIXEL_FORMAT_YCBCR_420_888,
@@ -370,8 +370,8 @@
 };
 
 TEST_F(C2BufferTest, BufferDataTest) {
-    std::shared_ptr<C2BlockAllocator> linearBlockAllocator(makeLinearBlockAllocator());
-    std::shared_ptr<C2BlockAllocator> graphicBlockAllocator(makeGraphicBlockAllocator());
+    std::shared_ptr<C2BlockPool> linearBlockPool(makeLinearBlockPool());
+    std::shared_ptr<C2BlockPool> graphicBlockPool(makeGraphicBlockPool());
 
     constexpr uint32_t kWidth1 = 320;
     constexpr uint32_t kHeight1 = 240;
@@ -384,23 +384,23 @@
 
     std::shared_ptr<C2LinearBlock> linearBlock1;
     std::shared_ptr<C2LinearBlock> linearBlock2;
-    ASSERT_EQ(C2_OK, linearBlockAllocator->allocateLinearBlock(
+    ASSERT_EQ(C2_OK, linearBlockPool->fetchLinearBlock(
             kCapacity1,
             { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
             &linearBlock1));
-    ASSERT_EQ(C2_OK, linearBlockAllocator->allocateLinearBlock(
+    ASSERT_EQ(C2_OK, linearBlockPool->fetchLinearBlock(
             kCapacity2,
             { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
             &linearBlock2));
     std::shared_ptr<C2GraphicBlock> graphicBlock1;
     std::shared_ptr<C2GraphicBlock> graphicBlock2;
-    ASSERT_EQ(C2_OK, graphicBlockAllocator->allocateGraphicBlock(
+    ASSERT_EQ(C2_OK, graphicBlockPool->fetchGraphicBlock(
             kWidth1,
             kHeight1,
             HAL_PIXEL_FORMAT_YCBCR_420_888,
             { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
             &graphicBlock1));
-    ASSERT_EQ(C2_OK, graphicBlockAllocator->allocateGraphicBlock(
+    ASSERT_EQ(C2_OK, graphicBlockPool->fetchGraphicBlock(
             kWidth2,
             kHeight2,
             HAL_PIXEL_FORMAT_YCBCR_420_888,
@@ -454,11 +454,11 @@
 typedef C2GlobalParam<C2Info, C2Int32Value, kParamIndexNumber2> C2Number2Info;
 
 TEST_F(C2BufferTest, BufferTest) {
-    std::shared_ptr<C2BlockAllocator> alloc(makeLinearBlockAllocator());
+    std::shared_ptr<C2BlockPool> alloc(makeLinearBlockPool());
     constexpr size_t kCapacity = 1024u;
     std::shared_ptr<C2LinearBlock> block;
 
-    ASSERT_EQ(C2_OK, alloc->allocateLinearBlock(
+    ASSERT_EQ(C2_OK, alloc->fetchLinearBlock(
             kCapacity,
             { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
             &block));
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp b/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
index 6530cc1..3e2242b 100644
--- a/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
@@ -231,11 +231,15 @@
 public:
     Impl();
 
-    C2Status allocateGraphicBuffer(
+    id_t getId() const;
+
+    C2String getName() const;
+
+    C2Status newGraphicAllocation(
             uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
             std::shared_ptr<C2GraphicAllocation> *allocation);
 
-    C2Status recreateGraphicBuffer(
+    C2Status priorGraphicAllocation(
             const C2Handle *handle,
             std::shared_ptr<C2GraphicAllocation> *allocation);
 
@@ -256,7 +260,15 @@
     }
 }
 
-C2Status C2AllocatorGralloc::Impl::allocateGraphicBuffer(
+C2Allocator::id_t C2AllocatorGralloc::Impl::getId() const {
+    return 1; /// \todo implement ID
+}
+
+C2String C2AllocatorGralloc::Impl::getName() const {
+    return "android.allocator.gralloc";
+}
+
+C2Status C2AllocatorGralloc::Impl::newGraphicAllocation(
         uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
         std::shared_ptr<C2GraphicAllocation> *allocation) {
     // TODO: buffer usage should be determined according to |usage|
@@ -307,7 +319,7 @@
     return C2_OK;
 }
 
-C2Status C2AllocatorGralloc::Impl::recreateGraphicBuffer(
+C2Status C2AllocatorGralloc::Impl::priorGraphicAllocation(
         const C2Handle *handle,
         std::shared_ptr<C2GraphicAllocation> *allocation) {
     (void) handle;
@@ -321,16 +333,24 @@
 
 C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
 
-C2Status C2AllocatorGralloc::allocateGraphicBuffer(
-        uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
-        std::shared_ptr<C2GraphicAllocation> *allocation) {
-    return mImpl->allocateGraphicBuffer(width, height, format, usage, allocation);
+C2Allocator::id_t C2AllocatorGralloc::getId() const {
+    return mImpl->getId();
 }
 
-C2Status C2AllocatorGralloc::recreateGraphicBuffer(
+C2String C2AllocatorGralloc::getName() const {
+    return mImpl->getName();
+}
+
+C2Status C2AllocatorGralloc::newGraphicAllocation(
+        uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
+        std::shared_ptr<C2GraphicAllocation> *allocation) {
+    return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
+}
+
+C2Status C2AllocatorGralloc::priorGraphicAllocation(
         const C2Handle *handle,
         std::shared_ptr<C2GraphicAllocation> *allocation) {
-    return mImpl->recreateGraphicBuffer(handle, allocation);
+    return mImpl->priorGraphicAllocation(handle, allocation);
 }
 
 C2Status C2AllocatorGralloc::status() const {
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
index 06b4874..09df502 100644
--- a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
+++ b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
@@ -294,7 +294,15 @@
     }
 }
 
-C2Status C2AllocatorIon::allocateLinearBuffer(
+C2Allocator::id_t C2AllocatorIon::getId() const {
+    return 0; /// \todo implement ID
+}
+
+C2String C2AllocatorIon::getName() const {
+    return "android.allocator.ion";
+}
+
+C2Status C2AllocatorIon::newLinearAllocation(
         uint32_t capacity, C2MemoryUsage usage, std::shared_ptr<C2LinearAllocation> *allocation) {
     if (allocation == nullptr) {
         return C2_BAD_VALUE;
@@ -328,7 +336,7 @@
     return ret;
 }
 
-C2Status C2AllocatorIon::recreateLinearBuffer(
+C2Status C2AllocatorIon::priorLinearAllocation(
         const C2Handle *handle, std::shared_ptr<C2LinearAllocation> *allocation) {
     *allocation = nullptr;
     if (mInit != C2_OK) {
diff --git a/media/libstagefright/codec2/vndk/C2Buffer.cpp b/media/libstagefright/codec2/vndk/C2Buffer.cpp
index d3f0d70..02e2dd9 100644
--- a/media/libstagefright/codec2/vndk/C2Buffer.cpp
+++ b/media/libstagefright/codec2/vndk/C2Buffer.cpp
@@ -61,7 +61,7 @@
 
 class C2DefaultLinearBlock : public C2LinearBlock {
     using C2LinearBlock::C2LinearBlock;
-    friend class ::android::C2DefaultBlockAllocator;
+    friend class ::android::C2BasicLinearBlockPool;
 };
 
 class C2DefaultGraphicView : public C2GraphicView {
@@ -87,7 +87,7 @@
 
 class C2DefaultGraphicBlock : public C2GraphicBlock {
     using C2GraphicBlock::C2GraphicBlock;
-    friend class ::android::C2DefaultGraphicBlockAllocator;
+    friend class ::android::C2BasicGraphicBlockPool;
 };
 
 class C2DefaultBufferData : public C2BufferData {
@@ -345,18 +345,18 @@
     return mImpl->share(offset, size, fence);
 }
 
-C2DefaultBlockAllocator::C2DefaultBlockAllocator(
+C2BasicLinearBlockPool::C2BasicLinearBlockPool(
         const std::shared_ptr<C2Allocator> &allocator)
   : mAllocator(allocator) {}
 
-C2Status C2DefaultBlockAllocator::allocateLinearBlock(
+C2Status C2BasicLinearBlockPool::fetchLinearBlock(
         uint32_t capacity,
         C2MemoryUsage usage,
         std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
     block->reset();
 
     std::shared_ptr<C2LinearAllocation> alloc;
-    C2Status err = mAllocator->allocateLinearBuffer(capacity, usage, &alloc);
+    C2Status err = mAllocator->newLinearAllocation(capacity, usage, &alloc);
     if (err != C2_OK) {
         return err;
     }
@@ -575,11 +575,11 @@
     return mImpl->share(crop, fence);
 }
 
-C2DefaultGraphicBlockAllocator::C2DefaultGraphicBlockAllocator(
+C2BasicGraphicBlockPool::C2BasicGraphicBlockPool(
         const std::shared_ptr<C2Allocator> &allocator)
   : mAllocator(allocator) {}
 
-C2Status C2DefaultGraphicBlockAllocator::allocateGraphicBlock(
+C2Status C2BasicGraphicBlockPool::fetchGraphicBlock(
         uint32_t width,
         uint32_t height,
         uint32_t format,
@@ -588,7 +588,7 @@
     block->reset();
 
     std::shared_ptr<C2GraphicAllocation> alloc;
-    C2Status err = mAllocator->allocateGraphicBuffer(width, height, format, usage, &alloc);
+    C2Status err = mAllocator->newGraphicAllocation(width, height, format, usage, &alloc);
     if (err != C2_OK) {
         return err;
     }
diff --git a/media/libstagefright/codec2/vndk/C2Store.cpp b/media/libstagefright/codec2/vndk/C2Store.cpp
index 42bdf0e..f8ddfef 100644
--- a/media/libstagefright/codec2/vndk/C2Store.cpp
+++ b/media/libstagefright/codec2/vndk/C2Store.cpp
@@ -16,6 +16,7 @@
 
 #include <C2AllocatorGralloc.h>
 #include <C2AllocatorIon.h>
+#include <C2BufferPriv.h>
 #include <C2Component.h>
 #include <C2PlatformSupport.h>
 
@@ -27,7 +28,7 @@
 
 class C2PlatformAllocatorStore : public C2AllocatorStore {
 public:
-    enum ID_ : uint32_t {
+    enum : id_t {
         ION = PLATFORM_START,
         GRALLOC,
     };
@@ -35,7 +36,16 @@
     C2PlatformAllocatorStore(
         /* ionmapper */
     );
-    virtual C2Status createAllocator(ID id, std::shared_ptr<C2Allocator> *const allocator);
+
+    virtual C2Status getAllocator(id_t id, std::shared_ptr<C2Allocator> *const allocator);
+
+    virtual std::vector<std::shared_ptr<const C2Allocator::Info>> listAllocators() const {
+        return std::vector<std::shared_ptr<const C2Allocator::Info>>(); /// \todo
+    }
+
+    virtual C2String getName() const {
+        return "android.allocator-store";
+    }
 
 private:
     // returns a shared-singleton ion allocator
@@ -48,8 +58,8 @@
 C2PlatformAllocatorStore::C2PlatformAllocatorStore() {
 }
 
-C2Status C2PlatformAllocatorStore::createAllocator(
-        ID id, std::shared_ptr<C2Allocator> *const allocator) {
+C2Status C2PlatformAllocatorStore::getAllocator(
+        id_t id, std::shared_ptr<C2Allocator> *const allocator) {
     allocator->reset();
     switch (id) {
     // TODO: should we implement a generic registry for all, and use that?
@@ -100,4 +110,35 @@
     return std::make_shared<C2PlatformAllocatorStore>();
 }
 
+C2Status GetCodec2BlockPool(
+        C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
+        std::shared_ptr<C2BlockPool> *pool) {
+    pool->reset();
+    if (!component) {
+        return C2_BAD_VALUE;
+    }
+    // TODO support pre-registered block pools
+    std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
+    std::shared_ptr<C2Allocator> allocator;
+    C2Status res = C2_NOT_FOUND;
+
+    switch (id) {
+    case C2BlockPool::BASIC_LINEAR:
+        res = allocatorStore->getAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
+        if (res == OK) {
+            *pool = std::make_shared<C2BasicLinearBlockPool>(allocator);
+        }
+        break;
+    case C2BlockPool::BASIC_GRAPHIC:
+        res = allocatorStore->getAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
+        if (res == OK) {
+            *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator);
+        }
+        break;
+    default:
+        break;
+    }
+    return res;
+}
+
 } // namespace android
\ No newline at end of file
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
index 9bfd987..78d41c4 100644
--- a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
@@ -30,11 +30,19 @@
     typedef std::function<int (C2MemoryUsage, size_t,
                       /* => */ size_t*, unsigned*, unsigned*)> usage_mapper_fn;
 
-    virtual C2Status allocateGraphicBuffer(
+    virtual id_t getId() const override;
+
+    virtual C2String getName() const override;
+
+    virtual std::shared_ptr<const Info> getInfo() const override {
+        return nullptr; // \todo
+    }
+
+    virtual C2Status newGraphicAllocation(
             uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
             std::shared_ptr<C2GraphicAllocation> *allocation) override;
 
-    virtual C2Status recreateGraphicBuffer(
+    virtual C2Status priorGraphicAllocation(
             const C2Handle *handle,
             std::shared_ptr<C2GraphicAllocation> *allocation) override;
 
@@ -49,20 +57,6 @@
     Impl *mImpl;
 };
 
-#if 0
-class C2Allocation::Impl {
-public:
-    Impl() : mMapped(false), mBase(nullptr) { }
-    uint8_t* base() { return mMapped ? mBase : nullptr; }
-
-    // TODO: call map...
-
-private:
-    bool mMapped;
-    uint8_t *mBase;
-};
-#endif
-
 } // namespace android
 
 #endif // STAGEFRIGHT_CODEC2_ALLOCATOR_GRALLOC_H_
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
index 00c33fe..2fff91f 100644
--- a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
@@ -29,11 +29,19 @@
     typedef std::function<int (C2MemoryUsage, size_t,
                       /* => */ size_t*, unsigned*, unsigned*)> usage_mapper_fn;
 
-    virtual C2Status allocateLinearBuffer(
+    virtual id_t getId() const override;
+
+    virtual C2String getName() const override;
+
+    virtual std::shared_ptr<const Info> getInfo() const override {
+        return nullptr; // \todo
+    }
+
+    virtual C2Status newLinearAllocation(
             uint32_t capacity, C2MemoryUsage usage,
             std::shared_ptr<C2LinearAllocation> *allocation) override;
 
-    virtual C2Status recreateLinearBuffer(
+    virtual C2Status priorLinearAllocation(
             const C2Handle *handle,
             std::shared_ptr<C2LinearAllocation> *allocation) override;
 
diff --git a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
index f1e8acb..56b0123 100644
--- a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
+++ b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
@@ -23,29 +23,46 @@
 
 namespace android {
 
-class C2DefaultBlockAllocator : public C2BlockAllocator {
+class C2BasicLinearBlockPool : public C2BlockPool {
 public:
-    explicit C2DefaultBlockAllocator(const std::shared_ptr<C2Allocator> &allocator);
+    explicit C2BasicLinearBlockPool(const std::shared_ptr<C2Allocator> &allocator);
 
-    virtual ~C2DefaultBlockAllocator() = default;
+    virtual ~C2BasicLinearBlockPool() = default;
 
-    virtual C2Status allocateLinearBlock(
+    virtual C2Allocator::id_t getAllocatorId() const override {
+        return mAllocator->getId();
+    }
+
+    virtual local_id_t getLocalId() const override {
+        return BASIC_LINEAR;
+    }
+
+    virtual C2Status fetchLinearBlock(
             uint32_t capacity,
             C2MemoryUsage usage,
             std::shared_ptr<C2LinearBlock> *block /* nonnull */) override;
 
-    // TODO:
+    // TODO: fetchCircularBlock
+
 private:
     const std::shared_ptr<C2Allocator> mAllocator;
 };
 
-class C2DefaultGraphicBlockAllocator : public C2BlockAllocator {
+class C2BasicGraphicBlockPool : public C2BlockPool {
 public:
-    explicit C2DefaultGraphicBlockAllocator(const std::shared_ptr<C2Allocator> &allocator);
+    explicit C2BasicGraphicBlockPool(const std::shared_ptr<C2Allocator> &allocator);
 
-    virtual ~C2DefaultGraphicBlockAllocator() = default;
+    virtual ~C2BasicGraphicBlockPool() = default;
 
-    virtual C2Status allocateGraphicBlock(
+    virtual C2Allocator::id_t getAllocatorId() const override {
+        return mAllocator->getId();
+    }
+
+    virtual local_id_t getLocalId() const override {
+        return BASIC_GRAPHIC;
+    }
+
+    virtual C2Status fetchGraphicBlock(
             uint32_t width,
             uint32_t height,
             uint32_t format,
@@ -56,21 +73,6 @@
     const std::shared_ptr<C2Allocator> mAllocator;
 };
 
-
-#if 0
-class C2Allocation::Impl {
-public:
-    Impl() : mMapped(false), mBase(nullptr) { }
-    uint8_t* base() { return mMapped ? mBase : nullptr; }
-
-    // TODO: call map...
-
-private:
-    bool mMapped;
-    uint8_t *mBase;
-};
-#endif
-
 } // namespace android
 
 #endif // STAGEFRIGHT_CODEC2_BUFFER_PRIV_H_
diff --git a/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h b/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h
index 9402050..40bb548 100644
--- a/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h
+++ b/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h
@@ -25,9 +25,33 @@
 
 /**
  * Returns the platform allocator store.
+ * \retval nullptr if the platform allocator store could not be obtained
  */
 std::shared_ptr<C2AllocatorStore> GetCodec2PlatformAllocatorStore();
 
+/**
+ * Retrieves a block pool for a component.
+ *
+ * \param id        the local ID of the block pool
+ * \param component the component using the block pool (must be non-null)
+ * \param pool      pointer to where the obtained block pool shall be stored on success. nullptr
+ *                  will be stored here on failure
+ *
+ * \retval C2_OK        the operation was successful
+ * \retval C2_BAD_VALUE the component is null
+ * \retval C2_NOT_FOUND if the block pool does not exist
+ * \retval C2_NO_MEMORY not enough memory to fetch the block pool (this return value is only
+ *                      possible for basic pools)
+ * \retval C2_TIMED_OUT the operation timed out (this return value is only possible for basic pools)
+ * \retval C2_REFUSED   no permission to complete any required allocation (this return value is only
+ *                      possible for basic pools)
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected,
+ *                      this return value is only possible for basic pools)
+ */
+C2Status GetCodec2BlockPool(
+        C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
+        std::shared_ptr<C2BlockPool> *pool);
+
 } // namespace android
 
 #endif // STAGEFRIGHT_CODEC2_PLATFORM_SUPPORT_H_
diff --git a/media/libstagefright/codecs/avcdec/Android.bp b/media/libstagefright/codecs/avcdec/Android.bp
index 3b2602d..5dcffd5 100644
--- a/media/libstagefright/codecs/avcdec/Android.bp
+++ b/media/libstagefright/codecs/avcdec/Android.bp
@@ -74,9 +74,9 @@
         misc_undefined: [
             "signed-integer-overflow",
         ],
-        cfi: true,
+        cfi: false, // true,
         diag: {
-            cfi: true,
+            cfi: false, // true,
         },
     },
 
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
index 77db255..12eaff5 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
@@ -27,6 +27,8 @@
 #include "ih264d.h"
 #include "C2SoftAvcDec.h"
 
+#include <C2PlatformSupport.h>
+
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaDefs.h>
 #include <utils/misc.h>
@@ -275,6 +277,8 @@
     mMaxVideoSizeHint.mWidth = H264_MAX_FRAME_WIDTH;
     mMaxVideoSizeHint.mHeight = H264_MAX_FRAME_HEIGHT;
 
+    mOutputBlockPools = C2PortBlockPoolsTuning::output::alloc_unique({});
+
     auto insertParam = [&params = mParams] (C2Param *param) {
         params[restoreIndex(param)] = param;
     };
@@ -422,6 +426,8 @@
             false, "_video_size", &mVideoSize));
     mParamDescs.push_back(std::make_shared<C2ParamDescriptor>(
             false, "_max_video_size_hint", &mMaxVideoSizeHint));
+    mParamDescs.push_back(std::make_shared<C2ParamDescriptor>(
+            false, "_output_block_pools", mOutputBlockPools.get()));
 }
 
 C2String C2SoftAvcDecIntf::getName() const {
@@ -443,6 +449,8 @@
 
         uint32_t index = restoreIndex(param);
         if (!mParams.count(index)) {
+            // TODO: add support for output-block-pools (this will be done when we move all
+            // config to shared ptr)
             continue;
         }
 
@@ -471,6 +479,13 @@
     C2Status err = C2_OK;
     for (C2Param *param : params) {
         uint32_t index = restoreIndex(param);
+        if (param->index() == mOutputBlockPools.get()->index()) {
+            // setting output block pools
+            mOutputBlockPools.reset(
+                    (C2PortBlockPoolsTuning::output *)C2Param::Copy(*param).release());
+            continue;
+        }
+
         if (mParams.count(index) == 0) {
             // We can't create C2SettingResult with no field, so just skipping in this case.
             err = C2_BAD_INDEX;
@@ -1211,7 +1226,19 @@
         // TODO: format & usage
         uint32_t format = HAL_PIXEL_FORMAT_YV12;
         C2MemoryUsage usage = { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite };
-        (void) work->worklets.front()->allocators[0]->allocateGraphicBlock(
+        // TODO: lock access to interface
+        C2BlockPool::local_id_t poolId =
+            mIntf->mOutputBlockPools->flexCount() ?
+                    mIntf->mOutputBlockPools->m.mValues[0] : C2BlockPool::BASIC_GRAPHIC;
+        if (!mOutputBlockPool || mOutputBlockPool->getLocalId() != poolId) {
+            C2Status err = GetCodec2BlockPool(poolId, shared_from_this(), &mOutputBlockPool);
+            if (err != C2_OK) {
+                // TODO: trip
+            }
+        }
+        ALOGE("using allocator %u", mOutputBlockPool->getAllocatorId());
+
+        (void)mOutputBlockPool->fetchGraphicBlock(
                 mWidth, mHeight, format, usage, &mAllocatedBlock);
         ALOGE("provided (%dx%d) required (%dx%d)", mAllocatedBlock->width(), mAllocatedBlock->height(), mWidth, mHeight);
     }
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
index cc33083..41ccf39 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
@@ -118,6 +118,7 @@
     // TODO: C2StreamMimeConfig mInputStreamMime;
     // TODO: C2StreamMimeConfig mOutputStreamMime;
     C2StreamFormatConfig::input mInputStreamFormat;
+    std::unique_ptr<C2PortBlockPoolsTuning::output> mOutputBlockPools;
     C2StreamFormatConfig::output mOutputStreamFormat;
     C2VideoSizeStreamInfo::output mVideoSize;
     C2MaxVideoSizeHintPortSetting::input mMaxVideoSizeHint;
@@ -138,6 +139,7 @@
     std::vector<std::shared_ptr<C2ParamDescriptor>> mParamDescs;
 
     void updateSupportedValues();
+    friend class C2SoftAvcDec;
 };
 
 class C2SoftAvcDec
@@ -191,6 +193,7 @@
 
     const std::shared_ptr<C2SoftAvcDecIntf> mIntf;
     const std::shared_ptr<C2ComponentListener> mListener;
+    std::shared_ptr<C2BlockPool> mOutputBlockPool;
 
     std::mutex mQueueLock;
     std::condition_variable mQueueCond;
diff --git a/media/libstagefright/codecs/cmds/codec2.cpp b/media/libstagefright/codecs/cmds/codec2.cpp
index 29669aa..c7e1c82 100644
--- a/media/libstagefright/codecs/cmds/codec2.cpp
+++ b/media/libstagefright/codecs/cmds/codec2.cpp
@@ -95,9 +95,7 @@
     sp<IProducerListener> mProducerListener;
 
     std::shared_ptr<C2Allocator> mAllocIon;
-    std::shared_ptr<C2Allocator> mAllocGralloc;
-    std::shared_ptr<C2BlockAllocator> mLinearAlloc;
-    std::shared_ptr<C2BlockAllocator> mGraphicAlloc;
+    std::shared_ptr<C2BlockPool> mLinearPool;
 
     std::mutex mQueueLock;
     std::condition_variable mQueueCondition;
@@ -144,11 +142,8 @@
     CHECK_EQ(mComposerClient->initCheck(), (status_t)OK);
 
     std::shared_ptr<C2AllocatorStore> store = GetCodec2PlatformAllocatorStore();
-    CHECK_EQ(store->createAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mAllocIon), C2_OK);
-    CHECK_EQ(store->createAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &mAllocGralloc), C2_OK);
-
-    mLinearAlloc = std::make_shared<C2DefaultBlockAllocator>(mAllocIon);
-    mGraphicAlloc = std::make_shared<C2DefaultGraphicBlockAllocator>(mAllocGralloc);
+    CHECK_EQ(store->getAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mAllocIon), C2_OK);
+    mLinearPool = std::make_shared<C2BasicLinearBlockPool>(mAllocIon);
 
     mControl = mComposerClient->createSurface(
             String8("A Surface"),
@@ -214,6 +209,10 @@
     }
 
     std::shared_ptr<C2Component> component(std::make_shared<C2SoftAvcDec>("avc", 0, mListener));
+    std::unique_ptr<C2PortBlockPoolsTuning::output> pools =
+        C2PortBlockPoolsTuning::output::alloc_unique({ (uint64_t)C2BlockPool::BASIC_GRAPHIC });
+    std::vector<std::unique_ptr<C2SettingResult>> result;
+    (void)component->intf()->config_nb({pools.get()}, &result);
     component->start();
 
     for (int i = 0; i < 8; ++i) {
@@ -274,7 +273,7 @@
     });
 
     long numFrames = 0;
-    mLinearAlloc.reset(new C2DefaultBlockAllocator(mAllocIon));
+    mLinearPool.reset(new C2BasicLinearBlockPool(mAllocIon));
 
     for (;;) {
         size_t size = 0u;
@@ -328,7 +327,7 @@
         work->input.ordinal.frame_index = numFrames;
 
         std::shared_ptr<C2LinearBlock> block;
-        mLinearAlloc->allocateLinearBlock(
+        mLinearPool->fetchLinearBlock(
                 size,
                 { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
                 &block);
@@ -343,7 +342,6 @@
         work->input.buffers.emplace_back(new LinearBuffer(block));
         work->worklets.clear();
         work->worklets.emplace_back(new C2Worklet);
-        work->worklets.front()->allocators.emplace_back(mGraphicAlloc);
 
         std::list<std::unique_ptr<C2Work>> items;
         items.push_back(std::move(work));
diff --git a/media/libstagefright/include/OmxNodeOwner.h b/media/libstagefright/include/OmxNodeOwner.h
deleted file mode 100644
index 64ec7f7..0000000
--- a/media/libstagefright/include/OmxNodeOwner.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2016 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 OMX_NODE_OWNER_H_
-
-#define OMX_NODE_OWNER_H_
-
-namespace android {
-
-struct OMXNodeInstance;
-
-/**
- * This struct is needed to separate OMX from OMXNodeInstance.
- *
- * TODO: This might not be needed after Treble transition is complete.
- */
-struct OmxNodeOwner {
-    virtual status_t freeNode(const sp<OMXNodeInstance> &instance) = 0;
-    virtual ~OmxNodeOwner() {}
-};
-
-}
-
-#endif  // OMX_NODE_OWNER_H_
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index 424246d..d1a9d25 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -95,11 +95,6 @@
 
     static status_t getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]);
 
-    // Save the flag.
-    void setTrebleFlag(bool trebleFlag);
-    // Return the saved flag.
-    bool getTrebleFlag() const;
-
 protected:
     virtual ~ACodec();
 
@@ -233,9 +228,7 @@
     sp<IOMX> mOMX;
     sp<IOMXNode> mOMXNode;
     int32_t mNodeGeneration;
-    bool mTrebleFlag;
     sp<TAllocator> mAllocator[2];
-    sp<MemoryDealer> mDealer[2];
 
     bool mUsingNativeWindow;
     sp<ANativeWindow> mNativeWindow;
diff --git a/media/libstagefright/include/media/stagefright/OMXClient.h b/media/libstagefright/include/media/stagefright/OMXClient.h
index b1864b8..bb133d3 100644
--- a/media/libstagefright/include/media/stagefright/OMXClient.h
+++ b/media/libstagefright/include/media/stagefright/OMXClient.h
@@ -18,25 +18,19 @@
 
 #define OMX_CLIENT_H_
 
-#include <media/IOMX.h>
-
 namespace android {
 
+class IOMX;
+
 class OMXClient {
 public:
     OMXClient();
 
     status_t connect();
-    status_t connect(bool* trebleFlag);
-    status_t connect(const char* name, bool* trebleFlag = nullptr);
-
-    status_t connectLegacy();
-    status_t connectTreble(const char* name = "default");
+    status_t connect(const char* name);
     void disconnect();
 
-    sp<IOMX> interface() {
-        return mOMX;
-    }
+    sp<IOMX> interface();
 
 private:
     sp<IOMX> mOMX;
diff --git a/media/libstagefright/omx/Android.bp b/media/libstagefright/omx/Android.bp
index f388a48..8539864 100644
--- a/media/libstagefright/omx/Android.bp
+++ b/media/libstagefright/omx/Android.bp
@@ -9,8 +9,6 @@
         "FrameDropper.cpp",
         "GraphicBufferSource.cpp",
         "BWGraphicBufferSource.cpp",
-        "OMX.cpp",
-        "OMXStore.cpp",
         "OMXMaster.cpp",
         "OMXNodeInstance.cpp",
         "OMXUtils.cpp",
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
deleted file mode 100644
index 09c4019..0000000
--- a/media/libstagefright/omx/OMX.cpp
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <inttypes.h>
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "OMX"
-#include <utils/Log.h>
-
-#include <dlfcn.h>
-
-#include <media/stagefright/omx/OMX.h>
-#include <media/stagefright/omx/OMXNodeInstance.h>
-#include <media/stagefright/omx/BWGraphicBufferSource.h>
-#include <media/stagefright/omx/OMXMaster.h>
-#include <media/stagefright/omx/OMXUtils.h>
-#include <media/stagefright/foundation/ADebug.h>
-
-namespace android {
-
-// node ids are created by concatenating the pid with a 16-bit counter
-static size_t kMaxNodeInstances = (1 << 16);
-
-OMX::OMX() : mMaster(new OMXMaster), mParser() {
-}
-
-OMX::~OMX() {
-    delete mMaster;
-    mMaster = NULL;
-}
-
-void OMX::binderDied(const wp<IBinder> &the_late_who) {
-    sp<OMXNodeInstance> instance;
-
-    {
-        Mutex::Autolock autoLock(mLock);
-
-        ssize_t index = mLiveNodes.indexOfKey(the_late_who);
-
-        if (index < 0) {
-            ALOGE("b/27597103, nonexistent observer on binderDied");
-            android_errorWriteLog(0x534e4554, "27597103");
-            return;
-        }
-
-        instance = mLiveNodes.editValueAt(index);
-        mLiveNodes.removeItemsAt(index);
-    }
-
-    instance->onObserverDied();
-}
-
-status_t OMX::listNodes(List<ComponentInfo> *list) {
-    list->clear();
-
-    OMX_U32 index = 0;
-    char componentName[256];
-    while (mMaster->enumerateComponents(
-                componentName, sizeof(componentName), index) == OMX_ErrorNone) {
-        list->push_back(ComponentInfo());
-        ComponentInfo &info = *--list->end();
-
-        info.mName = componentName;
-
-        Vector<String8> roles;
-        OMX_ERRORTYPE err =
-            mMaster->getRolesOfComponent(componentName, &roles);
-
-        if (err == OMX_ErrorNone) {
-            for (OMX_U32 i = 0; i < roles.size(); ++i) {
-                info.mRoles.push_back(roles[i]);
-            }
-        }
-
-        ++index;
-    }
-
-    return OK;
-}
-
-status_t OMX::allocateNode(
-        const char *name, const sp<IOMXObserver> &observer,
-        sp<IOMXNode> *omxNode) {
-    Mutex::Autolock autoLock(mLock);
-
-    omxNode->clear();
-
-    if (mLiveNodes.size() == kMaxNodeInstances) {
-        return NO_MEMORY;
-    }
-
-    sp<OMXNodeInstance> instance = new OMXNodeInstance(this, observer, name);
-
-    OMX_COMPONENTTYPE *handle;
-    OMX_ERRORTYPE err = mMaster->makeComponentInstance(
-            name, &OMXNodeInstance::kCallbacks,
-            instance.get(), &handle);
-
-    if (err != OMX_ErrorNone) {
-        ALOGE("FAILED to allocate omx component '%s' err=%s(%#x)", name, asString(err), err);
-
-        return StatusFromOMXError(err);
-    }
-    instance->setHandle(handle);
-
-    // Find quirks from mParser
-    const auto& codec = mParser.getCodecMap().find(name);
-    if (codec == mParser.getCodecMap().cend()) {
-        ALOGW("Failed to obtain quirks for omx component '%s' from XML files",
-                name);
-    } else {
-        uint32_t quirks = 0;
-        for (const auto& quirk : codec->second.quirkSet) {
-            if (quirk == "requires-allocate-on-input-ports") {
-                quirks |= OMXNodeInstance::
-                        kRequiresAllocateBufferOnInputPorts;
-            }
-            if (quirk == "requires-allocate-on-output-ports") {
-                quirks |= OMXNodeInstance::
-                        kRequiresAllocateBufferOnOutputPorts;
-            }
-        }
-        instance->setQuirks(quirks);
-    }
-
-    mLiveNodes.add(IInterface::asBinder(observer), instance);
-    IInterface::asBinder(observer)->linkToDeath(this);
-
-    *omxNode = instance;
-
-    return OK;
-}
-
-status_t OMX::freeNode(const sp<OMXNodeInstance> &instance) {
-    if (instance == NULL) {
-        return OK;
-    }
-
-    {
-        Mutex::Autolock autoLock(mLock);
-        ssize_t index = mLiveNodes.indexOfKey(IInterface::asBinder(instance->observer()));
-        if (index < 0) {
-            // This could conceivably happen if the observer dies at roughly the
-            // same time that a client attempts to free the node explicitly.
-
-            // NOTE: it's guaranteed that this method is called at most once per
-            //       instance.
-            ALOGV("freeNode: instance already removed from book-keeping.");
-        } else {
-            mLiveNodes.removeItemsAt(index);
-            IInterface::asBinder(instance->observer())->unlinkToDeath(this);
-        }
-    }
-
-    CHECK(instance->handle() != NULL);
-    OMX_ERRORTYPE err = mMaster->destroyComponentInstance(
-            static_cast<OMX_COMPONENTTYPE *>(instance->handle()));
-    ALOGV("freeNode: handle destroyed: %p", instance->handle());
-
-    return StatusFromOMXError(err);
-}
-
-status_t OMX::createInputSurface(
-        sp<IGraphicBufferProducer> *bufferProducer,
-        sp<IGraphicBufferSource> *bufferSource) {
-    if (bufferProducer == NULL || bufferSource == NULL) {
-        ALOGE("b/25884056");
-        return BAD_VALUE;
-    }
-
-    sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource();
-    status_t err = graphicBufferSource->initCheck();
-    if (err != OK) {
-        ALOGE("Failed to create persistent input surface: %s (%d)",
-                strerror(-err), err);
-        return err;
-    }
-
-    *bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
-    *bufferSource = new BWGraphicBufferSource(graphicBufferSource);
-
-    return OK;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 015a148..ff58eb6 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -344,7 +344,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 OMXNodeInstance::OMXNodeInstance(
-        OmxNodeOwner *owner, const sp<IOMXObserver> &observer, const char *name)
+        Omx *owner, const sp<IOMXObserver> &observer, const char *name)
     : mOwner(owner),
       mHandle(NULL),
       mObserver(observer),
diff --git a/media/libstagefright/omx/OMXStore.cpp b/media/libstagefright/omx/OMXStore.cpp
deleted file mode 100644
index 345336d..0000000
--- a/media/libstagefright/omx/OMXStore.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2009 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 "OMXStore"
-#include <utils/Log.h>
-
-#include <media/stagefright/omx/OMXUtils.h>
-#include <media/stagefright/omx/OMX.h>
-#include <media/stagefright/omx/OMXStore.h>
-#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
-
-#include <map>
-#include <string>
-
-namespace android {
-
-namespace {
-    struct RoleProperties {
-        std::string type;
-        bool isEncoder;
-        bool preferPlatformNodes;
-        std::multimap<size_t, IOMXStore::NodeInfo> nodeList;
-    };
-}  // Unnamed namespace
-
-OMXStore::OMXStore(
-        const char* owner,
-        const char* const* searchDirs,
-        const char* mainXmlName,
-        const char* performanceXmlName,
-        const char* profilingResultsXmlPath) {
-    MediaCodecsXmlParser parser(
-            searchDirs,
-            mainXmlName,
-            performanceXmlName,
-            profilingResultsXmlPath);
-    mParsingStatus = parser.getParsingStatus();
-
-    const auto& serviceAttributeMap = parser.getServiceAttributeMap();
-    mServiceAttributeList.reserve(serviceAttributeMap.size());
-    for (const auto& attributePair : serviceAttributeMap) {
-        Attribute attribute;
-        attribute.key = attributePair.first;
-        attribute.value = attributePair.second;
-        mServiceAttributeList.push_back(std::move(attribute));
-    }
-
-    const auto& roleMap = parser.getRoleMap();
-    mRoleList.reserve(roleMap.size());
-    for (const auto& rolePair : roleMap) {
-        RoleInfo role;
-        role.role = rolePair.first;
-        role.type = rolePair.second.type;
-        role.isEncoder = rolePair.second.isEncoder;
-        // TODO: Currently, preferPlatformNodes information is not available in
-        // the xml file. Once we have a way to provide this information, it
-        // should be parsed properly.
-        role.preferPlatformNodes = rolePair.first.compare(0, 5, "audio") == 0;
-        std::vector<NodeInfo>& nodeList = role.nodes;
-        nodeList.reserve(rolePair.second.nodeList.size());
-        for (const auto& nodePair : rolePair.second.nodeList) {
-            NodeInfo node;
-            node.name = nodePair.second.name;
-            node.owner = owner;
-            std::vector<Attribute>& attributeList = node.attributes;
-            attributeList.reserve(nodePair.second.attributeList.size());
-            for (const auto& attributePair : nodePair.second.attributeList) {
-                Attribute attribute;
-                attribute.key = attributePair.first;
-                attribute.value = attributePair.second;
-                attributeList.push_back(std::move(attribute));
-            }
-            nodeList.push_back(std::move(node));
-        }
-        mRoleList.push_back(std::move(role));
-    }
-
-    mPrefix = parser.getCommonPrefix();
-}
-
-status_t OMXStore::listServiceAttributes(std::vector<Attribute>* attributes) {
-    *attributes = mServiceAttributeList;
-    return mParsingStatus;
-}
-
-status_t OMXStore::getNodePrefix(std::string* prefix) {
-    *prefix = mPrefix;
-    return mParsingStatus;
-}
-
-status_t OMXStore::listRoles(std::vector<RoleInfo>* roleList) {
-    *roleList = mRoleList;
-    return mParsingStatus;
-}
-
-status_t OMXStore::getOmx(const std::string& name, sp<IOMX>* omx) {
-    *omx = new OMX();
-    return NO_ERROR;
-}
-
-OMXStore::~OMXStore() {
-}
-
-}  // namespace android
-
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h b/media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h
index a6a9d3e..baa7b81 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h
@@ -20,13 +20,13 @@
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
 
-#include <media/stagefright/omx/OMXNodeInstance.h>
 #include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
 #include <android/hardware/media/omx/1.0/IOmx.h>
 
 namespace android {
 
 struct OMXMaster;
+struct OMXNodeInstance;
 
 namespace hardware {
 namespace media {
@@ -50,10 +50,9 @@
 using ::android::wp;
 
 using ::android::OMXMaster;
-using ::android::OmxNodeOwner;
 using ::android::OMXNodeInstance;
 
-struct Omx : public IOmx, public hidl_death_recipient, public OmxNodeOwner {
+struct Omx : public IOmx, public hidl_death_recipient {
     Omx();
     virtual ~Omx();
 
@@ -68,8 +67,8 @@
     // Method from hidl_death_recipient
     void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
 
-    // Method from OmxNodeOwner
-    virtual status_t freeNode(sp<OMXNodeInstance> const& instance) override;
+    // Method for OMXNodeInstance
+    status_t freeNode(sp<OMXNodeInstance> const& instance);
 
 protected:
     OMXMaster* mMaster;
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/OMX.h b/media/libstagefright/omx/include/media/stagefright/omx/OMX.h
deleted file mode 100644
index 594b4c0..0000000
--- a/media/libstagefright/omx/include/media/stagefright/omx/OMX.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2009 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_OMX_H_
-#define ANDROID_OMX_H_
-
-#include <media/IOMX.h>
-#include <utils/threads.h>
-#include <utils/KeyedVector.h>
-#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
-#include "OmxNodeOwner.h"
-
-namespace android {
-
-struct OMXMaster;
-struct OMXNodeInstance;
-
-class OMX : public BnOMX,
-            public OmxNodeOwner,
-            public IBinder::DeathRecipient {
-public:
-    OMX();
-
-    virtual status_t listNodes(List<ComponentInfo> *list);
-
-    virtual status_t allocateNode(
-            const char *name, const sp<IOMXObserver> &observer,
-            sp<IOMXNode> *omxNode);
-
-    virtual status_t createInputSurface(
-            sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferSource> *bufferSource);
-
-    virtual void binderDied(const wp<IBinder> &the_late_who);
-
-    virtual status_t freeNode(const sp<OMXNodeInstance>& instance);
-
-protected:
-    virtual ~OMX();
-
-private:
-    Mutex mLock;
-    OMXMaster *mMaster;
-    MediaCodecsXmlParser mParser;
-
-    KeyedVector<wp<IBinder>, sp<OMXNodeInstance> > mLiveNodes;
-
-    OMX(const OMX &);
-    OMX &operator=(const OMX &);
-};
-
-}  // namespace android
-
-#endif  // ANDROID_OMX_H_
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h b/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
index 1065ca5..c436121 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
@@ -25,9 +25,9 @@
 #include <utils/threads.h>
 #include <utils/KeyedVector.h>
 #include <utils/SortedVector.h>
-#include "OmxNodeOwner.h"
 
 #include <android/hidl/memory/1.0/IMemory.h>
+#include <media/stagefright/omx/1.0/Omx.h>
 
 namespace android {
 class GraphicBuffer;
@@ -35,11 +35,12 @@
 class IOMXObserver;
 struct OMXMaster;
 class OMXBuffer;
-typedef hidl::memory::V1_0::IMemory IHidlMemory;
+using IHidlMemory = hidl::memory::V1_0::IMemory;
+using hardware::media::omx::V1_0::implementation::Omx;
 
 struct OMXNodeInstance : public BnOMXNode {
     OMXNodeInstance(
-            OmxNodeOwner *owner, const sp<IOMXObserver> &observer, const char *name);
+            Omx *owner, const sp<IOMXObserver> &observer, const char *name);
 
     void setHandle(OMX_HANDLETYPE handle);
 
@@ -122,7 +123,7 @@
 
     Mutex mLock;
 
-    OmxNodeOwner *mOwner;
+    Omx *mOwner;
     OMX_HANDLETYPE mHandle;
     sp<IOMXObserver> mObserver;
     sp<CallbackDispatcher> mDispatcher;
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/OMXStore.h b/media/libstagefright/omx/include/media/stagefright/omx/OMXStore.h
deleted file mode 100644
index e00d713..0000000
--- a/media/libstagefright/omx/include/media/stagefright/omx/OMXStore.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2009 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_OMXSTORE_H_
-#define ANDROID_OMXSTORE_H_
-
-#include <media/IOMXStore.h>
-#include <media/IOMX.h>
-#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
-
-#include <vector>
-#include <string>
-
-namespace android {
-
-class OMXStore : public BnOMXStore {
-public:
-    OMXStore(
-            const char* owner = "default",
-            const char* const* searchDirs
-                = MediaCodecsXmlParser::defaultSearchDirs,
-            const char* mainXmlName
-                = MediaCodecsXmlParser::defaultMainXmlName,
-            const char* performanceXmlName
-                = MediaCodecsXmlParser::defaultPerformanceXmlName,
-            const char* profilingResultsXmlPath
-                = MediaCodecsXmlParser::defaultProfilingResultsXmlPath);
-
-    status_t listServiceAttributes(
-            std::vector<Attribute>* attributes) override;
-
-    status_t getNodePrefix(std::string* prefix) override;
-
-    status_t listRoles(std::vector<RoleInfo>* roleList) override;
-
-    status_t getOmx(const std::string& name, sp<IOMX>* omx) override;
-
-    ~OMXStore() override;
-
-protected:
-    status_t mParsingStatus;
-    std::string mPrefix;
-    std::vector<Attribute> mServiceAttributeList;
-    std::vector<RoleInfo> mRoleList;
-};
-
-}  // namespace android
-
-#endif  // ANDROID_OMXSTORE_H_
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 8092887..86c7211 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -25,11 +25,9 @@
 
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
-#include <binder/MemoryDealer.h>
 #include <cutils/properties.h>
 #include <media/DataSource.h>
 #include <media/IMediaHTTPService.h>
-#include <media/IMediaCodecService.h>
 #include <media/MediaExtractor.h>
 #include <media/MediaSource.h>
 #include <media/OMXBuffer.h>
@@ -71,7 +69,7 @@
 /////////////////////////////////////////////////////////////////////
 
 Harness::Harness()
-    : mInitCheck(NO_INIT), mUseTreble(false) {
+    : mInitCheck(NO_INIT) {
     mInitCheck = initOMX();
 }
 
@@ -83,21 +81,12 @@
 }
 
 status_t Harness::initOMX() {
-    if (property_get_bool("persist.media.treble_omx", true)) {
-        using namespace ::android::hardware::media::omx::V1_0;
-        sp<IOmx> tOmx = IOmx::getService();
-        if (tOmx == nullptr) {
-            return NO_INIT;
-        }
-        mOMX = new utils::LWOmx(tOmx);
-        mUseTreble = true;
-    } else {
-        sp<IServiceManager> sm = defaultServiceManager();
-        sp<IBinder> binder = sm->getService(String16("media.codec"));
-        sp<IMediaCodecService> service = interface_cast<IMediaCodecService>(binder);
-        mOMX = service->getOMX();
-        mUseTreble = false;
+    using namespace ::android::hardware::media::omx::V1_0;
+    sp<IOmx> tOmx = IOmx::getService();
+    if (tOmx == nullptr) {
+        return NO_INIT;
     }
+    mOMX = new utils::LWOmx(tOmx);
 
     return mOMX != 0 ? OK : NO_INIT;
 }
@@ -225,25 +214,19 @@
     for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
         Buffer buffer;
         buffer.mFlags = 0;
-        if (mUseTreble) {
-            bool success;
-            auto transStatus = mAllocator->allocate(def.nBufferSize,
-                    [&success, &buffer](
-                            bool s,
-                            hidl_memory const& m) {
-                        success = s;
-                        buffer.mHidlMemory = m;
-                    });
-            EXPECT(transStatus.isOk(),
-                    "Cannot call allocator");
-            EXPECT(success,
-                    "Cannot allocate memory");
-            err = mOMXNode->useBuffer(portIndex, buffer.mHidlMemory, &buffer.mID);
-        } else {
-            buffer.mMemory = mDealer->allocate(def.nBufferSize);
-            CHECK(buffer.mMemory != NULL);
-            err = mOMXNode->useBuffer(portIndex, buffer.mMemory, &buffer.mID);
-        }
+        bool success;
+        auto transStatus = mAllocator->allocate(def.nBufferSize,
+                [&success, &buffer](
+                        bool s,
+                        hidl_memory const& m) {
+                    success = s;
+                    buffer.mHidlMemory = m;
+                });
+        EXPECT(transStatus.isOk(),
+                "Cannot call allocator");
+        EXPECT(success,
+                "Cannot allocate memory");
+        err = mOMXNode->useBuffer(portIndex, buffer.mHidlMemory, &buffer.mID);
 
         EXPECT_SUCCESS(err, "useBuffer");
 
@@ -312,13 +295,11 @@
         return OK;
     }
 
-    if (mUseTreble) {
-        mAllocator = IAllocator::getService("ashmem");
-        EXPECT(mAllocator != nullptr,
-                "Cannot obtain hidl AshmemAllocator");
-    } else {
-        mDealer = new MemoryDealer(16 * 1024 * 1024, "OMXHarness");
-    }
+    mAllocator = IAllocator::getService("ashmem");
+    EXPECT(mAllocator != nullptr,
+            "Cannot obtain hidl AshmemAllocator");
+    // TODO: When Treble has MemoryHeap/MemoryDealer, we should specify the heap
+    // size to be 16 * 1024 * 1024.
 
     sp<CodecObserver> observer = new CodecObserver(this, ++mCurGeneration);
 
diff --git a/media/libstagefright/omx/tests/OMXHarness.h b/media/libstagefright/omx/tests/OMXHarness.h
index 4fc0f79..dca787c 100644
--- a/media/libstagefright/omx/tests/OMXHarness.h
+++ b/media/libstagefright/omx/tests/OMXHarness.h
@@ -93,8 +93,6 @@
     Condition mMessageAddedCondition;
     int32_t mLastMsgGeneration;
     int32_t mCurGeneration;
-    bool mUseTreble;
-    sp<MemoryDealer> mDealer;
     sp<IAllocator> mAllocator;
 
     status_t initOMX();
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 79e540a..9cb0357 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -641,38 +641,52 @@
 
 // IAudioFlinger interface
 
-
-sp<IAudioTrack> AudioFlinger::createTrack(
-        audio_stream_type_t streamType,
-        uint32_t sampleRate,
-        audio_format_t format,
-        audio_channel_mask_t channelMask,
-        size_t *frameCount,
-        audio_output_flags_t *flags,
-        const sp<IMemory>& sharedBuffer,
-        audio_io_handle_t output,
-        pid_t pid,
-        pid_t tid,
-        audio_session_t *sessionId,
-        int clientUid,
-        status_t *status,
-        audio_port_handle_t portId)
+sp<IAudioTrack> AudioFlinger::createTrack(const CreateTrackInput& input,
+                                          CreateTrackOutput& output,
+                                          status_t *status)
 {
     sp<PlaybackThread::Track> track;
     sp<TrackHandle> trackHandle;
     sp<Client> client;
     status_t lStatus;
-    audio_session_t lSessionId;
+    audio_stream_type_t streamType;
+    audio_port_handle_t portId;
 
+    bool updatePid = (input.clientInfo.clientPid == -1);
     const uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    if (pid == -1 || !isTrustedCallingUid(callingUid)) {
+    uid_t clientUid = input.clientInfo.clientUid;
+    if (!isTrustedCallingUid(callingUid)) {
+        ALOGW_IF(clientUid != callingUid,
+                "%s uid %d tried to pass itself off as %d",
+                __FUNCTION__, callingUid, clientUid);
+        clientUid = callingUid;
+        updatePid = true;
+    }
+    pid_t clientPid = input.clientInfo.clientPid;
+    if (updatePid) {
         const pid_t callingPid = IPCThreadState::self()->getCallingPid();
-        ALOGW_IF(pid != -1 && pid != callingPid,
+        ALOGW_IF(clientPid != -1 && clientPid != callingPid,
                  "%s uid %d pid %d tried to pass itself off as pid %d",
-                 __func__, callingUid, callingPid, pid);
-        pid = callingPid;
+                 __func__, callingUid, callingPid, clientPid);
+        clientPid = callingPid;
     }
 
+    audio_session_t sessionId = input.sessionId;
+    if (sessionId == AUDIO_SESSION_ALLOCATE) {
+        sessionId = (audio_session_t) newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+    }
+    output.sessionId = sessionId;
+    output.outputId = AUDIO_IO_HANDLE_NONE;
+    output.selectedDeviceId = input.selectedDeviceId;
+
+    lStatus = AudioSystem::getOutputForAttr(&input.attr, &output.outputId, sessionId, &streamType,
+                                            clientUid, &input.config, input.flags,
+                                            &output.selectedDeviceId, &portId);
+
+    if (lStatus != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
+        ALOGE("createTrack() getOutputForAttr() return error %d or invalid output handle", lStatus);
+        goto Exit;
+    }
     // client AudioTrack::set already implements AUDIO_STREAM_DEFAULT => AUDIO_STREAM_MUSIC,
     // but if someone uses binder directly they could bypass that and cause us to crash
     if (uint32_t(streamType) >= AUDIO_STREAM_CNT) {
@@ -681,91 +695,76 @@
         goto Exit;
     }
 
-    // further sample rate checks are performed by createTrack_l() depending on the thread type
-    if (sampleRate == 0) {
-        ALOGE("createTrack() invalid sample rate %u", sampleRate);
-        lStatus = BAD_VALUE;
-        goto Exit;
-    }
-
     // further channel mask checks are performed by createTrack_l() depending on the thread type
-    if (!audio_is_output_channel(channelMask)) {
-        ALOGE("createTrack() invalid channel mask %#x", channelMask);
+    if (!audio_is_output_channel(input.config.channel_mask)) {
+        ALOGE("createTrack() invalid channel mask %#x", input.config.channel_mask);
         lStatus = BAD_VALUE;
         goto Exit;
     }
 
     // further format checks are performed by createTrack_l() depending on the thread type
-    if (!audio_is_valid_format(format)) {
-        ALOGE("createTrack() invalid format %#x", format);
-        lStatus = BAD_VALUE;
-        goto Exit;
-    }
-
-    if (sharedBuffer != 0 && sharedBuffer->pointer() == NULL) {
-        ALOGE("createTrack() sharedBuffer is non-0 but has NULL pointer()");
+    if (!audio_is_valid_format(input.config.format)) {
+        ALOGE("createTrack() invalid format %#x", input.config.format);
         lStatus = BAD_VALUE;
         goto Exit;
     }
 
     {
         Mutex::Autolock _l(mLock);
-        PlaybackThread *thread = checkPlaybackThread_l(output);
+        PlaybackThread *thread = checkPlaybackThread_l(output.outputId);
         if (thread == NULL) {
-            ALOGE("no playback thread found for output handle %d", output);
+            ALOGE("no playback thread found for output handle %d", output.outputId);
             lStatus = BAD_VALUE;
             goto Exit;
         }
 
-        client = registerPid(pid);
+        client = registerPid(clientPid);
 
         PlaybackThread *effectThread = NULL;
-        if (sessionId != NULL && *sessionId != AUDIO_SESSION_ALLOCATE) {
-            if (audio_unique_id_get_use(*sessionId) != AUDIO_UNIQUE_ID_USE_SESSION) {
-                ALOGE("createTrack() invalid session ID %d", *sessionId);
-                lStatus = BAD_VALUE;
-                goto Exit;
-            }
-            lSessionId = *sessionId;
-            // check if an effect chain with the same session ID is present on another
-            // output thread and move it here.
-            for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
-                sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
-                if (mPlaybackThreads.keyAt(i) != output) {
-                    uint32_t sessions = t->hasAudioSession(lSessionId);
-                    if (sessions & ThreadBase::EFFECT_SESSION) {
-                        effectThread = t.get();
-                        break;
-                    }
+        // check if an effect chain with the same session ID is present on another
+        // output thread and move it here.
+        for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+            sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
+            if (mPlaybackThreads.keyAt(i) != output.outputId) {
+                uint32_t sessions = t->hasAudioSession(sessionId);
+                if (sessions & ThreadBase::EFFECT_SESSION) {
+                    effectThread = t.get();
+                    break;
                 }
             }
-        } else {
-            // if no audio session id is provided, create one here
-            lSessionId = (audio_session_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
-            if (sessionId != NULL) {
-                *sessionId = lSessionId;
-            }
         }
-        ALOGV("createTrack() lSessionId: %d", lSessionId);
+        ALOGV("createTrack() sessionId: %d", sessionId);
 
-        track = thread->createTrack_l(client, streamType, sampleRate, format,
-                channelMask, frameCount, sharedBuffer, lSessionId, flags, tid,
-                clientUid, &lStatus, portId);
+        output.sampleRate = input.config.sample_rate;
+        output.frameCount = input.frameCount;
+        output.notificationFrameCount = input.notificationFrameCount;
+        output.flags = input.flags;
+
+        track = thread->createTrack_l(client, streamType, &output.sampleRate, input.config.format,
+                                      input.config.channel_mask,
+                                      &output.frameCount, &output.notificationFrameCount,
+                                      input.notificationsPerBuffer, input.speed,
+                                      input.sharedBuffer, sessionId, &output.flags,
+                                      input.clientInfo.clientTid, clientUid, &lStatus, portId);
         LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (track == 0));
         // we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless
 
+        output.afFrameCount = thread->frameCount();
+        output.afSampleRate = thread->sampleRate();
+        output.afLatencyMs = thread->latency();
+
         // move effect chain to this output thread if an effect on same session was waiting
         // for a track to be created
         if (lStatus == NO_ERROR && effectThread != NULL) {
             // no risk of deadlock because AudioFlinger::mLock is held
             Mutex::Autolock _dl(thread->mLock);
             Mutex::Autolock _sl(effectThread->mLock);
-            moveEffectChain_l(lSessionId, effectThread, thread, true);
+            moveEffectChain_l(sessionId, effectThread, thread, true);
         }
 
         // Look for sync events awaiting for a session to be used.
         for (size_t i = 0; i < mPendingSyncEvents.size(); i++) {
-            if (mPendingSyncEvents[i]->triggerSession() == lSessionId) {
+            if (mPendingSyncEvents[i]->triggerSession() == sessionId) {
                 if (thread->isValidSyncEvent(mPendingSyncEvents[i])) {
                     if (lStatus == NO_ERROR) {
                         (void) track->setSyncEvent(mPendingSyncEvents[i]);
@@ -778,7 +777,7 @@
             }
         }
 
-        setAudioHwSyncForSession_l(thread, lSessionId);
+        setAudioHwSyncForSession_l(thread, sessionId);
     }
 
     if (lStatus != NO_ERROR) {
@@ -798,6 +797,9 @@
     trackHandle = new TrackHandle(track);
 
 Exit:
+    if (lStatus != NO_ERROR && output.outputId != AUDIO_IO_HANDLE_NONE) {
+        AudioSystem::releaseOutput(output.outputId, streamType, sessionId);
+    }
     *status = lStatus;
     return trackHandle;
 }
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index dff94d2..7e9ef26 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -114,21 +114,9 @@
     virtual     status_t    dump(int fd, const Vector<String16>& args);
 
     // IAudioFlinger interface, in binder opcode order
-    virtual sp<IAudioTrack> createTrack(
-                                audio_stream_type_t streamType,
-                                uint32_t sampleRate,
-                                audio_format_t format,
-                                audio_channel_mask_t channelMask,
-                                size_t *pFrameCount,
-                                audio_output_flags_t *flags,
-                                const sp<IMemory>& sharedBuffer,
-                                audio_io_handle_t output,
-                                pid_t pid,
-                                pid_t tid,
-                                audio_session_t *sessionId,
-                                int clientUid,
-                                status_t *status /*non-NULL*/,
-                                audio_port_handle_t portId);
+    virtual sp<IAudioTrack> createTrack(const CreateTrackInput& input,
+                                        CreateTrackOutput& output,
+                                        status_t *status);
 
     virtual sp<media::IAudioRecord> openRecord(
                                 audio_io_handle_t input,
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8c7c830..8e6c720 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1837,10 +1837,13 @@
 sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
         const sp<AudioFlinger::Client>& client,
         audio_stream_type_t streamType,
-        uint32_t sampleRate,
+        uint32_t *pSampleRate,
         audio_format_t format,
         audio_channel_mask_t channelMask,
         size_t *pFrameCount,
+        size_t *pNotificationFrameCount,
+        uint32_t notificationsPerBuffer,
+        float speed,
         const sp<IMemory>& sharedBuffer,
         audio_session_t sessionId,
         audio_output_flags_t *flags,
@@ -1850,9 +1853,16 @@
         audio_port_handle_t portId)
 {
     size_t frameCount = *pFrameCount;
+    size_t notificationFrameCount = *pNotificationFrameCount;
     sp<Track> track;
     status_t lStatus;
     audio_output_flags_t outputFlags = mOutput->flags;
+    audio_output_flags_t requestedFlags = *flags;
+
+    if (*pSampleRate == 0) {
+        *pSampleRate = mSampleRate;
+    }
+    uint32_t sampleRate = *pSampleRate;
 
     // special case for FAST flag considered OK if fast mixer is present
     if (hasFastMixer()) {
@@ -1929,36 +1939,114 @@
         *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_FAST);
       }
     }
-    // For normal PCM streaming tracks, update minimum frame count.
-    // For compatibility with AudioTrack calculation, buffer depth is forced
-    // to be at least 2 x the normal mixer frame count and cover audio hardware latency.
-    // This is probably too conservative, but legacy application code may depend on it.
-    // If you change this calculation, also review the start threshold which is related.
-    if (!(*flags & AUDIO_OUTPUT_FLAG_FAST)
-            && audio_has_proportional_frames(format) && sharedBuffer == 0) {
-        // this must match AudioTrack.cpp calculateMinFrameCount().
-        // TODO: Move to a common library
-        uint32_t latencyMs = 0;
-        lStatus = mOutput->stream->getLatency(&latencyMs);
-        if (lStatus != OK) {
-            ALOGE("Error when retrieving output stream latency: %d", lStatus);
+
+    if (!audio_has_proportional_frames(format)) {
+        if (sharedBuffer != 0) {
+            // Same comment as below about ignoring frameCount parameter for set()
+            frameCount = sharedBuffer->size();
+        } else if (frameCount == 0) {
+            frameCount = mNormalFrameCount;
+        }
+        if (notificationFrameCount != frameCount) {
+            notificationFrameCount = frameCount;
+        }
+    } else if (sharedBuffer != 0) {
+        // FIXME: Ensure client side memory buffers need
+        // not have additional alignment beyond sample
+        // (e.g. 16 bit stereo accessed as 32 bit frame).
+        size_t alignment = audio_bytes_per_sample(format);
+        if (alignment & 1) {
+            // for AUDIO_FORMAT_PCM_24_BIT_PACKED (not exposed through Java).
+            alignment = 1;
+        }
+        uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
+        size_t frameSize = channelCount * audio_bytes_per_sample(format);
+        if (channelCount > 1) {
+            // More than 2 channels does not require stronger alignment than stereo
+            alignment <<= 1;
+        }
+        if (((uintptr_t)sharedBuffer->pointer() & (alignment - 1)) != 0) {
+            ALOGE("Invalid buffer alignment: address %p, channel count %u",
+                  sharedBuffer->pointer(), channelCount);
+            lStatus = BAD_VALUE;
             goto Exit;
         }
-        uint32_t minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate);
-        if (minBufCount < 2) {
-            minBufCount = 2;
+
+        // When initializing a shared buffer AudioTrack via constructors,
+        // there's no frameCount parameter.
+        // But when initializing a shared buffer AudioTrack via set(),
+        // there _is_ a frameCount parameter.  We silently ignore it.
+        frameCount = sharedBuffer->size() / frameSize;
+    } else {
+        size_t minFrameCount = 0;
+        // For fast tracks we try to respect the application's request for notifications per buffer.
+        if (*flags & AUDIO_OUTPUT_FLAG_FAST) {
+            if (notificationsPerBuffer > 0) {
+                // Avoid possible arithmetic overflow during multiplication.
+                if (notificationsPerBuffer > SIZE_MAX / mFrameCount) {
+                    ALOGE("Requested notificationPerBuffer=%u ignored for HAL frameCount=%zu",
+                          notificationsPerBuffer, mFrameCount);
+                } else {
+                    minFrameCount = mFrameCount * notificationsPerBuffer;
+                }
+            }
+        } else {
+            // For normal PCM streaming tracks, update minimum frame count.
+            // Buffer depth is forced to be at least 2 x the normal mixer frame count and
+            // cover audio hardware latency.
+            // This is probably too conservative, but legacy application code may depend on it.
+            // If you change this calculation, also review the start threshold which is related.
+            uint32_t latencyMs = latency_l();
+            if (latencyMs == 0) {
+                ALOGE("Error when retrieving output stream latency");
+                lStatus = UNKNOWN_ERROR;
+                goto Exit;
+            }
+
+            minFrameCount = AudioSystem::calculateMinFrameCount(latencyMs, mNormalFrameCount,
+                                mSampleRate, sampleRate, speed /*, 0 mNotificationsPerBufferReq*/);
+
         }
-        // For normal mixing tracks, if speed is > 1.0f (normal), AudioTrack
-        // or the client should compute and pass in a larger buffer request.
-        size_t minFrameCount =
-                minBufCount * sourceFramesNeededWithTimestretch(
-                        sampleRate, mNormalFrameCount,
-                        mSampleRate, AUDIO_TIMESTRETCH_SPEED_NORMAL /*speed*/);
-        if (frameCount < minFrameCount) { // including frameCount == 0
+        if (frameCount < minFrameCount) {
             frameCount = minFrameCount;
         }
     }
+
+    // Make sure that application is notified with sufficient margin before underrun.
+    // The client can divide the AudioTrack buffer into sub-buffers,
+    // and expresses its desire to server as the notification frame count.
+    if (sharedBuffer == 0 && audio_is_linear_pcm(format)) {
+        size_t maxNotificationFrames;
+        if (*flags & AUDIO_OUTPUT_FLAG_FAST) {
+            // notify every HAL buffer, regardless of the size of the track buffer
+            maxNotificationFrames = mFrameCount;
+        } else {
+            // For normal tracks, use at least double-buffering if no sample rate conversion,
+            // or at least triple-buffering if there is sample rate conversion
+            const int nBuffering = sampleRate == mSampleRate ? 2 : 3;
+            maxNotificationFrames = frameCount / nBuffering;
+            // If client requested a fast track but this was denied, then use the smaller maximum.
+            if (requestedFlags & AUDIO_OUTPUT_FLAG_FAST) {
+                size_t maxNotificationFramesFastDenied = FMS_20 * sampleRate / 1000;
+                if (maxNotificationFrames > maxNotificationFramesFastDenied) {
+                    maxNotificationFrames = maxNotificationFramesFastDenied;
+                }
+            }
+        }
+        if (notificationFrameCount == 0 || notificationFrameCount > maxNotificationFrames) {
+            if (notificationFrameCount == 0) {
+                ALOGD("Client defaulted notificationFrames to %zu for frameCount %zu",
+                    maxNotificationFrames, frameCount);
+            } else {
+                ALOGW("Client adjusted notificationFrames from %zu to %zu for frameCount %zu",
+                      notificationFrameCount, maxNotificationFrames, frameCount);
+            }
+            notificationFrameCount = maxNotificationFrames;
+        }
+    }
+
     *pFrameCount = frameCount;
+    *pNotificationFrameCount = notificationFrameCount;
 
     switch (mType) {
 
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index b685e1b..2ca273f 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -706,10 +706,13 @@
                 sp<Track>   createTrack_l(
                                 const sp<AudioFlinger::Client>& client,
                                 audio_stream_type_t streamType,
-                                uint32_t sampleRate,
+                                uint32_t *sampleRate,
                                 audio_format_t format,
                                 audio_channel_mask_t channelMask,
                                 size_t *pFrameCount,
+                                size_t *pNotificationFrameCount,
+                                uint32_t notificationsPerBuffer,
+                                float speed,
                                 const sp<IMemory>& sharedBuffer,
                                 audio_session_t sessionId,
                                 audio_output_flags_t *flags,
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index faeb0a7..9348ecd 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -1,28 +1,11 @@
 LOCAL_PATH := $(call my-dir)
 
-# service library
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := MediaCodecService.cpp
-LOCAL_SHARED_LIBRARIES := \
-    libmedia_omx \
-    libbinder \
-    libgui \
-    libutils \
-    liblog \
-    libstagefright_omx \
-    libstagefright_xmlparser
-LOCAL_MODULE:= libmediacodecservice
-LOCAL_VENDOR_MODULE := true
-LOCAL_32_BIT_ONLY := true
-include $(BUILD_SHARED_LIBRARY)
-
 # service executable
 include $(CLEAR_VARS)
 LOCAL_REQUIRED_MODULES_arm := mediacodec.policy
 LOCAL_SRC_FILES := main_codecservice.cpp
 LOCAL_SHARED_LIBRARIES := \
     libmedia_omx \
-    libmediacodecservice \
     libbinder \
     libutils \
     libgui \
@@ -42,6 +25,11 @@
 LOCAL_VENDOR_MODULE := true
 LOCAL_32_BIT_ONLY := true
 LOCAL_INIT_RC := android.hardware.media.omx@1.0-service.rc
+
+ifeq ($(PRODUCT_FULL_TREBLE),true)
+LOCAL_CFLAGS += -DUSE_VNDBINDER
+endif
+
 include $(BUILD_EXECUTABLE)
 
 # service seccomp policy
diff --git a/services/mediacodec/MediaCodecService.cpp b/services/mediacodec/MediaCodecService.cpp
deleted file mode 100644
index 6b510c6..0000000
--- a/services/mediacodec/MediaCodecService.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2015 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_TAG "MediaCodecService"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include "MediaCodecService.h"
-
-namespace android {
-
-sp<IOMX> MediaCodecService::getOMX() {
-
-    Mutex::Autolock autoLock(mOMXLock);
-
-    if (mOMX.get() == NULL) {
-        mOMX = new OMX();
-    }
-
-    return mOMX;
-}
-
-sp<IOMXStore> MediaCodecService::getOMXStore() {
-
-    Mutex::Autolock autoLock(mOMXStoreLock);
-
-    if (mOMXStore.get() == NULL) {
-        mOMXStore = new OMXStore();
-    }
-
-    return mOMXStore;
-}
-
-status_t MediaCodecService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
-        uint32_t flags)
-{
-    return BnMediaCodecService::onTransact(code, data, reply, flags);
-}
-
-}   // namespace android
diff --git a/services/mediacodec/MediaCodecService.h b/services/mediacodec/MediaCodecService.h
deleted file mode 100644
index 9301135..0000000
--- a/services/mediacodec/MediaCodecService.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_MEDIA_CODEC_SERVICE_H
-#define ANDROID_MEDIA_CODEC_SERVICE_H
-
-#include <binder/BinderService.h>
-#include <media/IMediaCodecService.h>
-#include <media/stagefright/omx/OMX.h>
-#include <media/stagefright/omx/OMXStore.h>
-
-namespace android {
-
-class MediaCodecService : public BinderService<MediaCodecService>,
-        public BnMediaCodecService
-{
-    friend class BinderService<MediaCodecService>;    // for MediaCodecService()
-public:
-    MediaCodecService() : BnMediaCodecService() { }
-    virtual ~MediaCodecService() { }
-    virtual void onFirstRef() { }
-
-    static const char*    getServiceName() { return "media.codec"; }
-
-    virtual sp<IOMX>      getOMX();
-
-    virtual sp<IOMXStore> getOMXStore();
-
-    virtual status_t      onTransact(uint32_t code, const Parcel& data,
-                                     Parcel* reply, uint32_t flags);
-
-private:
-    Mutex                 mOMXLock;
-    sp<IOMX>              mOMX;
-    Mutex                 mOMXStoreLock;
-    sp<IOMXStore>         mOMXStore;
-};
-
-}   // namespace android
-
-#endif  // ANDROID_MEDIA_CODEC_SERVICE_H
diff --git a/services/mediacodec/main_codecservice.cpp b/services/mediacodec/main_codecservice.cpp
index 79d6da5..6f14a42 100644
--- a/services/mediacodec/main_codecservice.cpp
+++ b/services/mediacodec/main_codecservice.cpp
@@ -15,22 +15,12 @@
 ** limitations under the License.
 */
 
-#include <fcntl.h>
-#include <sys/prctl.h>
-#include <sys/wait.h>
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-#include <cutils/properties.h>
-
-#include <string>
-
 #include <android-base/logging.h>
 
 // from LOCAL_C_INCLUDES
-#include "MediaCodecService.h"
 #include "minijail.h"
 
+#include <binder/ProcessState.h>
 #include <hidl/HidlTransportSupport.h>
 #include <media/stagefright/omx/1.0/Omx.h>
 #include <media/stagefright/omx/1.0/OmxStore.h>
@@ -45,41 +35,33 @@
 
 int main(int argc __unused, char** argv)
 {
+    strcpy(argv[0], "media.codec");
     LOG(INFO) << "mediacodecservice starting";
-    bool treble = property_get_bool("persist.media.treble_omx", true);
-    if (treble) {
-      android::ProcessState::initWithDriver("/dev/vndbinder");
-    }
-
     signal(SIGPIPE, SIG_IGN);
     SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);
 
-    strcpy(argv[0], "media.codec");
+#ifdef USE_VNDBINDER
+    android::ProcessState::initWithDriver("/dev/vndbinder");
+    android::ProcessState::self()->startThreadPool();
+#endif // USE_VNDBINDER
 
     ::android::hardware::configureRpcThreadpool(64, false);
-    sp<ProcessState> proc(ProcessState::self());
 
-    if (treble) {
-        using namespace ::android::hardware::media::omx::V1_0;
-        sp<IOmxStore> omxStore = new implementation::OmxStore();
-        if (omxStore == nullptr) {
-            LOG(ERROR) << "Cannot create IOmxStore HAL service.";
-        } else if (omxStore->registerAsService() != OK) {
-            LOG(ERROR) << "Cannot register IOmxStore HAL service.";
-        }
-        sp<IOmx> omx = new implementation::Omx();
-        if (omx == nullptr) {
-            LOG(ERROR) << "Cannot create IOmx HAL service.";
-        } else if (omx->registerAsService() != OK) {
-            LOG(ERROR) << "Cannot register IOmx HAL service.";
-        } else {
-            LOG(INFO) << "Treble OMX service created.";
-        }
+    using namespace ::android::hardware::media::omx::V1_0;
+    sp<IOmxStore> omxStore = new implementation::OmxStore();
+    if (omxStore == nullptr) {
+        LOG(ERROR) << "Cannot create IOmxStore HAL service.";
+    } else if (omxStore->registerAsService() != OK) {
+        LOG(ERROR) << "Cannot register IOmxStore HAL service.";
+    }
+    sp<IOmx> omx = new implementation::Omx();
+    if (omx == nullptr) {
+        LOG(ERROR) << "Cannot create IOmx HAL service.";
+    } else if (omx->registerAsService() != OK) {
+        LOG(ERROR) << "Cannot register IOmx HAL service.";
     } else {
-        MediaCodecService::instantiate();
-        LOG(INFO) << "Non-Treble OMX service created.";
+        LOG(INFO) << "IOmx HAL service created.";
     }
 
-    ProcessState::self()->startThreadPool();
-    IPCThreadState::self()->joinThreadPool();
+    ::android::hardware::joinRpcThreadpool();
 }