Merge "Convert capture frame rate metadata"
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 038c854..3223647 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -211,7 +211,7 @@
         mBufferMemory.clear();
         IPCThreadState::self()->flushCommands();
         ALOGV("%s(%d): releasing session id %d",
-                __func__, mId, mSessionId);
+                __func__, mPortId, mSessionId);
         AudioSystem::releaseAudioSessionId(mSessionId, -1 /*pid*/);
     }
 }
@@ -239,7 +239,7 @@
     pid_t callingPid;
     pid_t myPid;
 
-    // Note mId is not valid until the track is created, so omit mId in ALOG for set.
+    // Note mPortId is not valid until the track is created, so omit mPortId in ALOG for set.
     ALOGV("%s(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
           "notificationFrames %u, sessionId %d, transferType %d, flags %#x, opPackageName %s "
           "uid %d, pid %d",
@@ -356,7 +356,7 @@
     // create the IAudioRecord
     status = createRecord_l(0 /*epoch*/, mOpPackageName);
 
-    ALOGV("%s(%d): status %d", __func__, mId, status);
+    ALOGV("%s(%d): status %d", __func__, mPortId, status);
 
     if (status != NO_ERROR) {
         if (mAudioRecordThread != 0) {
@@ -393,7 +393,7 @@
 
 status_t AudioRecord::start(AudioSystem::sync_event_t event, audio_session_t triggerSession)
 {
-    ALOGV("%s(%d): sync event %d trigger session %d", __func__, mId, event, triggerSession);
+    ALOGV("%s(%d): sync event %d trigger session %d", __func__, mPortId, event, triggerSession);
 
     AutoMutex lock(mLock);
     if (mActive) {
@@ -434,7 +434,7 @@
 
     if (status != NO_ERROR) {
         mActive = false;
-        ALOGE("%s(%d): status %d", __func__, mId, status);
+        ALOGE("%s(%d): status %d", __func__, mPortId, status);
     } else {
         sp<AudioRecordThread> t = mAudioRecordThread;
         if (t != 0) {
@@ -458,7 +458,7 @@
 void AudioRecord::stop()
 {
     AutoMutex lock(mLock);
-    ALOGV("%s(%d): mActive:%d\n", __func__, mId, mActive);
+    ALOGV("%s(%d): mActive:%d\n", __func__, mPortId, mActive);
     if (!mActive) {
         return;
     }
@@ -638,7 +638,7 @@
 
     result.append(" AudioRecord::dump\n");
     result.appendFormat("  id(%d) status(%d), active(%d), session Id(%d)\n",
-                        mId, mStatus, mActive, mSessionId);
+                        mPortId, mStatus, mActive, mSessionId);
     result.appendFormat("  flags(%#x), req. flags(%#x), audio source(%d)\n",
                         mFlags, mOrigFlags, mAttributes.source);
     result.appendFormat("  format(%#x), channel mask(%#x), channel count(%u), sample rate(%u)\n",
@@ -680,7 +680,7 @@
     status_t status;
 
     if (audioFlinger == 0) {
-        ALOGE("%s(%d): Could not get audioflinger", __func__, mId);
+        ALOGE("%s(%d): Could not get audioflinger", __func__, mPortId);
         status = NO_INIT;
         goto exit;
     }
@@ -708,7 +708,7 @@
             (mTransfer == TRANSFER_OBTAIN);
         if (!useCaseAllowed) {
             ALOGW("%s(%d): AUDIO_INPUT_FLAG_FAST denied, incompatible transfer = %s",
-                  __func__, mId,
+                  __func__, mPortId,
                   convertTransferToText(mTransfer));
             mFlags = (audio_input_flags_t) (mFlags & ~(AUDIO_INPUT_FLAG_FAST |
                     AUDIO_INPUT_FLAG_RAW));
@@ -744,7 +744,7 @@
 
     if (status != NO_ERROR) {
         ALOGE("%s(%d): AudioFlinger could not create record track, status: %d",
-              __func__, mId, status);
+              __func__, mPortId, status);
         goto exit;
     }
     ALOG_ASSERT(record != 0);
@@ -755,7 +755,7 @@
     mAwaitBoost = false;
     if (output.flags & AUDIO_INPUT_FLAG_FAST) {
         ALOGI("%s(%d): AUDIO_INPUT_FLAG_FAST successful; frameCount %zu -> %zu",
-              __func__, mId,
+              __func__, mPortId,
               mReqFrameCount, output.frameCount);
         mAwaitBoost = true;
     }
@@ -765,13 +765,13 @@
     mSampleRate = output.sampleRate;
 
     if (output.cblk == 0) {
-        ALOGE("%s(%d): Could not get control block", __func__, mId);
+        ALOGE("%s(%d): Could not get control block", __func__, mPortId);
         status = NO_INIT;
         goto exit;
     }
     iMemPointer = output.cblk ->pointer();
     if (iMemPointer == NULL) {
-        ALOGE("%s(%d): Could not get control block pointer", __func__, mId);
+        ALOGE("%s(%d): Could not get control block pointer", __func__, mPortId);
         status = NO_INIT;
         goto exit;
     }
@@ -786,7 +786,7 @@
     } else {
         buffers = output.buffers->pointer();
         if (buffers == NULL) {
-            ALOGE("%s(%d): Could not get buffer pointer", __func__, mId);
+            ALOGE("%s(%d): Could not get buffer pointer", __func__, mPortId);
             status = NO_INIT;
             goto exit;
         }
@@ -800,14 +800,14 @@
     mAudioRecord = record;
     mCblkMemory = output.cblk;
     mBufferMemory = output.buffers;
-    mId = output.trackId;
+    mPortId = output.portId;
     IPCThreadState::self()->flushCommands();
 
     mCblk = cblk;
     // note that output.frameCount is the (possibly revised) value of mReqFrameCount
     if (output.frameCount < mReqFrameCount || (mReqFrameCount == 0 && output.frameCount == 0)) {
         ALOGW("%s(%d): Requested frameCount %zu but received frameCount %zu",
-              __func__, mId,
+              __func__, mPortId,
               mReqFrameCount,  output.frameCount);
     }
 
@@ -815,7 +815,7 @@
     // The computation is done on server side.
     if (mNotificationFramesReq > 0 && output.notificationFrameCount != mNotificationFramesReq) {
         ALOGW("%s(%d): Server adjusted notificationFrames from %u to %zu for frameCount %zu",
-                __func__, mId,
+                __func__, mPortId,
                 mNotificationFramesReq, output.notificationFrameCount, output.frameCount);
     }
     mNotificationFramesAct = (uint32_t)output.notificationFrameCount;
@@ -883,7 +883,7 @@
         timeout.tv_nsec = (long) (ms % 1000) * 1000000;
         requested = &timeout;
     } else {
-        ALOGE("%s(%d): invalid waitCount %d", __func__, mId, waitCount);
+        ALOGE("%s(%d): invalid waitCount %d", __func__, mPortId, waitCount);
         requested = NULL;
     }
     return obtainBuffer(audioBuffer, requested, NULL /*elapsed*/, nonContig);
@@ -993,7 +993,7 @@
         // sanity-check. user is most-likely passing an error code, and it would
         // make the return value ambiguous (actualSize vs error).
         ALOGE("%s(%d) (buffer=%p, size=%zu (%zu)",
-                __func__, mId, buffer, userSize, userSize);
+                __func__, mPortId, buffer, userSize, userSize);
         return BAD_VALUE;
     }
 
@@ -1050,7 +1050,7 @@
             pollUs <<= 1;
         } while (tryCounter-- > 0);
         if (tryCounter < 0) {
-            ALOGE("%s(%d): did not receive expected priority boost on time", __func__, mId);
+            ALOGE("%s(%d): did not receive expected priority boost on time", __func__, mPortId);
         }
         // Run again immediately
         return 0;
@@ -1174,7 +1174,7 @@
         timeout.tv_sec = ns / 1000000000LL;
         timeout.tv_nsec = ns % 1000000000LL;
         ALOGV("%s(%d): timeout %ld.%03d",
-                __func__, mId, timeout.tv_sec, (int) timeout.tv_nsec / 1000000);
+                __func__, mPortId, timeout.tv_sec, (int) timeout.tv_nsec / 1000000);
         requested = &timeout;
     }
 
@@ -1187,17 +1187,17 @@
         status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig);
         LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0),
                 "%s(%d): obtainBuffer() err=%d frameCount=%zu",
