Merge "Fix the CameraHardwareInterface::setPreviewWindow comment."
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index 03a6bbb..5505f14 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -65,8 +65,8 @@
 {
     pContext->mCaptureIdx = 0;
     pContext->mCurrentBuf = 0;
-    memset(pContext->mCaptureBuf[0], 0, VISUALIZER_CAPTURE_SIZE_MAX);
-    memset(pContext->mCaptureBuf[1], 0, VISUALIZER_CAPTURE_SIZE_MAX);
+    memset(pContext->mCaptureBuf[0], 0x80, VISUALIZER_CAPTURE_SIZE_MAX);
+    memset(pContext->mCaptureBuf[1], 0x80, VISUALIZER_CAPTURE_SIZE_MAX);
 }
 
 //----------------------------------------------------------------------------
diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp
index 0f3e245..88b8c86 100644
--- a/media/libmedia/AudioEffect.cpp
+++ b/media/libmedia/AudioEffect.cpp
@@ -228,24 +228,32 @@
                               void *replyData)
 {
     if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
+        LOGV("command() bad status %d", mStatus);
         return INVALID_OPERATION;
     }
 
+    if ((cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) &&
+            (replySize == NULL || *replySize != sizeof(status_t) || replyData == NULL)) {
+        return BAD_VALUE;
+    }
+
     status_t status = mIEffect->command(cmdCode, cmdSize, cmdData, replySize, replyData);
     if (status != NO_ERROR) {
         return status;
     }
-    status = *(status_t *)replyData;
-    if (status != NO_ERROR) {
-        return status;
+
+    if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) {
+        status = *(status_t *)replyData;
+        if (status != NO_ERROR) {
+            return status;
+        }
+        if (cmdCode == EFFECT_CMD_ENABLE) {
+            android_atomic_or(1, &mEnabled);
+        } else {
+            android_atomic_and(~1, &mEnabled);
+        }
     }
 
-    if (cmdCode == EFFECT_CMD_ENABLE) {
-        android_atomic_or(1, &mEnabled);
-    }
-    if (cmdCode == EFFECT_CMD_DISABLE) {
-        android_atomic_and(~1, &mEnabled);
-    }
     return status;
 }
 
diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp
index 39552b6..68f2e9b 100644
--- a/media/libmedia/Visualizer.cpp
+++ b/media/libmedia/Visualizer.cpp
@@ -169,11 +169,13 @@
     status_t status = NO_ERROR;
     if (mEnabled) {
         uint32_t replySize = mCaptureSize;
-        status_t status = command(VISU_CMD_CAPTURE, 0, NULL, &replySize, waveform);
+        status = command(VISU_CMD_CAPTURE, 0, NULL, &replySize, waveform);
+        LOGV("getWaveForm() command returned %d", status);
         if (replySize == 0) {
             status = NOT_ENOUGH_DATA;
         }
     } else {
+        LOGV("getWaveForm() disabled");
         memset(waveform, 0x80, mCaptureSize);
     }
     return status;
@@ -191,7 +193,7 @@
     status_t status = NO_ERROR;
     if (mEnabled) {
         uint8_t buf[mCaptureSize];
-        status_t status = getWaveForm(buf);
+        status = getWaveForm(buf);
         if (status == NO_ERROR) {
             status = doFft(fft, buf);
         }
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index ba1e218..e6c2f7e 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -1541,20 +1541,52 @@
         int32_t isSync = false;
         meta_data->findInt32(kKeyIsSyncFrame, &isSync);
 
+        /*
+         * The original timestamp found in the data buffer will be modified as below:
+         *
+         * There is a playback offset into this track if the track's start time
+         * is not the same as the movie start time, which will be recorded in edst
+         * box of the output file. The playback offset is to make sure that the
+         * starting time of the audio/video tracks are synchronized. Although the
+         * track's media timestamp may be subject to various modifications
+         * as outlined below, the track's playback offset time remains unchanged
+         * once the first data buffer of the track is received.
+         *
+         * The media time stamp will be calculated by subtracting the playback offset
+         * (and potential pause durations) from the original timestamp in the buffer.
+         *
+         * If this track is a video track for a real-time recording application with
+         * both audio and video tracks, its media timestamp will subject to further
+         * modification based on the media clock of the audio track. This modification
+         * is needed for the purpose of maintaining good audio/video synchronization.
+         *
+         * If the recording session is paused and resumed multiple times, the track
+         * media timestamp will be modified as if the  recording session had never been
+         * paused at all during playback of the recorded output file. In other words,
+         * the output file will have no memory of pause/resume durations.
+         *
+         */
         CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
+        LOGV("%s timestampUs: %lld", mIsAudio? "Audio": "Video", timestampUs);
 
 ////////////////////////////////////////////////////////////////////////////////
         if (mSampleSizes.empty()) {
             mStartTimestampUs = timestampUs;
             mOwner->setStartTimestampUs(mStartTimestampUs);
+            previousPausedDurationUs = mStartTimestampUs;
         }
 
         if (mResumed) {
-            previousPausedDurationUs += (timestampUs - mTrackDurationUs - lastDurationUs);
+            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
+            CHECK(durExcludingEarlierPausesUs >= 0);
+            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
+            CHECK(pausedDurationUs >= lastDurationUs);
+            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
             mResumed = false;
         }
 
         timestampUs -= previousPausedDurationUs;
+        CHECK(timestampUs >= 0);
         if (mIsRealTimeRecording && !mIsAudio) {
             // The minor adjustment on the timestamp is heuristic/experimental
             // We are adjusting the timestamp to reduce the fluctuation of the duration
@@ -1590,8 +1622,8 @@
             }
         }
 
