// Path: src/com/android/ddmlib/MultiLineReceiver.java
// public abstract class MultiLineReceiver implements IShellOutputReceiver {
// 
//     private boolean mTrimLines = true;
// 
//     /** unfinished message line, stored for next packet */
//     private String mUnfinishedLine = null;
// 
//     private final ArrayList<String> mArray = new ArrayList<String>();
// 
//     /**
//      * Set the trim lines flag.
//      * @param trim hether the lines are trimmed, or not.
//      */
//     public void setTrimLine(boolean trim) {
//         mTrimLines = trim;
//     }
// 
//     /* (non-Javadoc)
//      * @see com.android.ddmlib.adb.IShellOutputReceiver#addOutput(
//      *      byte[], int, int)
//      */
//     @Override
//     public final void addOutput(byte[] data, int offset, int length) {
//         if (isCancelled() == false) {
//             String s = null;
//             try {
//                 s = new String(data, offset, length, "UTF-8"); //$NON-NLS-1$
//             } catch (UnsupportedEncodingException e) {
//                 // normal encoding didn't work, try the default one
//                 e.printStackTrace();
//                 s = new String(data, offset,length);
//             }
// 
//             // ok we've got a string
//             if (s != null) {
//                 // if we had an unfinished line we add it.
//                 if (mUnfinishedLine != null) {
//                     s = mUnfinishedLine + s;
//                     mUnfinishedLine = null;
//                 }
// 
//                 // now we split the lines
//                 mArray.clear();
//                 int start = 0;
//                 do {
//                     int index = s.indexOf("\r\n", start); //$NON-NLS-1$
// 
//                     // if \r\n was not found, this is an unfinished line
//                     // and we store it to be processed for the next packet
//                     if (index == -1) {
//                         mUnfinishedLine = s.substring(start);
//                         break;
//                     }
// 
//                     // so we found a \r\n;
//                     // extract the line
//                     String line = s.substring(start, index);
//                     if (mTrimLines) {
//                         line = line.trim();
//                     }
//                     mArray.add(line);
// 
//                     // move start to after the \r\n we found
//                     start = index + 2;
//                 } while (true);
// 
//                 if (mArray.size() > 0) {
//                     // at this point we've split all the lines.
//                     // make the array
//                     String[] lines = mArray.toArray(new String[mArray.size()]);
// 
//                     // send it for final processing
//                     processNewLines(lines);
//                 }
//             }
//         }
//     }
// 
//     /* (non-Javadoc)
//      * @see com.android.ddmlib.adb.IShellOutputReceiver#flush()
//      */
//     @Override
//     public final void flush() {
//         if (mUnfinishedLine != null) {
//             processNewLines(new String[] { mUnfinishedLine });
//         }
// 
//         done();
//     }
// 
//     /**
//      * Terminates the process. This is called after the last lines have been through
//      * {@link #processNewLines(String[])}.
//      */
//     public void done() {
//         // do nothing.
//     }
// 
//     /**
//      * Called when new lines are being received by the remote process.
//      * <p/>It is guaranteed that the lines are complete when they are given to this method.
//      * @param lines The array containing the new lines.
//      */
//     public abstract void processNewLines(String[] lines);
// }


