change AudioTrack mode to MUSIC & add details to report

- mobile phones activates the Receiver speaker for VOICE_CALL mode
- this can pull additional processing, but the test should test the
  loud speaker.
- added details to report to collect save results
- changed buffering of FileUtil to accomodate longer message

Change-Id: Ifdbb9fbfcf80c630c8952599b7e65eb909735a94
diff --git a/suite/audio_quality/Android.mk b/suite/audio_quality/Android.mk
index 2078606..21d8fb8 100644
--- a/suite/audio_quality/Android.mk
+++ b/suite/audio_quality/Android.mk
@@ -35,7 +35,12 @@
 	$(hide) cd $(HOST_OUT)/cts-audio-quality && \
         zip -rq android-cts-audio-quality.zip android-cts-audio-quality -x android-cts-audio-quality/reports/\*
 
+# target to build only this package
+.PHONY: cts_audio_quality_package
+cts_audio_quality_package: $(CTS_AUDIO_QUALITY_ZIP)
+
 cts: $(CTS_AUDIO_QUALITY_ZIP)
+
 ifneq ($(filter cts, $(MAKECMDGOALS)),)
 $(call dist-for-goals, cts, $(CTS_AUDIO_QUALITY_ZIP))
 endif # cts
diff --git a/suite/audio_quality/client/src/com/android/cts/audiotest/AudioProtocol.java b/suite/audio_quality/client/src/com/android/cts/audiotest/AudioProtocol.java
index d3ace8b..3c45a8a 100644
--- a/suite/audio_quality/client/src/com/android/cts/audiotest/AudioProtocol.java
+++ b/suite/audio_quality/client/src/com/android/cts/audiotest/AudioProtocol.java
@@ -256,8 +256,9 @@
                         mPlayback.release();
                         mPlayback = null;
                     }
-                    int type = (mode == 0) ? AudioManager.STREAM_VOICE_CALL :
-                        AudioManager.STREAM_MUSIC;
+                    // STREAM_VOICE_CALL activates different speaker.
+                    // use MUSIC mode to activate the louder speaker.
+                    int type = AudioManager.STREAM_MUSIC;
                     int bufferSize = AudioTrack.getMinBufferSize(samplingRate,
                             stereo ? AudioFormat.CHANNEL_OUT_STEREO : AudioFormat.CHANNEL_OUT_MONO,
                             AudioFormat.ENCODING_PCM_16BIT);
diff --git a/suite/audio_quality/lib/include/FileUtil.h b/suite/audio_quality/lib/include/FileUtil.h
index e5fa886..df10c54 100644
--- a/suite/audio_quality/lib/include/FileUtil.h
+++ b/suite/audio_quality/lib/include/FileUtil.h
@@ -55,9 +55,10 @@
     // store dirPath to prevent creating multiple times
     static android::String8 mDirPath;
     std::ofstream mFile;
-    static const int BUFFER_SIZE = 1024;
+    static const int DEFAULT_BUFFER_SIZE = 1024;
     // buffer for printf. one line longer than this will be truncated.
-    char mBuffer[BUFFER_SIZE];
+    char* mBuffer;
+    int mBufferSize;
     android::Mutex mWriteLock;
 };
 
diff --git a/suite/audio_quality/lib/include/Report.h b/suite/audio_quality/lib/include/Report.h
index 248f4b9..e10899f 100644
--- a/suite/audio_quality/lib/include/Report.h
+++ b/suite/audio_quality/lib/include/Report.h
@@ -18,9 +18,12 @@
 #define CTSAUDIO_REPORT_H
 
 #include <list>
+#include <map>
 
 #include <utils/String8.h>
 #include "FileUtil.h"
+
+class TaskCase;
 /**
  * Class to generate report
  */
@@ -35,8 +38,8 @@
     // should be called before finishing to flush the report to file system
     static void Finalize();
 
-    void addCasePassed(const android::String8& name);
-    void addCaseFailed(const android::String8& name);
+    void addCasePassed(const TaskCase* task);
+    void addCaseFailed(const TaskCase* task);
 
 
 private:
@@ -45,11 +48,14 @@
     bool init(const char* dirName);
     void writeReport();
     void printf(const char* fmt, ...);
+    typedef std::pair<android::String8, android::String8> StringPair;
+    void writeResult(std::list<StringPair>::const_iterator begin,
+            std::list<StringPair>::const_iterator end, bool passed);
 
 private:
     static Report* mInstance;