-        LOGV("time stamp: %lld and previous paused duration %lld",
-                timestampUs, previousPausedDurationUs);
+        LOGV("%s media time stamp: %lld and previous paused duration %lld",
+                mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs);
         if (timestampUs > mTrackDurationUs) {
             mTrackDurationUs = timestampUs;
         }
@@ -1873,6 +1905,7 @@
 
             // First elst entry: specify the starting time offset
             int64_t offsetUs = mStartTimestampUs - moovStartTimeUs;
+            LOGV("OffsetUs: %lld", offsetUs);
             int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6;
             mOwner->writeInt32(seg);         // in mvhd timecale
             mOwner->writeInt32(-1);          // starting time offset
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
index 332bab3..2743b2f 100644
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ b/media/libstagefright/NuHTTPDataSource.cpp
@@ -96,6 +96,11 @@
     return connect(host, port, path, headers, offset);
 }
 
+static bool IsRedirectStatusCode(int httpStatus) {
+    return httpStatus == 301 || httpStatus == 302
+        || httpStatus == 303 || httpStatus == 307;
+}
+
 status_t NuHTTPDataSource::connect(
         const char *host, unsigned port, const char *path,
         const String8 &headers,
@@ -161,7 +166,7 @@
             return err;
         }
 
-        if (httpStatus == 302) {
+        if (IsRedirectStatusCode(httpStatus)) {
             string value;
             CHECK(mHTTP.find_header_value("Location", &value));
 
diff --git a/media/mtp/MtpObjectInfo.cpp b/media/mtp/MtpObjectInfo.cpp
index dd4304e..ea68c3b 100644
--- a/media/mtp/MtpObjectInfo.cpp
+++ b/media/mtp/MtpObjectInfo.cpp
@@ -101,7 +101,7 @@
             mImagePixWidth, mImagePixHeight, mImagePixDepth);
     LOGD("  mParent: %08X mAssociationType: %04X mAssociationDesc: %04X\n",
             mParent, mAssociationType, mAssociationDesc);
-    LOGD("  mSequenceNumber: %d mDateCreated: %d mDateModified: %d mKeywords: %s\n",
+    LOGD("  mSequenceNumber: %d mDateCreated: %ld mDateModified: %ld mKeywords: %s\n",
             mSequenceNumber, mDateCreated, mDateModified, mKeywords);
 }
 
diff --git a/media/mtp/MtpProperty.cpp b/media/mtp/MtpProperty.cpp
index c7a91d6..bbd0237 100644
--- a/media/mtp/MtpProperty.cpp
+++ b/media/mtp/MtpProperty.cpp
@@ -36,10 +36,10 @@
         mEnumLength(0),
         mEnumValues(NULL)
 {
-    mDefaultValue.str = NULL;
-    mCurrentValue.str = NULL;
-    mMinimumValue.str = NULL;
-    mMaximumValue.str = NULL;
+    memset(&mDefaultValue, 0, sizeof(mDefaultValue));
+    memset(&mCurrentValue, 0, sizeof(mCurrentValue));
+    memset(&mMinimumValue, 0, sizeof(mMinimumValue));
+    memset(&mMaximumValue, 0, sizeof(mMaximumValue));
 }
 
 MtpProperty::MtpProperty(MtpPropertyCode propCode,
@@ -66,28 +66,28 @@
     if (defaultValue) {
         switch (type) {
             case MTP_TYPE_INT8:
-                mDefaultValue.i8 = defaultValue;
+                mDefaultValue.u.i8 = defaultValue;
                 break;
             case MTP_TYPE_UINT8:
-                mDefaultValue.u8 = defaultValue;
+                mDefaultValue.u.u8 = defaultValue;
                 break;
             case MTP_TYPE_INT16:
-                mDefaultValue.i16 = defaultValue;
+                mDefaultValue.u.i16 = defaultValue;
                 break;
             case MTP_TYPE_UINT16:
-                mDefaultValue.u16 = defaultValue;
+                mDefaultValue.u.u16 = defaultValue;
                 break;
             case MTP_TYPE_INT32:
-                mDefaultValue.i32 = defaultValue;
+                mDefaultValue.u.i32 = defaultValue;
                 break;
             case MTP_TYPE_UINT32:
-                mDefaultValue.u32 = defaultValue;
+                mDefaultValue.u.u32 = defaultValue;
                 break;
             case MTP_TYPE_INT64:
-                mDefaultValue.i64 = defaultValue;
+                mDefaultValue.u.i64 = defaultValue;
                 break;
             case MTP_TYPE_UINT64:
-                mDefaultValue.u64 = defaultValue;
+                mDefaultValue.u.u64 = defaultValue;
                 break;
             default:
                 LOGE("unknown type %04X in MtpProperty::MtpProperty", type);
@@ -121,6 +121,7 @@
 }
 
 void MtpProperty::read(MtpDataPacket& packet) {
+    bool deviceProp = isDeviceProperty();
 
     mCode = packet.getUInt16();
     mType = packet.getUInt16();
@@ -137,14 +138,16 @@
         case MTP_TYPE_AINT128:
         case MTP_TYPE_AUINT128:
             mDefaultArrayValues = readArrayValues(packet, mDefaultArrayLength);
-            mCurrentArrayValues = readArrayValues(packet, mCurrentArrayLength);
+            if (deviceProp)
+                mCurrentArrayValues = readArrayValues(packet, mCurrentArrayLength);
             break;
         default:
             readValue(packet, mDefaultValue);
-            if (isDeviceProperty())
+            if (deviceProp)
                 readValue(packet, mCurrentValue);
     }
-    mGroupCode = packet.getUInt32();
+    if (!deviceProp)
+        mGroupCode = packet.getUInt32();
     mFormFlag = packet.getUInt8();
 
     if (mFormFlag == kFormRange) {
@@ -160,6 +163,8 @@
 }
 
 void MtpProperty::write(MtpDataPacket& packet) {
+    bool deviceProp = isDeviceProperty();
+
     packet.putUInt16(mCode);
     packet.putUInt16(mType);
     packet.putUInt8(mWriteable ? 1 : 0);
@@ -176,12 +181,17 @@
         case MTP_TYPE_AINT128:
         case MTP_TYPE_AUINT128:
             writeArrayValues(packet, mDefaultArrayValues, mDefaultArrayLength);
+            if (deviceProp)
+                writeArrayValues(packet, mCurrentArrayValues, mCurrentArrayLength);
             break;
         default:
             writeValue(packet, mDefaultValue);
+            if (deviceProp)
+                writeValue(packet, mCurrentValue);
     }
     packet.putUInt32(mGroupCode);
-    packet.putUInt8(mFormFlag);
+    if (!deviceProp)
+        packet.putUInt8(mFormFlag);
     if (mFormFlag == kFormRange) {
             writeValue(packet, mMinimumValue);
             writeValue(packet, mMaximumValue);
@@ -193,6 +203,26 @@
     }
 }
 
+void MtpProperty::setDefaultValue(const uint16_t* string) {
+    free(mDefaultValue.str);
+    if (string) {
+        MtpStringBuffer buffer(string);
+        mDefaultValue.str = strdup(buffer);
+    }
+    else
+        mDefaultValue.str = NULL;
+}
+
+void MtpProperty::setCurrentValue(const uint16_t* string) {
+    free(mCurrentValue.str);
+    if (string) {
+        MtpStringBuffer buffer(string);
+        mCurrentValue.str = strdup(buffer);
+    }
+    else
+        mCurrentValue.str = NULL;
+}
+
 void MtpProperty::print() {
     LOGV("MtpProperty %04X\n", mCode);
     LOGV("    type %04X\n", mType);
@@ -205,43 +235,43 @@
     switch (mType) {
         case MTP_TYPE_INT8:
         case MTP_TYPE_AINT8:
-            value.i8 = packet.getInt8();
+            value.u.i8 = packet.getInt8();
             break;
         case MTP_TYPE_UINT8:
         case MTP_TYPE_AUINT8:
-            value.u8 = packet.getUInt8();
+            value.u.u8 = packet.getUInt8();
             break;
         case MTP_TYPE_INT16:
         case MTP_TYPE_AINT16:
-            value.i16 = packet.getInt16();
+            value.u.i16 = packet.getInt16();
             break;
         case MTP_TYPE_UINT16:
         case MTP_TYPE_AUINT16:
-            value.u16 = packet.getUInt16();
+            value.u.u16 = packet.getUInt16();
             break;
         case MTP_TYPE_INT32:
         case MTP_TYPE_AINT32:
-            value.i32 = packet.getInt32();
+            value.u.i32 = packet.getInt32();
             break;
         case MTP_TYPE_UINT32:
         case MTP_TYPE_AUINT32:
-            value.u32 = packet.getUInt32();
+            value.u.u32 = packet.getUInt32();
             break;
         case MTP_TYPE_INT64:
         case MTP_TYPE_AINT64:
-            value.i64 = packet.getInt64();
+            value.u.i64 = packet.getInt64();
             break;
         case MTP_TYPE_UINT64:
         case MTP_TYPE_AUINT64:
-            value.u64 = packet.getUInt64();
+            value.u.u64 = packet.getUInt64();
             break;
         case MTP_TYPE_INT128:
         case MTP_TYPE_AINT128:
-            packet.getInt128(value.i128);
+            packet.getInt128(value.u.i128);
             break;
         case MTP_TYPE_UINT128:
         case MTP_TYPE_AUINT128:
-            packet.getUInt128(value.u128);
+            packet.getUInt128(value.u.u128);
             break;
         case MTP_TYPE_STR:
             packet.getString(stringBuffer);
@@ -258,43 +288,43 @@
     switch (mType) {
         case MTP_TYPE_INT8:
         case MTP_TYPE_AINT8:
-            packet.putInt8(value.i8);
+            packet.putInt8(value.u.i8);
             break;
         case MTP_TYPE_UINT8:
         case MTP_TYPE_AUINT8:
-            packet.putUInt8(value.u8);
+            packet.putUInt8(value.u.u8);
             break;
         case MTP_TYPE_INT16:
         case MTP_TYPE_AINT16:
-            packet.putInt16(value.i16);
+            packet.putInt16(value.u.i16);
             break;
         case MTP_TYPE_UINT16:
         case MTP_TYPE_AUINT16:
-            packet.putUInt16(value.u16);
+            packet.putUInt16(value.u.u16);
             break;
         case MTP_TYPE_INT32:
         case MTP_TYPE_AINT32:
-            packet.putInt32(value.i32);
+            packet.putInt32(value.u.i32);
             break;
         case MTP_TYPE_UINT32:
         case MTP_TYPE_AUINT32:
-            packet.putUInt32(value.u32);
+            packet.putUInt32(value.u.u32);
             break;
         case MTP_TYPE_INT64:
         case MTP_TYPE_AINT64:
-            packet.putInt64(value.i64);
+            packet.putInt64(value.u.i64);
             break;
         case MTP_TYPE_UINT64:
         case MTP_TYPE_AUINT64:
-            packet.putUInt64(value.u64);
+            packet.putUInt64(value.u.u64);
             break;
         case MTP_TYPE_INT128:
         case MTP_TYPE_AINT128:
-            packet.putInt128(value.i128);
+            packet.putInt128(value.u.i128);
             break;
         case MTP_TYPE_UINT128:
         case MTP_TYPE_AUINT128:
-            packet.putUInt128(value.u128);
+            packet.putUInt128(value.u.u128);
             break;
         case MTP_TYPE_STR:
             if (value.str)
diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h
index 64cfb93..98b465a 100644
--- a/media/mtp/MtpProperty.h
+++ b/media/mtp/MtpProperty.h
@@ -23,6 +23,23 @@
 
 class MtpDataPacket;
 
+struct MtpPropertyValue {
+    union {
+        int8_t          i8;
+        uint8_t         u8;
+        int16_t         i16;
+        uint16_t        u16;
+        int32_t         i32;
+        uint32_t        u32;
+        int64_t         i64;
+        uint64_t        u64;
+        int128_t        i128;
+        uint128_t       u128;
+    } u;
+    // string in UTF8 format
+    char*               str;
+};
+
 class MtpProperty {
 public:
     MtpPropertyCode     mCode;
@@ -68,6 +85,9 @@
     void                read(MtpDataPacket& packet);
     void                write(MtpDataPacket& packet);
 
+    void                setDefaultValue(const uint16_t* string);
+    void                setCurrentValue(const uint16_t* string);
+
     void                print();
 
     inline bool         isDeviceProperty() const {
diff --git a/media/mtp/MtpStringBuffer.cpp b/media/mtp/MtpStringBuffer.cpp
index 8bf6731..fe8cf04 100644
--- a/media/mtp/MtpStringBuffer.cpp
+++ b/media/mtp/MtpStringBuffer.cpp
@@ -37,6 +37,13 @@
     set(src);
 }
 
+MtpStringBuffer::MtpStringBuffer(const uint16_t* src)
+    :   mCharCount(0),
+        mByteCount(1)
+{
+    set(src);
+}
+
 MtpStringBuffer::MtpStringBuffer(const MtpStringBuffer& src)
     :   mCharCount(src.mCharCount),
         mByteCount(src.mByteCount)
@@ -88,6 +95,29 @@
     mCharCount = count;
 }
 
+void MtpStringBuffer::set(const uint16_t* src) {
+    int count = 0;
+    uint16_t ch;
+    uint8_t* dest = mBuffer;
+
+    while ((ch = *src++) != 0 && count < 255) {
+        if (ch >= 0x0800) {
+            *dest++ = (uint8_t)(0xE0 | (ch >> 12));
+            *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F));
+            *dest++ = (uint8_t)(0x80 | (ch & 0x3F));
+        } else if (ch >= 0x80) {
+            *dest++ = (uint8_t)(0xC0 | (ch >> 6));
+            *dest++ = (uint8_t)(0x80 | (ch & 0x3F));
+        } else {
+            *dest++ = ch;
+        }
+        count++;
+    }
+    *dest++ = 0;
+    mCharCount = count;
+    mByteCount = dest - mBuffer;
+}
+
 void MtpStringBuffer::readFromPacket(MtpDataPacket* packet) {
     int count = packet->getUInt8();
     uint8_t* dest = mBuffer;
diff --git a/media/mtp/MtpStringBuffer.h b/media/mtp/MtpStringBuffer.h
index 4641c3f..cbc8307 100644
--- a/media/mtp/MtpStringBuffer.h
+++ b/media/mtp/MtpStringBuffer.h
@@ -27,6 +27,7 @@
 class MtpStringBuffer {
 
 private:
+    // mBuffer contains string in UTF8 format
     // maximum 3 bytes/character, with 1 extra for zero termination
     uint8_t         mBuffer[255 * 3 + 1];
     int             mCharCount;
@@ -35,10 +36,12 @@
 public:
                     MtpStringBuffer();
                     MtpStringBuffer(const char* src);
+                    MtpStringBuffer(const uint16_t* src);
                     MtpStringBuffer(const MtpStringBuffer& src);
     virtual         ~MtpStringBuffer();
 
     void            set(const char* src);
+    void            set(const uint16_t* src);
 
     void            readFromPacket(MtpDataPacket* packet);
     void            writeToPacket(MtpDataPacket* packet) const;
diff --git a/media/mtp/MtpTypes.h b/media/mtp/MtpTypes.h
index 7e3c009..720c854 100644
--- a/media/mtp/MtpTypes.h
+++ b/media/mtp/MtpTypes.h
@@ -43,20 +43,6 @@
 // values 0x00000000 and 0xFFFFFFFF are reserved for special purposes.
 typedef uint32_t MtpObjectHandle;
 
-union MtpPropertyValue {
-    int8_t          i8;
-    uint8_t         u8;
-    int16_t         i16;
-    uint16_t        u16;
-    int32_t         i32;
-    uint32_t        u32;
-    int64_t         i64;
-    uint64_t        u64;
-    int128_t        i128;
-    uint128_t       u128;
-    char*           str;
-};
-
 // Special values
 #define MTP_PARENT_ROOT         0xFFFFFFFF       // parent is root of the storage
 #define kInvalidObjectHandle    0xFFFFFFFF