Merge "Fix build. Missing vendor_tag header."
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index c724949..45134c4 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -464,7 +464,7 @@
     // These are private to processAudioBuffer(), and are not protected by a lock
     uint32_t                mRemainingFrames;       // number of frames to request in obtainBuffer()
     bool                    mRetryOnPartialBuffer;  // sleep and retry after partial obtainBuffer()
-    int                     mObservedSequence;      // last observed value of mSequence
+    uint32_t                mObservedSequence;      // last observed value of mSequence
 
     uint32_t                mMarkerPosition;    // in wrapping (overflow) frame units
     bool                    mMarkerReached;
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 706344a..5abab8a 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -200,12 +200,16 @@
     static status_t setPhoneState(audio_mode_t state);
     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 audio_io_handle_t getOutput(audio_stream_type_t stream,
                                         uint32_t samplingRate = 0,
                                         audio_format_t format = AUDIO_FORMAT_DEFAULT,
                                         audio_channel_mask_t channelMask = AUDIO_CHANNEL_OUT_STEREO,
                                         audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
                                         const audio_offload_info_t *offloadInfo = NULL);
+
     static status_t startOutput(audio_io_handle_t output,
                                 audio_stream_type_t stream,
                                 int session);
@@ -213,11 +217,15 @@
                                audio_stream_type_t stream,
                                int session);
     static void releaseOutput(audio_io_handle_t output);
+
+    // Client must successfully hand off the handle reference to AudioFlinger via openRecord(),
+    // or release it with releaseInput().
     static audio_io_handle_t getInput(audio_source_t inputSource,
                                     uint32_t samplingRate,
                                     audio_format_t format,
                                     audio_channel_mask_t channelMask,
                                     int sessionId);
+
     static status_t startInput(audio_io_handle_t input);
     static status_t stopInput(audio_io_handle_t input);
     static void releaseInput(audio_io_handle_t input);
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 88a5a4c..644e55c 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -661,6 +661,7 @@
     audio_track_cblk_t*     mCblk;                  // re-load after mLock.unlock()
 
     sp<AudioTrackThread>    mAudioTrackThread;
+
     float                   mVolume[2];
     float                   mSendLevel;
     mutable uint32_t        mSampleRate;            // mutable because getSampleRate() can update it.
@@ -674,7 +675,10 @@
     audio_stream_type_t     mStreamType;
     uint32_t                mChannelCount;
     audio_channel_mask_t    mChannelMask;
+    sp<IMemory>             mSharedBuffer;
     transfer_type           mTransfer;
+    audio_offload_info_t    mOffloadInfoCopy;
+    const audio_offload_info_t* mOffloadInfo;
 
     // mFrameSize is equal to mFrameSizeAF for non-PCM or 16-bit PCM data.  For 8-bit PCM data, it's
     // twice as large as mFrameSize because data is expanded to 16-bit before it's stored in buffer.
@@ -715,7 +719,6 @@
     bool                    mRetryOnPartialBuffer;  // sleep and retry after partial obtainBuffer()
     uint32_t                mObservedSequence;      // last observed value of mSequence
 
-    sp<IMemory>             mSharedBuffer;
     uint32_t                mLoopPeriod;            // in frames, zero means looping is disabled
 
     uint32_t                mMarkerPosition;        // in wrapping (overflow) frame units
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index c9cffe3..a794e87 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -67,6 +67,9 @@
                                 size_t frameCount,
                                 track_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 tid,  // -1 means unused, otherwise must be valid non-0
                                 int *sessionId,
@@ -78,6 +81,9 @@
                                 status_t *status) = 0;
 
     virtual sp<IAudioRecord> openRecord(
+                                // 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 input,
                                 uint32_t sampleRate,
                                 audio_format_t format,
@@ -188,6 +194,7 @@
                                     effect_descriptor_t *pDesc,
                                     const sp<IEffectClient>& client,
                                     int32_t priority,
+                                    // AudioFlinger doesn't take over handle reference from client
                                     audio_io_handle_t output,
                                     int sessionId,
                                     status_t *status,
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 3a87474..db8216b 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -215,6 +215,8 @@
     bool findData(uint32_t key, uint32_t *type,
                   const void **data, size_t *size) const;
 
+    bool hasData(uint32_t key) const;
+
     void dumpToLog() const;
 
 protected:
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 98697f5..6565a16 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -775,7 +775,7 @@
         mRetryOnPartialBuffer = false;
     }
     size_t misalignment = mProxy->getMisalignment();