-                __func__, mId, err, audioBuffer.frameCount);
+                __func__, mPortId, err, audioBuffer.frameCount);
         requested = &ClientProxy::kNonBlocking;
         size_t avail = audioBuffer.frameCount + nonContig;
         ALOGV("%s(%d): obtainBuffer(%u) returned %zu = %zu + %zu err %d",
-                __func__, mId, mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err);
+                __func__, mPortId, mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err);
         if (err != NO_ERROR) {
             if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR) {
                 break;
             }
             ALOGE("%s(%d): Error %d obtaining an audio buffer, giving up.",
-                    __func__, mId, err);
+                    __func__, mPortId, err);
             return NS_NEVER;
         }
 
@@ -1220,7 +1220,7 @@
         // Sanity check on returned size
         if (ssize_t(readSize) < 0 || readSize > reqSize) {
             ALOGE("%s(%d):  EVENT_MORE_DATA requested %zu bytes but callback returned %zd bytes",
-                    __func__, mId, reqSize, ssize_t(readSize));
+                    __func__, mPortId, reqSize, ssize_t(readSize));
             return NS_NEVER;
         }
 
@@ -1280,7 +1280,7 @@
 
 status_t AudioRecord::restoreRecord_l(const char *from)
 {
-    ALOGW("%s(%d): dead IAudioRecord, creating a new one from %s()", __func__, mId, from);
+    ALOGW("%s(%d): dead IAudioRecord, creating a new one from %s()", __func__, mPortId, from);
     ++mSequence;
 
     const int INITIAL_RETRIES = 3;
@@ -1311,7 +1311,7 @@
     }
 
     if (result != NO_ERROR) {
-        ALOGW("%s(%d): failed status %d, retries %d", __func__, mId, result, retries);
+        ALOGW("%s(%d): failed status %d, retries %d", __func__, mPortId, result, retries);
         if (--retries > 0) {
             // leave time for an eventual race condition to clear before retrying
             usleep(500000);
@@ -1330,18 +1330,18 @@
 status_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback)
 {
     if (callback == 0) {
-        ALOGW("%s(%d): adding NULL callback!", __func__, mId);
+        ALOGW("%s(%d): adding NULL callback!", __func__, mPortId);
         return BAD_VALUE;
     }
     AutoMutex lock(mLock);
     if (mDeviceCallback.unsafe_get() == callback.get()) {
-        ALOGW("%s(%d): adding same callback!", __func__, mId);
+        ALOGW("%s(%d): adding same callback!", __func__, mPortId);
         return INVALID_OPERATION;
     }
     status_t status = NO_ERROR;
     if (mInput != AUDIO_IO_HANDLE_NONE) {
         if (mDeviceCallback != 0) {
-            ALOGW("%s(%d): callback already present!", __func__, mId);
+            ALOGW("%s(%d): callback already present!", __func__, mPortId);
             AudioSystem::removeAudioDeviceCallback(this, mInput);
         }
         status = AudioSystem::addAudioDeviceCallback(this, mInput);
@@ -1354,12 +1354,12 @@
         const sp<AudioSystem::AudioDeviceCallback>& callback)
 {
     if (callback == 0) {
-        ALOGW("%s(%d): removing NULL callback!", __func__, mId);
+        ALOGW("%s(%d): removing NULL callback!", __func__, mPortId);
         return BAD_VALUE;
     }
     AutoMutex lock(mLock);
     if (mDeviceCallback.unsafe_get() != callback.get()) {
-        ALOGW("%s(%d): removing different callback!", __func__, mId);
+        ALOGW("%s(%d): removing different callback!", __func__, mPortId);
         return INVALID_OPERATION;
     }
     mDeviceCallback.clear();
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 8607ee1..02324ac 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -344,7 +344,7 @@
         mSharedBuffer.clear();
         IPCThreadState::self()->flushCommands();
         ALOGV("%s(%d), releasing session id %d from %d on behalf of %d",
-                __func__, mId,
+                __func__, mPortId,
                 mSessionId, IPCThreadState::self()->getCallingPid(), mClientPid);
         AudioSystem::releaseAudioSessionId(mSessionId, mClientPid);
     }
@@ -377,7 +377,7 @@
     pid_t callingPid;
     pid_t myPid;
 
-    // Note mId is not valid until the track is created, so omit mId in ALOG for set.
+    // Note mPortId is not valid until the track is created, so omit mPortId in ALOG for set.
     ALOGV("%s(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
           "flags #%x, notificationFrames %d, sessionId %d, transferType %d, uid %d, pid %d",
           __func__,
@@ -658,7 +658,7 @@
 status_t AudioTrack::start()
 {
     AutoMutex lock(mLock);
-    ALOGV("%s(%d): prior state:%s", __func__, mId, stateToString(mState));
+    ALOGV("%s(%d): prior state:%s", __func__, mPortId, stateToString(mState));
 
     if (mState == STATE_ACTIVE) {
         return INVALID_OPERATION;
@@ -699,7 +699,7 @@
             // It is possible since flush and stop are asynchronous that the server
             // is still active at this point.
             ALOGV("%s(%d): server read:%lld  cumulative flushed:%lld  client written:%lld",
-                    __func__, mId,
+                    __func__, mPortId,
                     (long long)(mFramesWrittenServerOffset
                             + mStartEts.mPosition[ExtendedTimestamp::LOCATION_SERVER]),
                     (long long)mStartEts.mFlushed,
@@ -760,7 +760,7 @@
         // Start our local VolumeHandler for restoration purposes.
         mVolumeHandler->setStarted();
     } else {
-        ALOGE("%s(%d): status %d", __func__, mId, status);
+        ALOGE("%s(%d): status %d", __func__, mPortId, status);
         mState = previousState;
         if (t != 0) {
             if (previousState != STATE_STOPPING) {
@@ -778,7 +778,7 @@
 void AudioTrack::stop()
 {
     AutoMutex lock(mLock);
-    ALOGV("%s(%d): prior state:%s", __func__, mId, stateToString(mState));
+    ALOGV("%s(%d): prior state:%s", __func__, mPortId, stateToString(mState));
 
     if (mState != STATE_ACTIVE && mState != STATE_PAUSED) {
         return;
@@ -789,7 +789,7 @@
     } else {
         mState = STATE_STOPPED;
         ALOGD_IF(mSharedBuffer == nullptr,
-                "%s(%d): called with %u frames delivered", __func__, mId, mReleased.value());
+                "%s(%d): called with %u frames delivered", __func__, mPortId, mReleased.value());
         mReleased = 0;
     }
 
@@ -830,7 +830,7 @@
 void AudioTrack::flush()
 {
     AutoMutex lock(mLock);
-    ALOGV("%s(%d): prior state:%s", __func__, mId, stateToString(mState));
+    ALOGV("%s(%d): prior state:%s", __func__, mPortId, stateToString(mState));
 
     if (mSharedBuffer != 0) {
         return;
@@ -863,7 +863,7 @@
 void AudioTrack::pause()
 {
     AutoMutex lock(mLock);
-    ALOGV("%s(%d): prior state:%s", __func__, mId, stateToString(mState));
+    ALOGV("%s(%d): prior state:%s", __func__, mPortId, stateToString(mState));
 
     if (mState == STATE_ACTIVE) {
         mState = STATE_PAUSED;
@@ -891,7 +891,7 @@
             uint32_t halFrames;
             AudioSystem::getRenderPosition(mOutput, &halFrames, &mPausedPosition);
             ALOGV("%s(%d): for offload, cache current position %u",
-                    __func__, mId, mPausedPosition);
+                    __func__, mPortId, mPausedPosition);
         }
     }
 }
@@ -945,7 +945,7 @@
 status_t AudioTrack::setSampleRate(uint32_t rate)
 {
     AutoMutex lock(mLock);
-    ALOGV("%s(%d): prior state:%s rate:%u", __func__, mId, stateToString(mState), rate);
+    ALOGV("%s(%d): prior state:%s rate:%u", __func__, mPortId, stateToString(mState), rate);
 
     if (rate == mSampleRate) {
         return NO_ERROR;
@@ -1013,7 +1013,7 @@
     }
 
     ALOGV("%s(%d): mSampleRate:%u  mSpeed:%f  mPitch:%f",
-            __func__, mId, mSampleRate, playbackRate.mSpeed, playbackRate.mPitch);
+            __func__, mPortId, mSampleRate, playbackRate.mSpeed, playbackRate.mPitch);
     // pitch is emulated by adjusting speed and sampleRate
     const uint32_t effectiveRate = adjustSampleRate(mSampleRate, playbackRate.mPitch);
     const float effectiveSpeed = adjustSpeed(playbackRate.mSpeed, playbackRate.mPitch);
@@ -1023,17 +1023,17 @@
     playbackRateTemp.mPitch = effectivePitch;
 
     ALOGV("%s(%d) (effective) mSampleRate:%u  mSpeed:%f  mPitch:%f",
-            __func__, mId, effectiveRate, effectiveSpeed, effectivePitch);
+            __func__, mPortId, effectiveRate, effectiveSpeed, effectivePitch);
 
     if (!isAudioPlaybackRateValid(playbackRateTemp)) {
         ALOGW("%s(%d) (%f, %f) failed (effective rate out of bounds)",
-                __func__, mId, playbackRate.mSpeed, playbackRate.mPitch);
+                __func__, mPortId, playbackRate.mSpeed, playbackRate.mPitch);
         return BAD_VALUE;
     }
     // Check if the buffer size is compatible.
     if (!isSampleRateSpeedAllowed_l(effectiveRate, effectiveSpeed)) {
         ALOGW("%s(%d) (%f, %f) failed (buffer size)",
-                __func__, mId, playbackRate.mSpeed, playbackRate.mPitch);
+                __func__, mPortId, playbackRate.mSpeed, playbackRate.mPitch);
         return BAD_VALUE;
     }
 
@@ -1041,13 +1041,13 @@
     if ((uint64_t)effectiveRate > (uint64_t)mSampleRate *
             (uint64_t)AUDIO_RESAMPLER_DOWN_RATIO_MAX) {
         ALOGW("%s(%d) (%f, %f) failed. Resample rate exceeds max accepted value",
-                __func__, mId, playbackRate.mSpeed, playbackRate.mPitch);
+                __func__, mPortId, playbackRate.mSpeed, playbackRate.mPitch);
         return BAD_VALUE;
     }
 
     if ((uint64_t)effectiveRate * (uint64_t)AUDIO_RESAMPLER_UP_RATIO_MAX < (uint64_t)mSampleRate) {
         ALOGW("%s(%d) (%f, %f) failed. Resample rate below min accepted value",
-                __func__, mId, playbackRate.mSpeed, playbackRate.mPitch);
+                __func__, mPortId, playbackRate.mSpeed, playbackRate.mPitch);
         return BAD_VALUE;
     }
     mPlaybackRate = playbackRate;
@@ -1249,7 +1249,7 @@
 
         if (isOffloaded_l() && ((mState == STATE_PAUSED) || (mState == STATE_PAUSED_STOPPING))) {
             ALOGV("%s(%d): called in paused state, return cached position %u",
-                __func__, mId, mPausedPosition);
+                __func__, mPortId, mPausedPosition);
             *position = mPausedPosition;
             return NO_ERROR;
         }
@@ -1395,7 +1395,7 @@
 {
     status_t status = AudioSystem::getLatency(mOutput, &mAfLatency);
     if (status != NO_ERROR) {
-        ALOGW("%s(%d): getLatency(%d) failed status %d", __func__, mId, mOutput, status);
+        ALOGW("%s(%d): getLatency(%d) failed status %d", __func__, mPortId, mOutput, status);
     } else {
         // FIXME don't believe this lie
         mLatency = mAfLatency + (1000LL * mFrameCount) / mSampleRate;
@@ -1425,7 +1425,7 @@
     const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
     if (audioFlinger == 0) {
         ALOGE("%s(%d): Could not get audioflinger",
-                __func__, mId);
+                __func__, mPortId);
         status = NO_INIT;
         goto exit;
     }
@@ -1451,7 +1451,7 @@
         if (!fastAllowed) {
             ALOGW("%s(%d): AUDIO_OUTPUT_FLAG_FAST denied by client,"
                   " not shared buffer and transfer = %s",
-                  __func__, mId,
+                  __func__, mPortId,
                   convertTransferToText(mTransfer));
             mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_FAST);
         }
@@ -1501,7 +1501,7 @@
 
     if (status != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
         ALOGE("%s(%d): AudioFlinger could not create track, status: %d output %d",
-                __func__, mId, status, output.outputId);
+                __func__, mPortId, status, output.outputId);
         if (status == NO_ERROR) {
             status = NO_INIT;
         }
@@ -1522,7 +1522,7 @@
     mAfFrameCount = output.afFrameCount;
     mAfSampleRate = output.afSampleRate;
     mAfLatency = output.afLatencyMs;
-    mId = output.trackId;
+    mPortId = output.portId;
 
     mLatency = mAfLatency + (1000LL * mFrameCount) / mSampleRate;
 
@@ -1532,13 +1532,13 @@
     // FIXME compare to AudioRecord
     sp<IMemory> iMem = track->getCblk();
     if (iMem == 0) {
-        ALOGE("%s(%d): Could not get control block", __func__, mId);
+        ALOGE("%s(%d): Could not get control block", __func__, mPortId);
         status = NO_INIT;
         goto exit;
     }
     void *iMemPointer = iMem->pointer();
     if (iMemPointer == NULL) {
-        ALOGE("%s(%d): Could not get control block pointer", __func__, mId);
+        ALOGE("%s(%d): Could not get control block pointer", __func__, mPortId);
         status = NO_INIT;
         goto exit;
     }
@@ -1558,13 +1558,13 @@
     if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
         if (output.flags & AUDIO_OUTPUT_FLAG_FAST) {
             ALOGI("%s(%d): AUDIO_OUTPUT_FLAG_FAST successful; frameCount %zu -> %zu",
-                  __func__, mId, mReqFrameCount, mFrameCount);
+                  __func__, mPortId, mReqFrameCount, mFrameCount);
             if (!mThreadCanCallJava) {
                 mAwaitBoost = true;
             }
         } else {
             ALOGW("%s(%d): AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %zu -> %zu",
-                  __func__, mId, mReqFrameCount, mFrameCount);
+                  __func__, mPortId, mReqFrameCount, mFrameCount);
         }
     }
     mFlags = output.flags;