-    std::list<android::String8> mPassedCases;
-    std::list<android::String8> mFailedCases;
+    std::list<StringPair> mPassedCases;
+    std::list<StringPair> mFailedCases;
 };
 
 
diff --git a/suite/audio_quality/lib/include/task/TaskCase.h b/suite/audio_quality/lib/include/task/TaskCase.h
index 323119c..4e20829 100644
--- a/suite/audio_quality/lib/include/task/TaskCase.h
+++ b/suite/audio_quality/lib/include/task/TaskCase.h
@@ -38,7 +38,7 @@
     virtual bool addChild(TaskGeneric* child);
     virtual TaskGeneric::ExecutionResult run();
 
-    bool getCaseName(android::String8& name);
+    bool getCaseName(android::String8& name) const;
 
     bool registerBuffer(const android::String8& name, android::sp<Buffer>& buffer);
     // update already existing buffer. Actually the old buffer will be deleted.
@@ -62,7 +62,7 @@
         inline Value(double val): mType(ETypeDouble) {
             setDouble(val);
         };
-        inline Value(int64_t val): mType(ETypeI64){
+        inline Value(int64_t val): mType(ETypeI64) {
             setInt64(val);
         };
         inline Type getType() {
@@ -123,6 +123,8 @@
      */
     bool translateVarName(const android::String8& orig, android::String8& translated);
 
+    void setDetails(android::String8 details);
+    const android::String8& getDetails() const;
 private:
     void releaseRemoteAudio();
 
@@ -131,6 +133,7 @@
     std::map<android::String8, int> mIndexList;
     std::map<android::String8, Value> mValueList;
     ClientInterface* mClient;
+    android::String8 mDetails;
 };
 
 
diff --git a/suite/audio_quality/lib/include/task/TaskGeneric.h b/suite/audio_quality/lib/include/task/TaskGeneric.h
index fe5215d..6f60bcf 100644
--- a/suite/audio_quality/lib/include/task/TaskGeneric.h
+++ b/suite/audio_quality/lib/include/task/TaskGeneric.h
@@ -99,7 +99,7 @@
     /// keys array should end with NULL
     void registerSupportedStringAttributes(const android::String8* keys[]);
     bool addStringAttribute(const android::String8& key, const android::String8& value);
-    bool findStringAttribute(const android::String8& key, android::String8& value);
+    bool findStringAttribute(const android::String8& key, android::String8& value) const;
     inline std::list<TaskGeneric*>& getChildren() {
         return mChildren;
     };
diff --git a/suite/audio_quality/lib/src/FileUtil.cpp b/suite/audio_quality/lib/src/FileUtil.cpp
index 8c8ea7e..dffc394 100644
--- a/suite/audio_quality/lib/src/FileUtil.cpp
+++ b/suite/audio_quality/lib/src/FileUtil.cpp
@@ -78,7 +78,12 @@
 
 FileUtil::FileUtil()
 {
-
+    mBuffer = new char[DEFAULT_BUFFER_SIZE];
+    if (mBuffer == NULL) {
+        // cannot use ASSERT here, just crash
+        *(char*)0 = 0;
+    }
+    mBufferSize = DEFAULT_BUFFER_SIZE;
 }
 
 FileUtil::~FileUtil()
@@ -86,6 +91,7 @@
     if (mFile.is_open()) {
         mFile.close();
     }
+    delete[] mBuffer;
 }
 
 bool FileUtil::init(const char* fileName)
@@ -101,34 +107,48 @@
     return true;
 }
 