import com.android.ddmlib.IShellOutputReceiver;
import com.android.ddmlib.Log;
import com.android.ddmlib.MultiLineReceiver;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
        for (String line : lines) {
            parse(line);
            // in verbose mode, dump all adb output to log
            Log.v(LOG_TAG, line);
        }
    }

    /**
     * Parse an individual output line. Expects a line that is one of:
     * <ul>
     * <li>
     * The start of a new status line (starts with Prefixes.STATUS or Prefixes.STATUS_CODE),
     * and thus there is a new key=value pair to parse, and the previous key-value pair is
     * finished.
     * </li>
     * <li>
     * A continuation of the previous status (the "value" portion of the key has wrapped
     * to the next line).
     * </li>
     * <li> A line reporting a fatal error in the test run (Prefixes.STATUS_FAILED) </li>
     * <li> A line reporting the total elapsed time of the test run. (Prefixes.TIME_REPORT) </li>
     * </ul>
     *
     * @param line  Text output line
     */
    private void parse(String line) {
        if (line.startsWith(Prefixes.STATUS_CODE)) {
            // Previous status key-value has been collected. Store it.
            submitCurrentKeyValue();
            mInInstrumentationResultKey = false;
// Path: src/com/android/ddmlib/MultiLineReceiver.java
// public abstract class MultiLineReceiver implements IShellOutputReceiver {
// 
//     private boolean mTrimLines = true;
// 
//     /** unfinished message line, stored for next packet */
//     private String mUnfinishedLine = null;
// 
//     private final ArrayList<String> mArray = new ArrayList<String>();
// 
//     /**
//      * Set the trim lines flag.
//      * @param trim hether the lines are trimmed, or not.
//      */
//     public void setTrimLine(boolean trim) {
//         mTrimLines = trim;
//     }
// 
//     /* (non-Javadoc)
//      * @see com.android.ddmlib.adb.IShellOutputReceiver#addOutput(
//      *      byte[], int, int)
//      */
//     @Override
//     public final void addOutput(byte[] data, int offset, int length) {
//         if (isCancelled() == false) {
//             String s = null;
//             try {
//                 s = new String(data, offset, length, "UTF-8"); //$NON-NLS-1$
//             } catch (UnsupportedEncodingException e) {
//                 // normal encoding didn't work, try the default one
//                 e.printStackTrace();
//                 s = new String(data, offset,length);
//             }
// 
//             // ok we've got a string
//             if (s != null) {
//                 // if we had an unfinished line we add it.
//                 if (mUnfinishedLine != null) {
//                     s = mUnfinishedLine + s;
//                     mUnfinishedLine = null;
//                 }
// 
//                 // now we split the lines
//                 mArray.clear();
//                 int start = 0;
//                 do {
//                     int index = s.indexOf("\r\n", start); //$NON-NLS-1$
// 
//                     // if \r\n was not found, this is an unfinished line
//                     // and we store it to be processed for the next packet
//                     if (index == -1) {
//                         mUnfinishedLine = s.substring(start);
//                         break;
//                     }
// 
//                     // so we found a \r\n;
//                     // extract the line
//                     String line = s.substring(start, index);
//                     if (mTrimLines) {
//                         line = line.trim();
//                     }
//                     mArray.add(line);
// 
//                     // move start to after the \r\n we found
//                     start = index + 2;
//                 } while (true);
// 
//                 if (mArray.size() > 0) {
//                     // at this point we've split all the lines.
//                     // make the array
//                     String[] lines = mArray.toArray(new String[mArray.size()]);
// 
//                     // send it for final processing
//                     processNewLines(lines);
//                 }
//             }
//         }
//     }
// 
//     /* (non-Javadoc)
//      * @see com.android.ddmlib.adb.IShellOutputReceiver#flush()
//      */
//     @Override
//     public final void flush() {
//         if (mUnfinishedLine != null) {
//             processNewLines(new String[] { mUnfinishedLine });
//         }
// 
//         done();
//     }
// 
//     /**
//      * Terminates the process. This is called after the last lines have been through
//      * {@link #processNewLines(String[])}.
//      */
//     public void done() {
//         // do nothing.
//     }
// 
//     /**
//      * Called when new lines are being received by the remote process.
//      * <p/>It is guaranteed that the lines are complete when they are given to this method.
//      * @param lines The array containing the new lines.
//      */
//     public abstract void processNewLines(String[] lines);
// }


// Path: src/com/android/ddmlib/testrunner/InstrumentationResultParser.java
import com.android.ddmlib.IShellOutputReceiver;
import com.android.ddmlib.Log;
import com.android.ddmlib.MultiLineReceiver;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

        for (String line : lines) {
            parse(line);
            // in verbose mode, dump all adb output to log
            Log.v(LOG_TAG, line);
        }
    }

    /**
     * Parse an individual output line. Expects a line that is one of:
     * <ul>
     * <li>
     * The start of a new status line (starts with Prefixes.STATUS or Prefixes.STATUS_CODE),
     * and thus there is a new key=value pair to parse, and the previous key-value pair is
     * finished.
     * </li>
     * <li>
     * A continuation of the previous status (the "value" portion of the key has wrapped
     * to the next line).
     * </li>
     * <li> A line reporting a fatal error in the test run (Prefixes.STATUS_FAILED) </li>
     * <li> A line reporting the total elapsed time of the test run. (Prefixes.TIME_REPORT) </li>
     * </ul>
     *
     * @param line  Text output line
     */
    private void parse(String line) {
        if (line.startsWith(Prefixes.STATUS_CODE)) {
            // Previous status key-value has been collected. Store it.
            submitCurrentKeyValue();
            mInInstrumentationResultKey = false;
            parseStatusCode(line);