@@ -1592,7 +1592,7 @@
     } else {
         buffers = mSharedBuffer->pointer();
         if (buffers == NULL) {
-            ALOGE("%s(%d): Could not get buffer pointer", __func__, mId);
+            ALOGE("%s(%d): Could not get buffer pointer", __func__, mPortId);
             status = NO_INIT;
             goto exit;
         }
@@ -1681,7 +1681,7 @@
         timeout.tv_nsec = (long) (ms % 1000) * 1000000;
         requested = &timeout;
     } else {
-        ALOGE("%s(%d): invalid waitCount %d", __func__, mId, waitCount);
+        ALOGE("%s(%d): invalid waitCount %d", __func__, mPortId, waitCount);
         requested = NULL;
     }
     return obtainBuffer(audioBuffer, requested, NULL /*elapsed*/, nonContig);
@@ -1792,7 +1792,7 @@
     int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
     if ((mState == STATE_ACTIVE) && (flags & CBLK_DISABLED)) {
         ALOGW("%s(%d): releaseBuffer() track %p disabled due to previous underrun, restarting",
-                __func__, mId, this);
+                __func__, mPortId, this);
         // FIXME ignoring status
         mAudioTrack->start();
     }
@@ -1820,7 +1820,7 @@
         // Sanity-check: user is most-likely passing an error code, and it would
         // make the return value ambiguous (actualSize vs error).
         ALOGE("%s(%d): AudioTrack::write(buffer=%p, size=%zu (%zd)",
-                __func__, mId, buffer, userSize, userSize);
+                __func__, mPortId, buffer, userSize, userSize);
         return BAD_VALUE;
     }
 