-bool FileUtil::doVprintf(bool fileOnly, int loglevel, const char *fmt, va_list ap)
+bool FileUtil::doVprintf(bool fileOnly, int logLevel, const char *fmt, va_list ap)
 {
     // prevent messed up log in multi-thread env. Still multi-line logs can be messed up.
     android::Mutex::Autolock lock(mWriteLock);
-    int start = 0;
-    if (loglevel != -1) {
-        mBuffer[0] = '0' + loglevel;
-        mBuffer[1] = '>';
-        start = 2;
-    }
-    int size;
-    size = vsnprintf(mBuffer + start, BUFFER_SIZE - start - 2, fmt, ap); // 2 for \n\0
-    if (size < 0) {
-        fprintf(stderr, "FileUtil::vprintf failed");
-        return false;
-    }
-    size += start;
-    mBuffer[size] = '\n';
-    size++;
-    mBuffer[size] = 0;
+    while (1) {
+        int start = 0;
+        if (logLevel != -1) {
+            mBuffer[0] = '0' + logLevel;
+            mBuffer[1] = '>';
+            start = 2;
+        }
+        int size;
+        size = vsnprintf(mBuffer + start, mBufferSize - start - 2, fmt, ap); // 2 for \n\0
+        if (size < 0) {
+            fprintf(stderr, "FileUtil::vprintf failed");
+            return false;
+        }
+        if ((size + start + 2) > mBufferSize) {
+            //default buffer does not fit, increase buffer size and retry
+            delete[] mBuffer;
+            mBuffer = new char[2 * size];
+            if (mBuffer == NULL) {
+                // cannot use ASSERT here, just crash
+                *(char*)0 = 0;
+            }
+            mBufferSize = 2 * size;
+            // re-try
+            continue;
+        }
+        size += start;
+        mBuffer[size] = '\n';
+        size++;
+        mBuffer[size] = 0;
 
-    if (!fileOnly) {
-        fprintf(stdout, "%s", mBuffer);
+        if (!fileOnly) {
+            fprintf(stdout, "%s", mBuffer);
+        }
+        if (mFile.is_open()) {
+            mFile<<mBuffer;
+        }
+        return true;
     }
-    if (mFile.is_open()) {
-        mFile<<mBuffer;
-    }
-    return true;
 }
 
 bool FileUtil::doPrintf(const char* fmt, ...)
diff --git a/suite/audio_quality/lib/src/Report.cpp b/suite/audio_quality/lib/src/Report.cpp
index e6a248c..e47f3aa 100644
--- a/suite/audio_quality/lib/src/Report.cpp
+++ b/suite/audio_quality/lib/src/Report.cpp
@@ -18,6 +18,7 @@
 #include "Settings.h"
 #include "StringUtil.h"
 #include "Report.h"
+#include "task/TaskCase.h"
 
 
 Report* Report::mInstance = NULL;
@@ -45,6 +46,8 @@
 Report::~Report()
 {
     writeReport();
+    mFailedCases.clear();
+    mPassedCases.clear();
 }
 
 bool Report::init(const char* dirName)
@@ -68,14 +71,36 @@
     va_end(ap);
 }
 
-void Report::addCasePassed(const android::String8& name)
+void Report::addCasePassed(const TaskCase* task)
 {
-    mPassedCases.push_back(name);
+    android::String8 name(" ");
+    task->getCaseName(name);
+    StringPair pair(name, task->getDetails());
+    mPassedCases.push_back(pair);
 }
 
-void Report::addCaseFailed(const android::String8& name)
+void Report::addCaseFailed(const TaskCase* task)
 {
-    mFailedCases.push_back(name);
+    android::String8 name(" ");
+    task->getCaseName(name);
+    StringPair pair(name, task->getDetails());
+    mFailedCases.push_back(pair);
+}
+
+void Report::writeResult(std::list<StringPair>::const_iterator begin,
+        std::list<StringPair>::const_iterator end, bool passed)
+{
+    std::list<StringPair>::const_iterator it;
+    for (it = begin; it != end; it++) {
+        if (passed) {
+            printf("    <test title=\"%s\" result=\"pass\" >", it->first.string());
+        } else {
+            printf("    <test title=\"%s\" result=\"fail\" >", it->first.string());
+        }
+        printf("        <details>\n%s", it->second.string());
+        printf("        </details>");
+        printf("    </test>");
+    }
 }
 
 void Report::writeReport()
@@ -89,13 +114,10 @@
     printf("  </device-info>");
     printf("  <audio-test-results xml=\"%s\">",
             Settings::Instance()->getSetting(Settings::ETEST_XML).string());
-    std::list<android::String8>::iterator it;
-    for (it = mFailedCases.begin(); it != mFailedCases.end(); it++) {
-        printf("    <test title=\"%s\" result=\"fail\" />", it->string());
-    }
-    for (it = mPassedCases.begin(); it != mPassedCases.end(); it++) {
-        printf("    <test title=\"%s\" result=\"pass\" />", it->string());
-    }
+
+    writeResult(mFailedCases.begin(), mFailedCases.end(), false);
+    writeResult(mPassedCases.begin(), mPassedCases.end(), true);
+
     printf("  </audio-test-results>");
     printf("</audio-test-results-report>");
 }
diff --git a/suite/audio_quality/lib/src/SignalProcessingImpl.cpp b/suite/audio_quality/lib/src/SignalProcessingImpl.cpp
index fed9866..21f9702 100644
--- a/suite/audio_quality/lib/src/SignalProcessingImpl.cpp
+++ b/suite/audio_quality/lib/src/SignalProcessingImpl.cpp
@@ -138,7 +138,7 @@
                 LOGE("send failed");
                 return TaskGeneric::EResultError;
             }