-    int32_t sequence = mSequence;
+    uint32_t sequence = mSequence;
 
     // These fields don't need to be cached, because they are assigned only by set():
     //      mTransfer, mCbf, mUserData, mSampleRate, mFrameSize
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 5c4be46..72be5ca 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -222,6 +222,7 @@
         ALOGE("Invalid transfer type %d", transferType);
         return BAD_VALUE;
     }
+    mSharedBuffer = sharedBuffer;
     mTransfer = transferType;
 
     // FIXME "int" here is legacy and will be replaced by size_t later
@@ -250,6 +251,11 @@
     if (streamType == AUDIO_STREAM_DEFAULT) {
         streamType = AUDIO_STREAM_MUSIC;
     }
+    if (uint32_t(streamType) >= AUDIO_STREAM_CNT) {
+        ALOGE("Invalid stream type %d", streamType);
+        return BAD_VALUE;
+    }
+    mStreamType = streamType;
 
     status_t status;
     if (sampleRate == 0) {
@@ -272,6 +278,7 @@
         ALOGE("Invalid format %d", format);
         return BAD_VALUE;
     }
+    mFormat = format;
 
     if (!audio_is_output_channel(channelMask)) {
         ALOGE("Invalid channel mask %#x", channelMask);
@@ -323,6 +330,16 @@
         return BAD_VALUE;
     }
 
+    // Make copy of input parameter offloadInfo so that in the future:
+    //  (a) createTrack_l doesn't need it as an input parameter
+    //  (b) we can support re-creation of offloaded tracks
+    if (offloadInfo != NULL) {
+        mOffloadInfoCopy = *offloadInfo;
+        mOffloadInfo = &mOffloadInfoCopy;
+    } else {
+        mOffloadInfo = NULL;
+    }
+
     mVolume[LEFT] = 1.0f;
     mVolume[RIGHT] = 1.0f;
     mSendLevel = 0.0f;
@@ -369,9 +386,6 @@
     }
 
     mStatus = NO_ERROR;
-    mStreamType = streamType;
-    mFormat = format;
-    mSharedBuffer = sharedBuffer;
     mState = STATE_STOPPED;
     mUserData = user;
     mLoopPeriod = 0;
@@ -1011,6 +1025,11 @@
         ALOGE("Could not get control block");
         return NO_INIT;
     }
+    void *iMemPointer = iMem->pointer();
+    if (iMemPointer == NULL) {
+        ALOGE("Could not get control block pointer");
+        return NO_INIT;
+    }
     // invariant that mAudioTrack != 0 is true only after set() returns successfully
     if (mAudioTrack != 0) {
         mAudioTrack->asBinder()->unlinkToDeath(mDeathNotifier, this);
@@ -1018,7 +1037,7 @@
     }
     mAudioTrack = track;
     mCblkMemory = iMem;
-    audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMem->pointer());
+    audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
     mCblk = cblk;
     size_t temp = cblk->frameCount_;
     if (temp < frameCount || (frameCount == 0 && temp == 0)) {
@@ -1617,7 +1636,6 @@
         size_t reqSize = audioBuffer.size;
         mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
         size_t writtenSize = audioBuffer.size;
-        size_t writtenFrames = writtenSize / mFrameSize;
 
         // Sanity check on returned size
         if (ssize_t(writtenSize) < 0 || writtenSize > reqSize) {
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 3aaff88..86a4d74 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -138,6 +138,17 @@
             name = reply.readString8();
             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();
+                }
+            }
         }
         if (status != NULL) {
             *status = lStatus;
@@ -798,6 +809,7 @@
                         (audio_stream_type_t) streamType, sampleRate, format,
                         channelMask, frameCount, &flags, buffer, output, tid,
                         &sessionId, name, clientUid, &status);