@@ -1893,7 +1893,7 @@
         } while (tryCounter-- > 0);
         if (tryCounter < 0) {
             ALOGE("%s(%d): did not receive expected priority boost on time",
-                    __func__, mId);
+                    __func__, mPortId);
         }
         // Run again immediately
         return 0;
@@ -2135,7 +2135,7 @@
         timeout.tv_sec = ns / 1000000000LL;
         timeout.tv_nsec = ns % 1000000000LL;
         ALOGV("%s(%d): timeout %ld.%03d",
-                __func__, mId, timeout.tv_sec, (int) timeout.tv_nsec / 1000000);
+                __func__, mPortId, timeout.tv_sec, (int) timeout.tv_nsec / 1000000);
         requested = &timeout;
     }
 
@@ -2148,11 +2148,11 @@
         status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig);
         LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0),
                 "%s(%d): obtainBuffer() err=%d frameCount=%zu",
-                 __func__, mId, err, audioBuffer.frameCount);
+                 __func__, mPortId, err, audioBuffer.frameCount);
         requested = &ClientProxy::kNonBlocking;
         size_t avail = audioBuffer.frameCount + nonContig;
         ALOGV("%s(%d): obtainBuffer(%u) returned %zu = %zu + %zu err %d",
-                __func__, mId, mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err);
+                __func__, mPortId, mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err);
         if (err != NO_ERROR) {
             if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR ||
                     (isOffloaded() && (err == DEAD_OBJECT))) {
@@ -2160,7 +2160,7 @@
                 return 1000000;
             }
             ALOGE("%s(%d): Error %d obtaining an audio buffer, giving up.",
-                    __func__, mId, err);
+                    __func__, mPortId, err);
             return NS_NEVER;
         }
 
@@ -2192,7 +2192,7 @@
         // Sanity check on returned size
         if (ssize_t(writtenSize) < 0 || writtenSize > reqSize) {
             ALOGE("%s(%d): EVENT_MORE_DATA requested %zu bytes but callback returned %zd bytes",
-                    __func__, mId, reqSize, ssize_t(writtenSize));
+                    __func__, mPortId, reqSize, ssize_t(writtenSize));
             return NS_NEVER;
         }
 
@@ -2296,7 +2296,7 @@
 status_t AudioTrack::restoreTrack_l(const char *from)
 {
     ALOGW("%s(%d): dead IAudioTrack, %s, creating a new one from %s()",
-            __func__, mId, isOffloadedOrDirect_l() ? "Offloaded or Direct" : "PCM", from);
+            __func__, mPortId, isOffloadedOrDirect_l() ? "Offloaded or Direct" : "PCM", from);
     ++mSequence;
 
     // refresh the audio configuration cache in this process to make sure we get new
@@ -2354,7 +2354,7 @@
             } else {
                 mStaticProxy->setBufferPosition(bufferPosition);
                 if (bufferPosition == mFrameCount) {
-                    ALOGD("%s(%d): restoring track at end of static buffer", __func__, mId);
+                    ALOGD("%s(%d): restoring track at end of static buffer", __func__, mPortId);
                 }
             }
         }
@@ -2384,7 +2384,7 @@
         mFramesWrittenAtRestore = mFramesWrittenServerOffset;
     }
     if (result != NO_ERROR) {
-        ALOGW("%s(%d): failed status %d, retries %d", __func__, mId, result, retries);
+        ALOGW("%s(%d): failed status %d, retries %d", __func__, mPortId, result, retries);
         if (--retries > 0) {
             // leave time for an eventual race condition to clear before retrying
             usleep(500000);
@@ -2414,7 +2414,7 @@
     //      in which case the use of uint32_t for these counters has bigger issues.
     ALOGE_IF(delta < 0,
             "%s(%d): detected illegal retrograde motion by the server: mServer advanced by %d",
-            __func__, mId, delta);
+            __func__, mPortId, delta);
     mServer = newServer;
     if (delta > 0) { // avoid retrograde
         mPosition += delta;
@@ -2437,7 +2437,7 @@
             "%s(%d): denied "
             "mAfLatency:%u  mAfFrameCount:%zu  mAfSampleRate:%u  sampleRate:%u  speed:%f "
             "mFrameCount:%zu < minFrameCount:%zu",
-            __func__, mId,
+            __func__, mPortId,
             mAfLatency, mAfFrameCount, mAfSampleRate, sampleRate, speed,
             mFrameCount, minFrameCount);
     return allowed;
@@ -2452,8 +2452,13 @@
 status_t AudioTrack::selectPresentation(int presentationId, int programId)
 {
     AutoMutex lock(mLock);
-    ALOGV("%s(%d): PresentationId:%d ProgramId:%d", __func__, mId, presentationId, programId);
-    return mAudioTrack->selectPresentation(presentationId, programId);
+    AudioParameter param = AudioParameter();
+    param.addInt(String8(AudioParameter::keyPresentationId), presentationId);
+    param.addInt(String8(AudioParameter::keyProgramId), programId);
+    ALOGV("%s(%d): PresentationId/ProgramId[%s]",
+            __func__, mPortId, param.toString().string());
+
+    return mAudioTrack->setParameters(param.toString());
 }
 
 VolumeShaper::Status AudioTrack::applyVolumeShaper(
@@ -2478,7 +2483,7 @@
     } else {
         // warn only if not an expected restore failure.
         ALOGW_IF(!((isOffloadedOrDirect_l() || mDoNotReconnect) && status == DEAD_OBJECT),
-                "%s(%d): applyVolumeShaper failed: %d", __func__, mId, status);
+                "%s(%d): applyVolumeShaper failed: %d", __func__, mPortId, status);
     }
     return status;
 }
@@ -2520,7 +2525,7 @@
     }
     status_t status = mProxy->getTimestamp(timestamp);
     LOG_ALWAYS_FATAL_IF(status != OK, "%s(%d): status %d not allowed from proxy getTimestamp",
-            __func__, mId, status);
+            __func__, mPortId, status);
     bool found = false;
     timestamp->mPosition[ExtendedTimestamp::LOCATION_CLIENT] = mFramesWritten;
     timestamp->mTimeNs[ExtendedTimestamp::LOCATION_CLIENT] = 0;
@@ -2564,7 +2569,7 @@
         break; // offloaded tracks handled below
     default:
         LOG_ALWAYS_FATAL("%s(%d): Invalid mState in getTimestamp(): %d",
-               __func__, mId, mState);
+               __func__, mPortId, mState);
         break;
     }
 
