Merge "Notification updates."
diff --git a/media/jni/android_media_MtpCursor.cpp b/media/jni/android_media_MtpCursor.cpp
index 6a65ffd..7a0ae8a 100644
--- a/media/jni/android_media_MtpCursor.cpp
+++ b/media/jni/android_media_MtpCursor.cpp
@@ -52,7 +52,7 @@
         jint queryType, jint deviceID, jlong storageID, jlong objectID, jintArray javaColumns)
 {
 #ifdef HAVE_ANDROID_OS
-    LOGD("android_media_MtpCursor_setup queryType: %d deviceID: %d storageID: %d objectID: %d\n",
+    LOGD("android_media_MtpCursor_setup queryType: %d deviceID: %d storageID: %lld objectID: %lld\n",
                 queryType, deviceID, storageID, objectID);
 
     int* columns = NULL;
diff --git a/media/jni/android_media_MtpDatabase.cpp b/media/jni/android_media_MtpDatabase.cpp
index 227ee92..b5f4856 100644
--- a/media/jni/android_media_MtpDatabase.cpp
+++ b/media/jni/android_media_MtpDatabase.cpp
@@ -456,7 +456,6 @@
 
 MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
                                             MtpDataPacket& packet) {
-
     int         type;
 
     if (!getDevicePropertyInfo(property, type))
@@ -782,10 +781,25 @@
     switch (property) {
         case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
         case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
+        {
             // writeable string properties
             result = new MtpProperty(property, MTP_TYPE_STR, true);
-            // FIXME - set current value here!
+
+            // set current value
+            JNIEnv* env = AndroidRuntime::getJNIEnv();
+            jint ret = env->CallIntMethod(mDatabase, method_getDeviceProperty,
+                        (jint)property, mLongBuffer, mStringBuffer);
+            if (ret == MTP_RESPONSE_OK) {
+                jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
+                result->setCurrentValue(str);
+                env->ReleaseCharArrayElements(mStringBuffer, str, 0);
+            } else {
+                LOGE("unable to read device property, response: %04X", ret);
+            }
+
+            checkAndClearExceptionFromCallback(env, __FUNCTION__);
             break;
+        }
     }
 
     return result;
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
diff --git a/media/tests/mtp/mtp.cpp b/media/tests/mtp/mtp.cpp
index 2c5e23b..3202cae 100644
--- a/media/tests/mtp/mtp.cpp
+++ b/media/tests/mtp/mtp.cpp
@@ -321,7 +321,7 @@
         buffer[0] = 0;
         fgets(buffer, sizeof(buffer), stdin);
         int count = strlen(buffer);
-        if (count > 0 && buffer[0] == EOF) {
+        if (count > 0 && buffer[0] == (char)EOF) {
             printf("\n");
             exit(0);
         }