+                LOG_ALWAYS_FATAL_IF((track != 0) != (status == NO_ERROR));
             }
             reply->writeInt32(flags);
             reply->writeInt32(sessionId);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 92b9a92..bf5271e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -422,7 +422,9 @@
         ALOGV("video late by %lld us (%.2f secs)",
              mVideoLateByUs, mVideoLateByUs / 1E6);
     } else {
-        ALOGV("rendering video at media time %.2f secs", mediaTimeUs / 1E6);
+        ALOGV("rendering video at media time %.2f secs",
+                (mFlags & FLAG_REAL_TIME ? realTimeUs :
+                (realTimeUs + mAnchorTimeMediaUs - mAnchorTimeRealUs)) / 1E6);
         if (mSoftRenderer != NULL) {
             mSoftRenderer->render(entry->mBuffer->data(), entry->mBuffer->size(), NULL);
         }
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 9c89e82..dfb5c04 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -39,6 +39,7 @@
 #include <utils/String8.h>
 
 #include <byteswap.h>
+#include "include/ID3.h"
 
 namespace android {
 
@@ -1787,6 +1788,18 @@
             break;
         }
 
+        case FOURCC('I', 'D', '3', '2'):
+        {
+            if (chunk_data_size < 6) {
+                return ERROR_MALFORMED;
+            }
+
+            parseID3v2MetaData(data_offset + 6);
+
+            *offset += chunk_size;
+            break;
+        }
+
         case FOURCC('-', '-', '-', '-'):
         {
             mLastCommentMean.clear();
@@ -2167,7 +2180,7 @@
             break;
     }
 
-    if (size >= 8 && metadataKey) {
+    if (size >= 8 && metadataKey && !mFileMetaData->hasData(metadataKey)) {
         if (metadataKey == kKeyAlbumArt) {
             mFileMetaData->setData(
                     kKeyAlbumArt, MetaData::TYPE_NONE,
@@ -2316,6 +2329,62 @@
     return OK;
 }
 
+void MPEG4Extractor::parseID3v2MetaData(off64_t offset) {
+    ID3 id3(mDataSource, true /* ignorev1 */, offset);
+
+    if (id3.isValid()) {
+        struct Map {
+            int key;
+            const char *tag1;
+            const char *tag2;
+        };
+        static const Map kMap[] = {
+            { kKeyAlbum, "TALB", "TAL" },
+            { kKeyArtist, "TPE1", "TP1" },
+            { kKeyAlbumArtist, "TPE2", "TP2" },
+            { kKeyComposer, "TCOM", "TCM" },
+            { kKeyGenre, "TCON", "TCO" },
+            { kKeyTitle, "TIT2", "TT2" },
+            { kKeyYear, "TYE", "TYER" },
+            { kKeyAuthor, "TXT", "TEXT" },
+            { kKeyCDTrackNumber, "TRK", "TRCK" },
+            { kKeyDiscNumber, "TPA", "TPOS" },
+            { kKeyCompilation, "TCP", "TCMP" },
+        };
+        static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
+
+        for (size_t i = 0; i < kNumMapEntries; ++i) {
+            if (!mFileMetaData->hasData(kMap[i].key)) {
+                ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1);
+                if (it->done()) {
+                    delete it;
+                    it = new ID3::Iterator(id3, kMap[i].tag2);
+                }
+
+                if (it->done()) {
+                    delete it;
+                    continue;
+                }
+
+                String8 s;
+                it->getString(&s);
+                delete it;
+
+                mFileMetaData->setCString(kMap[i].key, s);
+            }
+        }
+
+        size_t dataSize;
+        String8 mime;
+        const void *data = id3.getAlbumArt(&dataSize, &mime);
+
+        if (data) {
+            mFileMetaData->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
+            mFileMetaData->setCString(kKeyAlbumArtMIME, mime.string());
+        }
+    }
+}
+
 sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
     status_t err;
     if ((err = readMetaData()) != OK) {
diff --git a/media/libstagefright/MetaData.cpp b/media/libstagefright/MetaData.cpp
index 7b60afc..1daead7 100644
--- a/media/libstagefright/MetaData.cpp
+++ b/media/libstagefright/MetaData.cpp
@@ -221,6 +221,16 @@
     return true;
 }
 
+bool MetaData::hasData(uint32_t key) const {
+    ssize_t i = mItems.indexOfKey(key);
+
+    if (i < 0) {
+        return false;
+    }
+
+    return true;
+}
+
 MetaData::typed_data::typed_data()
     : mType(0),
       mSize(0) {
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index a486522..f0f203c 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -56,14 +56,14 @@
     DISALLOW_EVIL_CONSTRUCTORS(MemorySource);
 };
 
-ID3::ID3(const sp<DataSource> &source, bool ignoreV1)
+ID3::ID3(const sp<DataSource> &source, bool ignoreV1, off64_t offset)
     : mIsValid(false),
       mData(NULL),
       mSize(0),
       mFirstFrameOffset(0),
       mVersion(ID3_UNKNOWN),
       mRawSize(0) {
-    mIsValid = parseV2(source);
+    mIsValid = parseV2(source, offset);
 
     if (!mIsValid && !ignoreV1) {
         mIsValid = parseV1(source);
@@ -79,7 +79,7 @@
       mRawSize(0) {
     sp<MemorySource> source = new MemorySource(data, size);
 
-    mIsValid = parseV2(source);
+    mIsValid = parseV2(source, 0);
 
     if (!mIsValid && !ignoreV1) {
         mIsValid = parseV1(source);
@@ -115,7 +115,7 @@
     return true;
 }
 
-bool ID3::parseV2(const sp<DataSource> &source) {
+bool ID3::parseV2(const sp<DataSource> &source, off64_t offset) {
 struct id3_header {
     char id[3];
     uint8_t version_major;
@@ -126,7 +126,7 @@
 
     id3_header header;
     if (source->readAt(
-                0, &header, sizeof(header)) != (ssize_t)sizeof(header)) {
+                offset, &header, sizeof(header)) != (ssize_t)sizeof(header)) {
         return false;
     }
 
@@ -185,7 +185,7 @@
     mSize = size;
     mRawSize = mSize + sizeof(header);
 
-    if (source->readAt(sizeof(header), mData, mSize) != (ssize_t)mSize) {
+    if (source->readAt(offset + sizeof(header), mData, mSize) != (ssize_t)mSize) {
         free(mData);
         mData = NULL;
 
diff --git a/media/libstagefright/include/ID3.h b/media/libstagefright/include/ID3.h
index cca83ab..e83f3ef 100644
--- a/media/libstagefright/include/ID3.h
+++ b/media/libstagefright/include/ID3.h
@@ -35,7 +35,7 @@
         ID3_V2_4,
     };
 
-    ID3(const sp<DataSource> &source, bool ignoreV1 = false);
+    ID3(const sp<DataSource> &source, bool ignoreV1 = false, off64_t offset = 0);
     ID3(const uint8_t *data, size_t size, bool ignoreV1 = false);
     ~ID3();
 
@@ -86,7 +86,7 @@
     size_t mRawSize;
 
     bool parseV1(const sp<DataSource> &source);
-    bool parseV2(const sp<DataSource> &source);
+    bool parseV2(const sp<DataSource> &source, off64_t offset);
     void removeUnsynchronization();
     bool removeUnsynchronizationV2_4(bool iTunesHack);
 
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index bd5e4b9..7b4bc6d 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -97,6 +97,7 @@
     status_t parseChunk(off64_t *offset, int depth);
     status_t parseITunesMetaData(off64_t offset, size_t size);
     status_t parse3GPPMetaData(off64_t offset, size_t size, int depth);
+    void parseID3v2MetaData(off64_t offset);
 
     status_t updateAudioTrackInfoFromESDS_MPEG4Audio(
             const void *esds_data, size_t esds_size);
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index 930f0b0..c4f87a0 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -331,7 +331,7 @@
 
 void MtpDataPacket::putString(const uint16_t* string) {
     int count = 0;
-    for (int i = 0; i < 256; i++) {
+    for (int i = 0; i <= MTP_STRING_MAX_CHARACTER_NUMBER; i++) {
         if (string[i])
             count++;
         else
diff --git a/media/mtp/MtpStringBuffer.cpp b/media/mtp/MtpStringBuffer.cpp
index fe8cf04..f3420a4 100644
--- a/media/mtp/MtpStringBuffer.cpp
+++ b/media/mtp/MtpStringBuffer.cpp
@@ -56,42 +56,47 @@
 }
 
 void MtpStringBuffer::set(const char* src) {
-    int length = strlen(src);
-    if (length >= sizeof(mBuffer))
-        length = sizeof(mBuffer) - 1;
-    memcpy(mBuffer, src, length);
-
     // count the characters
     int count = 0;
     char ch;
-    while ((ch = *src++) != 0) {
+    char* dest = (char*)mBuffer;
+
+    while ((ch = *src++) != 0 && count < MTP_STRING_MAX_CHARACTER_NUMBER) {
         if ((ch & 0x80) == 0) {
             // single byte character
+            *dest++ = ch;
         } else if ((ch & 0xE0) == 0xC0) {
             // two byte character
-            if (! *src++) {
+            char ch1 = *src++;
+            if (! ch1) {
                 // last character was truncated, so ignore last byte
-                length--;
                 break;
             }
+
+            *dest++ = ch;
+            *dest++ = ch1;
         } else if ((ch & 0xF0) == 0xE0) {
             // 3 byte char
-            if (! *src++) {
+            char ch1 = *src++;
+            if (! ch1) {
                 // last character was truncated, so ignore last byte
-                length--;
                 break;
             }
-            if (! *src++) {
-                // last character was truncated, so ignore last two bytes
-                length -= 2;
+            char ch2 = *src++;
+            if (! ch2) {
+                // last character was truncated, so ignore last byte
                 break;
             }
+
+            *dest++ = ch;
+            *dest++ = ch1;
+            *dest++ = ch2;
         }
         count++;
     }
 
-    mByteCount = length + 1;
-    mBuffer[length] = 0;
+    *dest++ = 0;
+    mByteCount = dest - (char*)mBuffer;
     mCharCount = count;
 }
 
@@ -100,7 +105,7 @@
     uint16_t ch;
     uint8_t* dest = mBuffer;
 
-    while ((ch = *src++) != 0 && count < 255) {
+    while ((ch = *src++) != 0 && count < MTP_STRING_MAX_CHARACTER_NUMBER) {
         if (ch >= 0x0800) {
             *dest++ = (uint8_t)(0xE0 | (ch >> 12));
             *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F));
diff --git a/media/mtp/MtpStringBuffer.h b/media/mtp/MtpStringBuffer.h
index cbc8307..e5150df 100644
--- a/media/mtp/MtpStringBuffer.h
+++ b/media/mtp/MtpStringBuffer.h
@@ -19,6 +19,9 @@
 
 #include <stdint.h>
 
+// Max Character number of a MTP String
+#define MTP_STRING_MAX_CHARACTER_NUMBER             255
+
 namespace android {
 
 class MtpDataPacket;
@@ -29,7 +32,7 @@
 private:
     // mBuffer contains string in UTF8 format
     // maximum 3 bytes/character, with 1 extra for zero termination
-    uint8_t         mBuffer[255 * 3 + 1];
+    uint8_t         mBuffer[MTP_STRING_MAX_CHARACTER_NUMBER * 3 + 1];
     int             mCharCount;
     int             mByteCount;
 
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 780ecf1..1257161 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -559,6 +559,7 @@
 
         track = thread->createTrack_l(client, streamType, sampleRate, format,
                 channelMask, frameCount, sharedBuffer, lSessionId, flags, tid, clientUid, &lStatus);
+        LOG_ALWAYS_FATAL_IF((track != 0) != (lStatus == NO_ERROR));
         // we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless
 
         // move effect chain to this output thread if an effect on same session was waiting
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index a79d0e3..d5a0e21 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1339,6 +1339,7 @@
         // but TimedTrack::create() is a factory that could fail by returning NULL
         lStatus = track != 0 ? track->initCheck() : (status_t) NO_MEMORY;
         if (lStatus != NO_ERROR) {
+            ALOGE("createTrack_l() initCheck failed %d; no control block?", lStatus);
             track.clear();
             goto Exit;
         }