@@ -2599,7 +2604,7 @@
                 if (location == ExtendedTimestamp::LOCATION_SERVER) {
                     ALOGW_IF(mPreviousLocation == ExtendedTimestamp::LOCATION_KERNEL,
                             "%s(%d): location moved from kernel to server",
-                            __func__, mId);
+                            __func__, mPortId);
                     // check that the last kernel OK time info exists and the positions
                     // are valid (if they predate the current track, the positions may
                     // be zero or negative).
@@ -2615,7 +2620,7 @@
                             (ets.mPosition[ExtendedTimestamp::LOCATION_SERVER_LASTKERNELOK]
                             - ets.mPosition[ExtendedTimestamp::LOCATION_KERNEL_LASTKERNELOK]);
                     ALOGV("%s(%d): frame adjustment:%lld  timestamp:%s",
-                            __func__, mId, (long long)frames, ets.toString().c_str());
+                            __func__, mPortId, (long long)frames, ets.toString().c_str());
                     if (frames >= ets.mPosition[location]) {
                         timestamp.mPosition = 0;
                     } else {
@@ -2624,7 +2629,7 @@
                 } else if (location == ExtendedTimestamp::LOCATION_KERNEL) {
                     ALOGV_IF(mPreviousLocation == ExtendedTimestamp::LOCATION_SERVER,
                             "%s(%d): location moved from server to kernel",
-                            __func__, mId);
+                            __func__, mPortId);
                 }
 
                 // We update the timestamp time even when paused.
@@ -2648,7 +2653,7 @@
                 mPreviousLocation = location;
             } else {
                 // right after AudioTrack is started, one may not find a timestamp
-                ALOGV("%s(%d): getBestTimestamp did not find timestamp", __func__, mId);
+                ALOGV("%s(%d): getBestTimestamp did not find timestamp", __func__, mPortId);
             }
         }
         if (status == INVALID_OPERATION) {
@@ -2659,7 +2664,7 @@
             // "zero" for NuPlayer).  We don't convert for track restoration as position
             // does not reset.
             ALOGV("%s(%d): timestamp server offset:%lld restore frames:%lld",
-                    __func__, mId,
+                    __func__, mPortId,
                     (long long)mFramesWrittenServerOffset, (long long)mFramesWrittenAtRestore);
             if (mFramesWrittenServerOffset != mFramesWrittenAtRestore) {
                 status = WOULD_BLOCK;
@@ -2667,7 +2672,7 @@
         }
     }
     if (status != NO_ERROR) {
-        ALOGV_IF(status != WOULD_BLOCK, "%s(%d): getTimestamp error:%#x", __func__, mId, status);
+        ALOGV_IF(status != WOULD_BLOCK, "%s(%d): getTimestamp error:%#x", __func__, mPortId, status);
         return status;
     }
     if (isOffloadedOrDirect_l()) {
@@ -2708,7 +2713,7 @@
                     ALOGW_IF(!mTimestampStartupGlitchReported,
                             "%s(%d): startup glitch detected"
                             " deltaTimeUs(%lld) deltaPositionUs(%lld) tsmPosition(%u)",
-                            __func__, mId,
+                            __func__, mPortId,
                             (long long)deltaTimeUs, (long long)deltaPositionByUs,
                             timestamp.mPosition);
                     mTimestampStartupGlitchReported = true;
@@ -2778,7 +2783,7 @@
             if (currentTimeNanos < limitNs) {
                 ALOGD("%s(%d): correcting timestamp time for pause, "
                         "currentTimeNanos: %lld < limitNs: %lld < mStartNs: %lld",
-                        __func__, mId,
+                        __func__, mPortId,
                         (long long)currentTimeNanos, (long long)limitNs, (long long)mStartNs);
                 timestamp.mTime = convertNsToTimespec(limitNs);
                 currentTimeNanos = limitNs;
@@ -2787,7 +2792,7 @@
             // retrograde check
             if (currentTimeNanos < previousTimeNanos) {
                 ALOGW("%s(%d): retrograde timestamp time corrected, %lld < %lld",
-                        __func__, mId,
+                        __func__, mPortId,
                         (long long)currentTimeNanos, (long long)previousTimeNanos);
                 timestamp.mTime = mPreviousTimestamp.mTime;
                 // currentTimeNanos not used below.
@@ -2801,7 +2806,7 @@
                 // Only report once per position instead of spamming the log.
                 if (!mRetrogradeMotionReported) {
                     ALOGW("%s(%d): retrograde timestamp position corrected, %d = %u - %u",
-                            __func__, mId,
+                            __func__, mPortId,
                             deltaPosition,
                             timestamp.mPosition,
                             mPreviousTimestamp.mPosition);
@@ -2822,7 +2827,7 @@
                 const int64_t computedSampleRate =
                         deltaPosition * (long long)NANOS_PER_SECOND / deltaTime;
                 ALOGD("%s(%d): computedSampleRate:%u  sampleRate:%u",
-                        __func__, mId,
+                        __func__, mPortId,
                         (unsigned)computedSampleRate, mSampleRate);
             }
 #endif
@@ -2869,7 +2874,7 @@
 
     result.append(" AudioTrack::dump\n");
     result.appendFormat("  id(%d) status(%d), state(%d), session Id(%d), flags(%#x)\n",
-                        mId, mStatus, mState, mSessionId, mFlags);
+                        mPortId, mStatus, mState, mSessionId, mFlags);
     result.appendFormat("  stream type(%d), left - right volume(%f, %f)\n",
                         (mStreamType == AUDIO_STREAM_DEFAULT) ?
                                 audio_attributes_to_stream_type(&mAttributes) : mStreamType,
@@ -2911,18 +2916,18 @@
 status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback)
 {
     if (callback == 0) {
-        ALOGW("%s(%d): adding NULL callback!", __func__, mId);
+        ALOGW("%s(%d): adding NULL callback!", __func__, mPortId);
         return BAD_VALUE;
     }
     AutoMutex lock(mLock);
     if (mDeviceCallback.unsafe_get() == callback.get()) {
-        ALOGW("%s(%d): adding same callback!", __func__, mId);
+        ALOGW("%s(%d): adding same callback!", __func__, mPortId);
         return INVALID_OPERATION;
     }
     status_t status = NO_ERROR;
     if (mOutput != AUDIO_IO_HANDLE_NONE) {
         if (mDeviceCallback != 0) {
-            ALOGW("%s(%d): callback already present!", __func__, mId);
+            ALOGW("%s(%d): callback already present!", __func__, mPortId);
             AudioSystem::removeAudioDeviceCallback(this, mOutput);
         }
         status = AudioSystem::addAudioDeviceCallback(this, mOutput);
@@ -2935,12 +2940,12 @@
         const sp<AudioSystem::AudioDeviceCallback>& callback)
 {
     if (callback == 0) {
-        ALOGW("%s(%d): removing NULL callback!", __func__, mId);
+        ALOGW("%s(%d): removing NULL callback!", __func__, mPortId);
         return BAD_VALUE;
     }
     AutoMutex lock(mLock);
     if (mDeviceCallback.unsafe_get() != callback.get()) {
-        ALOGW("%s(%d): removing different callback!", __func__, mId);
+        ALOGW("%s(%d): removing different callback!", __func__, mPortId);
         return INVALID_OPERATION;
     }
     mDeviceCallback.clear();
@@ -3046,7 +3051,7 @@
     case STATE_FLUSHED:
         return false;  // we're not active
     default:
-        LOG_ALWAYS_FATAL("%s(%d): Invalid mState in hasStarted(): %d", __func__, mId, mState);
+        LOG_ALWAYS_FATAL("%s(%d): Invalid mState in hasStarted(): %d", __func__, mPortId, mState);
         break;
     }
 
@@ -3063,7 +3068,7 @@
             wait = (ts.mPosition == 0 || ts.mPosition == mStartTs.mPosition);
         }
         ALOGV("%s(%d): hasStarted wait:%d  ts:%u  start position:%lld",
-                __func__, mId,
+                __func__, mPortId,
                 (int)wait,
                 ts.mPosition,
                 (long long)mStartTs.mPosition);
@@ -3085,7 +3090,7 @@
             }
         }
         ALOGV("%s(%d): hasStarted wait:%d  ets:%lld  start position:%lld",
-                __func__, mId,
+                __func__, mPortId,
                 (int)wait,
                 (long long)ets.mPosition[location],
                 (long long)mStartEts.mPosition[location]);