-            LOGD("%d-th param buffer %d, stereo:%d", dataLen, (*buffer)->isStereo());
+            LOGD("%d-th param buffer %d, stereo:%d", i, dataLen, (*buffer)->isStereo());
         } else { //TaskCase::Value*
             TaskCase::Value* val = reinterpret_cast<TaskCase::Value*>(inputs[i]);
             bool isI64 = (val->getType() == TaskCase::Value::ETypeI64);
diff --git a/suite/audio_quality/lib/src/task/TaskCase.cpp b/suite/audio_quality/lib/src/task/TaskCase.cpp
index c92e71b..5f9de97 100644
--- a/suite/audio_quality/lib/src/task/TaskCase.cpp
+++ b/suite/audio_quality/lib/src/task/TaskCase.cpp
@@ -44,7 +44,7 @@
     delete mClient;
 }
 
-bool TaskCase::getCaseName(android::String8& name)
+bool TaskCase::getCaseName(android::String8& name) const
 {
     if (!findStringAttribute(STR_NAME, name)) {
         LOGW("TaskCase no name");
@@ -292,6 +292,17 @@
     mClient = NULL;
 }
 
+void TaskCase::setDetails(android::String8 details)
+{
+    mDetails = details;
+}
+
+const android::String8& TaskCase::getDetails() const
+{
+    return mDetails;
+}
+
+
 TaskGeneric::ExecutionResult TaskCase::run()
 {
     android::String8 name;
@@ -335,17 +346,16 @@
     if (testPassed) {
         result = TaskGeneric::EResultPass;
         MSG("== Case %s Passed ==", name.string());
-        Report::Instance()->addCasePassed(name);
+        Report::Instance()->addCasePassed(this);
     } else {
         if (resultAction != TaskGeneric::EResultOK) {
             result = resultAction;
         }
         MSG("== Case %s Failed ==", name.string());
-        Report::Instance()->addCaseFailed(name);
+        Report::Instance()->addCaseFailed(this);
     }
     // release remote audio for other cases to use
     releaseRemoteAudio();
     return result;
 }
 
-
diff --git a/suite/audio_quality/lib/src/task/TaskGeneric.cpp b/suite/audio_quality/lib/src/task/TaskGeneric.cpp
index 7abd137..c0e4935 100644
--- a/suite/audio_quality/lib/src/task/TaskGeneric.cpp
+++ b/suite/audio_quality/lib/src/task/TaskGeneric.cpp
@@ -132,9 +132,9 @@
     return true;
 }
 
-bool TaskGeneric::findStringAttribute(const android::String8& key, android::String8& value)
+bool TaskGeneric::findStringAttribute(const android::String8& key, android::String8& value) const
 {
-    std::map<android::String8, android::String8>::iterator it = mStringAttributes.find(key);
+    std::map<android::String8, android::String8>::const_iterator it = mStringAttributes.find(key);
     if (it == mStringAttributes.end()) {
         return false; // not found
     }
diff --git a/suite/audio_quality/lib/src/task/TaskSave.cpp b/suite/audio_quality/lib/src/task/TaskSave.cpp
index 8938c1e..156e554 100644
--- a/suite/audio_quality/lib/src/task/TaskSave.cpp
+++ b/suite/audio_quality/lib/src/task/TaskSave.cpp
@@ -111,6 +111,7 @@
         return false;
     }
     MSG("=== Values stored ===");
+    android::String8 details;
     for (size_t i = 0; i < listp->size(); i++) {
         UniquePtr<std::list<TaskCase::ValuePair> > values(
                 getTestCase()->findAllValues((*listp)[i]));
@@ -121,14 +122,17 @@
         }
         std::list<TaskCase::ValuePair>::iterator it = values->begin();
         std::list<TaskCase::ValuePair>::iterator end = values->end();
+
         for (; it != end; it++) {
             if (it->second.getType() == TaskCase::Value::ETypeDouble) {
-                MSG("   %s: %f", it->first.string(), it->second.getDouble());
+                details.appendFormat("   %s: %f\n", it->first.string(), it->second.getDouble());
             } else { //64bit int
-                MSG("   %s: %lld", it->first.string(), it->second.getInt64());
+                details.appendFormat("   %s: %lld\n", it->first.string(), it->second.getInt64());
             }
         }
+        MSG("%s", details.string());
     }
+    getTestCase()->setDetails(details);
     return true;
 }