@@ -3161,7 +3166,7 @@
         FALLTHROUGH_INTENDED;
     default:
         LOG_ALWAYS_FATAL_IF(ns < 0, "%s(%d): processAudioBuffer() returned %lld",
-                __func__, mReceiver.mId, (long long)ns);
+                __func__, mReceiver.mPortId, (long long)ns);
         pauseInternal(ns);
         return true;
     }
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index c226557..35a7e05 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -534,9 +534,15 @@
      */
             status_t    getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
 
-    /*
-     * Dumps the state of an audio record.
-     */
+     /* Get the unique port ID assigned to this AudioRecord instance by audio policy manager.
+      * The ID is unique across all audioserver clients and can change during the life cycle
+      * of a given AudioRecord instance if the connection to audioserver is restored.
+      */
+            audio_port_handle_t getPortId() const { return mPortId; };
+
+     /*
+      * Dumps the state of an audio record.
+      */
             status_t    dump(int fd, const Vector<String16>& args) const;
 
 private:
@@ -654,7 +660,7 @@
     audio_input_flags_t     mOrigFlags;             // as specified in constructor or set(), const
 
     audio_session_t         mSessionId;
-    int                     mId;                    // Id from AudioFlinger
+    audio_port_handle_t     mPortId;                    // Id from Audio Policy Manager
     transfer_type           mTransfer;
 
     // Next 5 fields may be changed if IAudioRecord is re-created, but always != 0
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 4b84fd1..8238ea2 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -912,7 +912,14 @@
                 AutoMutex lock(mLock);
                 return mState == STATE_ACTIVE || mState == STATE_STOPPING;
             }
-protected:
+
+    /* Get the unique port ID assigned to this AudioTrack instance by audio policy manager.
+     * The ID is unique across all audioserver clients and can change during the life cycle
+     * of a given AudioTrack instance if the connection to audioserver is restored.
+     */
+            audio_port_handle_t getPortId() const { return mPortId; };
+
+ protected:
     /* copying audio tracks is not allowed */
                         AudioTrack(const AudioTrack& other);
             AudioTrack& operator = (const AudioTrack& other);
@@ -1166,7 +1173,7 @@
 
     audio_session_t         mSessionId;
     int                     mAuxEffectId;
-    int                     mId;                    // Id from AudioFlinger.
+    audio_port_handle_t     mPortId;                    // Id from Audio Policy Manager
 
     mutable Mutex           mLock;
 
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 52cc860..a34b207 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -146,7 +146,7 @@
             afSampleRate = parcel->readInt64();
             afLatencyMs = parcel->readInt32();
             (void)parcel->read(&outputId, sizeof(audio_io_handle_t));
-            (void)parcel->readInt32(&trackId);
+            (void)parcel->read(&portId, sizeof(audio_port_handle_t));
             return NO_ERROR;
         }
 
@@ -164,7 +164,7 @@
             (void)parcel->writeInt64(afSampleRate);
             (void)parcel->writeInt32(afLatencyMs);
             (void)parcel->write(&outputId, sizeof(audio_io_handle_t));
-            (void)parcel->writeInt32(trackId);
+            (void)parcel->write(&portId, sizeof(audio_port_handle_t));
             return NO_ERROR;
         }
 
@@ -181,7 +181,7 @@
         uint32_t afSampleRate;
         uint32_t afLatencyMs;
         audio_io_handle_t outputId;
-        int32_t trackId;
+        audio_port_handle_t portId;
     };
 
     /* CreateRecordInput contains all input arguments sent by AudioRecord to AudioFlinger
@@ -274,7 +274,7 @@
                     return BAD_VALUE;
                 }
             }
-            (void)parcel->readInt32(&trackId);
+            (void)parcel->read(&portId, sizeof(audio_port_handle_t));
             return NO_ERROR;
         }
 
@@ -301,7 +301,7 @@
             } else {
                 (void)parcel->writeInt32(0);
             }
-            (void)parcel->writeInt32(trackId);
+            (void)parcel->write(&portId, sizeof(audio_port_handle_t));
 
             return NO_ERROR;
         }
@@ -318,7 +318,7 @@
         audio_io_handle_t inputId;
         sp<IMemory> cblk;
         sp<IMemory> buffers;
-        int32_t trackId;
+        audio_port_handle_t portId;
     };
 
     // invariant on exit for all APIs that return an sp<>:
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 06975ac..26f76c0 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -746,7 +746,7 @@
         output.afFrameCount = thread->frameCount();
         output.afSampleRate = thread->sampleRate();
         output.afLatencyMs = thread->latency();
-        output.trackId = track == nullptr ? -1 : track->id();
+        output.portId = portId;
 
         // move effect chain to this output thread if an effect on same session was waiting
         // for a track to be created
@@ -1766,7 +1766,7 @@
 
     output.cblk = recordTrack->getCblk();
     output.buffers = recordTrack->getBuffers();
-    output.trackId = recordTrack->id();
+    output.portId = portId;
 
     // return handle to client
     recordHandle = new RecordHandle(recordTrack);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 46e40c7..45d3a06 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -7562,7 +7562,7 @@
         (void)input->stream->dump(fd);
     }
 
-    const double latencyMs = RecordTrack::checkServerLatencySupported(mFormat, input->flags)
+    const double latencyMs = RecordTrack::checkServerLatencySupported(mFormat, flags)
             ? - mTimestamp.getOutputServerLatencyMs(mSampleRate) : 0.;
     if (latencyMs != 0.) {
         dprintf(fd, "  NormalRecord latency ms: %.2lf\n", latencyMs);
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index dd81c71..9a7f1f1 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -502,7 +502,7 @@
 
 void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result)
 {
-    result.appendFormat("Type     Id Active Client Session S  Flags "
+    result.appendFormat("Type     Id Active Client Session Port Id S  Flags "
                         "  Format Chn mask  SRate "
                         "ST Usg CT "
                         " G db  L dB  R dB  VS dB "
@@ -588,7 +588,7 @@
             ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
                     ? 'e' /* error */ : ' ' /* identical */;
 
-    result.appendFormat("%7s %6u %7u %2s 0x%03X "
+    result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
                         "%08X %08X %6u "
                         "%2u %3x %2x "
                         "%5.2g %5.2g %5.2g %5.2g%c "
@@ -596,6 +596,7 @@
             active ? "yes" : "no",
             (mClient == 0) ? getpid() : mClient->pid(),
             mSessionId,
+            mPortId,
             getTrackStateString(),
             mCblk->mFlags,
 
@@ -1886,7 +1887,7 @@
 
 void AudioFlinger::RecordThread::RecordTrack::appendDumpHeader(String8& result)
 {
-    result.appendFormat("Active     Id Client Session S  Flags  "
+    result.appendFormat("Active     Id Client Session Port Id  S  Flags  "
                         " Format Chn mask  SRate Source  "
                         " Server FrmCnt FrmRdy Sil%s\n",
                         isServerLatencySupported() ? "   Latency" : "");
@@ -1894,7 +1895,7 @@
 
 void AudioFlinger::RecordThread::RecordTrack::appendDump(String8& result, bool active)
 {
-    result.appendFormat("%c%5s %6d %6u %7u %2s 0x%03X "
+    result.appendFormat("%c%5s %6d %6u %7u %7u  %2s 0x%03X "
             "%08X %08X %6u %6X "
             "%08X %6zu %6zu %3c",
             isFastTrack() ? 'F' : ' ',
@@ -1902,6 +1903,7 @@
             mId,
             (mClient == 0) ? getpid() : mClient->pid(),
             mSessionId,
+            mPortId,
             getTrackStateString(),
             mCblk->mFlags,
 
@@ -2142,15 +2144,16 @@
 
 void AudioFlinger::MmapThread::MmapTrack::appendDumpHeader(String8& result)
 {
-    result.appendFormat("Client Session   Format Chn mask  SRate Flags %s\n",
+    result.appendFormat("Client Session Port Id  Format Chn mask  SRate Flags %s\n",
                         isOut() ? "Usg CT": "Source");
 }
 
 void AudioFlinger::MmapThread::MmapTrack::appendDump(String8& result, bool active __unused)
 {
-    result.appendFormat("%6u %7u %08X %08X %6u 0x%03X ",
+    result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
             mPid,
             mSessionId,
+            mPortId,
             mFormat,
             mChannelMask,
             mSampleRate,
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 018d9e3..78dbf5f 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -340,14 +340,41 @@
     return NO_ERROR;
 }
 
-void AudioPolicyService::setAppState(uid_t uid, app_state_t state)
+void AudioPolicyService::updateUidStates()
 {
-    {
-        Mutex::Autolock _l(mLock);
-        if (mAudioPolicyManager) {
-            AutoCallerClear acc;
-            mAudioPolicyManager->setAppState(uid, state);
-        }
+    Mutex::Autolock _l(mLock);
+    updateUidStates_l();
+}
+
+void AudioPolicyService::updateUidStates_l()
+{
+    //TODO: implement real concurrent capture policy: for now just apply each app state directly
+    for (size_t i =0; i < mAudioRecordClients.size(); i++) {
+        sp<AudioRecordClient> current = mAudioRecordClients[i];
+        if (!current->active) continue;
+        setAppState_l(current->uid, apmStatFromAmState(mUidPolicy->getUidState(current->uid)));
+    }
+}
+
+/* static */
+app_state_t AudioPolicyService::apmStatFromAmState(int amState) {
+    switch (amState) {
+    case ActivityManager::PROCESS_STATE_UNKNOWN:
+        return APP_STATE_IDLE;
+    case ActivityManager::PROCESS_STATE_TOP:
+        return APP_STATE_TOP;
+    default:
+        break;
+    }
+    return APP_STATE_FOREGROUND;
+}
+
+void AudioPolicyService::setAppState_l(uid_t uid, app_state_t state)
+{
+    AutoCallerClear acc;
+
+    if (mAudioPolicyManager) {
+        mAudioPolicyManager->setAppState(uid, state);
     }
     sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
     if (af) {
@@ -511,7 +538,8 @@
     ActivityManager am;
     am.registerUidObserver(this, ActivityManager::UID_OBSERVER_GONE
             | ActivityManager::UID_OBSERVER_IDLE
-            | ActivityManager::UID_OBSERVER_ACTIVE,
+            | ActivityManager::UID_OBSERVER_ACTIVE
+            | ActivityManager::UID_OBSERVER_PROCSTATE,
             ActivityManager::PROCESS_STATE_UNKNOWN,
             String16("audioserver"));
     status_t res = am.linkToDeath(this);
@@ -538,8 +566,7 @@
     mObserverRegistered = false;
 }
 
-bool AudioPolicyService::UidPolicy::isUidActive(uid_t uid) {
-    if (isServiceUid(uid)) return true;
+void AudioPolicyService::UidPolicy::checkRegistered() {
     bool needToReregister = false;
     {
         Mutex::Autolock _l(mLock);
@@ -549,91 +576,157 @@
         // Looks like ActivityManager has died previously, attempt to re-register.
         registerSelf();
     }
+}
+
+bool AudioPolicyService::UidPolicy::isUidActive(uid_t uid) {
+    if (isServiceUid(uid)) return true;
+    checkRegistered();
     {
         Mutex::Autolock _l(mLock);
         auto overrideIter = mOverrideUids.find(uid);
         if (overrideIter != mOverrideUids.end()) {
-            return overrideIter->second;
+            return overrideIter->second.first;
         }
         // In an absense of the ActivityManager, assume everything to be active.
         if (!mObserverRegistered) return true;
         auto cacheIter = mCachedUids.find(uid);
         if (cacheIter != mCachedUids.end()) {
-            return cacheIter->second;
+            return cacheIter->second.first;
         }
     }
     ActivityManager am;
     bool active = am.isUidActive(uid, String16("audioserver"));
     {
         Mutex::Autolock _l(mLock);
-        mCachedUids.insert(std::pair<uid_t, bool>(uid, active));
+        mCachedUids.insert(std::pair<uid_t,
+                           std::pair<bool, int>>(uid, std::pair<bool, int>(active,
+                                                      ActivityManager::PROCESS_STATE_UNKNOWN)));
     }
     return active;
 }
 
+int AudioPolicyService::UidPolicy::getUidState(uid_t uid) {
+    if (isServiceUid(uid)) {
+        return ActivityManager::PROCESS_STATE_TOP;
+    }
+    checkRegistered();
+    {
+        Mutex::Autolock _l(mLock);
+        auto overrideIter = mOverrideUids.find(uid);
+        if (overrideIter != mOverrideUids.end()) {
+            if (overrideIter->second.first) {
+                if (overrideIter->second.second != ActivityManager::PROCESS_STATE_UNKNOWN) {
+                    return overrideIter->second.second;
+                } else {
+                    auto cacheIter = mCachedUids.find(uid);
+                    if (cacheIter != mCachedUids.end()) {
+                        return cacheIter->second.second;
+                    }
+                }
+            }
+            return ActivityManager::PROCESS_STATE_UNKNOWN;
+        }
+        // In an absense of the ActivityManager, assume everything to be active.
+        if (!mObserverRegistered) {
+            return ActivityManager::PROCESS_STATE_TOP;
+        }
+        auto cacheIter = mCachedUids.find(uid);
+        if (cacheIter != mCachedUids.end()) {
+            if (cacheIter->second.first) {
+                return cacheIter->second.second;
+            } else {
+                return ActivityManager::PROCESS_STATE_UNKNOWN;
+            }
+        }
+    }
+    ActivityManager am;
+    bool active = am.isUidActive(uid, String16("audioserver"));
+    int state = ActivityManager::PROCESS_STATE_UNKNOWN;
+    if (active) {
+        state = am.getUidProcessState(uid, String16("audioserver"));
+    }
+    {
+        Mutex::Autolock _l(mLock);
+        mCachedUids.insert(std::pair<uid_t,
+                           std::pair<bool, int>>(uid, std::pair<bool, int>(active, state)));
+    }
+    return state;
+}
+
 void AudioPolicyService::UidPolicy::onUidActive(uid_t uid) {
-    updateUidCache(uid, true, true);
+    updateUid(&mCachedUids, uid, true, ActivityManager::PROCESS_STATE_UNKNOWN, true);
 }
 
 void AudioPolicyService::UidPolicy::onUidGone(uid_t uid, __unused bool disabled) {
-    updateUidCache(uid, false, false);
+    updateUid(&mCachedUids, uid, false, ActivityManager::PROCESS_STATE_UNKNOWN, false);
 }
 
 void AudioPolicyService::UidPolicy::onUidIdle(uid_t uid, __unused bool disabled) {
-    updateUidCache(uid, false, true);
+    updateUid(&mCachedUids, uid, false, ActivityManager::PROCESS_STATE_UNKNOWN, true);
 }
 
-void AudioPolicyService::UidPolicy::notifyService(uid_t uid, bool active) {
-    sp<AudioPolicyService> service = mService.promote();
-    if (service != nullptr) {
-        service->setAppState(uid, active ?
-                              APP_STATE_FOREGROUND :
-                              APP_STATE_IDLE);
+void AudioPolicyService::UidPolicy::onUidStateChanged(uid_t uid,
+                                                      int32_t procState,
+                                                      int64_t procStateSeq __unused) {
+    if (procState != ActivityManager::PROCESS_STATE_UNKNOWN) {
+        updateUid(&mCachedUids, uid, true, procState, true);
     }
 }
 
 void AudioPolicyService::UidPolicy::updateOverrideUid(uid_t uid, bool active, bool insert) {
-    if (isServiceUid(uid)) return;
-    bool wasOverridden = false, wasActive = false;
-    {
-        Mutex::Autolock _l(mLock);
-        updateUidLocked(&mOverrideUids, uid, active, insert, &wasOverridden, &wasActive);
-    }
-    if (!wasOverridden && insert) {
-        notifyService(uid, active);  // Started to override.
-    } else if (wasOverridden && !insert) {
-        notifyService(uid, isUidActive(uid));  // Override ceased, notify with ground truth.
-    } else if (wasActive != active) {
-        notifyService(uid, active);  // Override updated.
+    updateUid(&mOverrideUids, uid, active, ActivityManager::PROCESS_STATE_UNKNOWN, insert);
+}
+
+void AudioPolicyService::UidPolicy::notifyService() {
+    sp<AudioPolicyService> service = mService.promote();
+    if (service != nullptr) {
+        service->updateUidStates();
     }
 }
 
-void AudioPolicyService::UidPolicy::updateUidCache(uid_t uid, bool active, bool insert) {
-    if (isServiceUid(uid)) return;
-    bool wasActive = false;
+void AudioPolicyService::UidPolicy::updateUid(std::unordered_map<uid_t,
+                                              std::pair<bool, int>> *uids,
+                                              uid_t uid,
+                                              bool active,
+                                              int state,
+                                              bool insert) {
+    if (isServiceUid(uid)) {
+        return;
+    }
+    bool wasActive = isUidActive(uid);
+    int previousState = getUidState(uid);
     {
         Mutex::Autolock _l(mLock);
-        updateUidLocked(&mCachedUids, uid, active, insert, nullptr, &wasActive);
-        // Do not notify service if currently overridden.
-        if (mOverrideUids.find(uid) != mOverrideUids.end()) return;
+        updateUidLocked(uids, uid, active, state, insert);
     }
-    bool nowActive = active && insert;
-    if (wasActive != nowActive) notifyService(uid, nowActive);
+    if (wasActive != isUidActive(uid) || state != previousState) {
+        notifyService();
+    }
 }
 
-void AudioPolicyService::UidPolicy::updateUidLocked(std::unordered_map<uid_t, bool> *uids,
-        uid_t uid, bool active, bool insert, bool *wasThere, bool *wasActive) {
+void AudioPolicyService::UidPolicy::updateUidLocked(std::unordered_map<uid_t,
+                                                    std::pair<bool, int>> *uids,
+                                                    uid_t uid,
+                                                    bool active,
+                                                    int state,
+                                                    bool insert) {
     auto it = uids->find(uid);
     if (it != uids->end()) {
-        if (wasThere != nullptr) *wasThere = true;
-        if (wasActive != nullptr) *wasActive = it->second;
         if (insert) {
-            it->second = active;
+            if (state == ActivityManager::PROCESS_STATE_UNKNOWN) {
+                it->second.first = active;
+            }
+            if (it->second.first) {
+                it->second.second = state;
+            } else {
+                it->second.second = ActivityManager::PROCESS_STATE_UNKNOWN;
+            }
         } else {
             uids->erase(it);
         }
-    } else if (insert) {
-        uids->insert(std::pair<uid_t, bool>(uid, active));
+    } else if (insert && (state == ActivityManager::PROCESS_STATE_UNKNOWN)) {
+        uids->insert(std::pair<uid_t, std::pair<bool, int>>(uid,
+                                      std::pair<bool, int>(active, state)));
     }
 }
 
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index ec32511..4d7235f 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -253,7 +253,7 @@
     virtual status_t shellCommand(int in, int out, int err, Vector<String16>& args);
 
     // Sets whether the given UID records only silence
-    virtual void setAppState(uid_t uid, app_state_t state);
+    virtual void setAppState_l(uid_t uid, app_state_t state);
 
     // Overrides the UID state as if it is idle
     status_t handleSetUidState(Vector<String16>& args, int err);
@@ -271,6 +271,11 @@
 
     status_t getAudioPolicyEffects(sp<AudioPolicyEffects>& audioPolicyEffects);
 
+    app_state_t apmStatFromAmState(int amState);
+
+    void updateUidStates();
+    void updateUidStates_l();
+
     // If recording we need to make sure the UID is allowed to do that. If the UID is idle
     // then it cannot record and gets buffers with zeros - silence. As soon as the UID
     // transitions to an active state we will start reporting buffers with data. This approach
@@ -289,6 +294,7 @@
         void binderDied(const wp<IBinder> &who) override;
 
         bool isUidActive(uid_t uid);
+        int getUidState(uid_t uid);
         void setAssistantUid(uid_t uid) { mAssistantUid = uid; }
         bool isAssistantUid(uid_t uid) { return uid == mAssistantUid; }
         void setA11yUids(const std::vector<uid_t>& uids) { mA11yUids.clear(); mA11yUids = uids; }
@@ -298,22 +304,26 @@
         void onUidActive(uid_t uid) override;
         void onUidGone(uid_t uid, bool disabled) override;
         void onUidIdle(uid_t uid, bool disabled) override;
+        void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq);
 
         void addOverrideUid(uid_t uid, bool active) { updateOverrideUid(uid, active, true); }
         void removeOverrideUid(uid_t uid) { updateOverrideUid(uid, false, false); }
 
-    private:
-        void notifyService(uid_t uid, bool active);
+        void updateUid(std::unordered_map<uid_t, std::pair<bool, int>> *uids,
+                       uid_t uid, bool active, int state, bool insert);
+
+     private:
+        void notifyService();
         void updateOverrideUid(uid_t uid, bool active, bool insert);
-        void updateUidCache(uid_t uid, bool active, bool insert);
-        void updateUidLocked(std::unordered_map<uid_t, bool> *uids,
-                uid_t uid, bool active, bool insert, bool *wasThere, bool *wasActive);
+        void updateUidLocked(std::unordered_map<uid_t, std::pair<bool, int>> *uids,
+                             uid_t uid, bool active, int state, bool insert);
+        void checkRegistered();
 
         wp<AudioPolicyService> mService;
         Mutex mLock;
         bool mObserverRegistered;
-        std::unordered_map<uid_t, bool> mOverrideUids;
-        std::unordered_map<uid_t, bool> mCachedUids;
+        std::unordered_map<uid_t, std::pair<bool, int>> mOverrideUids;
+        std::unordered_map<uid_t, std::pair<bool, int>> mCachedUids;
         uid_t mAssistantUid;
         std::vector<uid_t> mA11yUids;
     };
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 064863f..d332f6e 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -536,6 +536,7 @@
         void onUidGone(uid_t uid, bool disabled);
         void onUidActive(uid_t uid);
         void onUidIdle(uid_t uid, bool disabled);
+        void onUidStateChanged(uid_t uid __unused, int32_t procState __unused, int64_t procStateSeq __unused) {}
 
         void addOverrideUid(uid_t uid, String16 callingPackage, bool active);
         void removeOverrideUid(uid_t uid, String16 callingPackage);