Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d34b4a8 authored by Robert Greenwalt's avatar Robert Greenwalt
Browse files

Allow quoted strings from NativeDaemonConnector

Previously we'd only handled quoted strings going into NDC.  This
change auto-handles quoted strings in broadcasts and allows
protocol handlers to request de-quoted elements when needed instead
of using the generic split(" ").

bug: 6353048
Change-Id: I8a07be86411063ed1b402294edc399b4cc076da5
parent d7f256dd
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
    public boolean handleMessage(Message msg) {
        String event = (String) msg.obj;
        try {
            if (!mCallbacks.onEvent(msg.what, event, event.split(" "))) {
            if (!mCallbacks.onEvent(msg.what, event, NativeDaemonEvent.unescapeArgs(event))) {
                log(String.format("Unhandled event '%s'", event));
            }
        } catch (Exception e) {
+85 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server;

import android.util.Slog;
import com.google.android.collect.Lists;

import java.util.ArrayList;
@@ -32,12 +33,14 @@ public class NativeDaemonEvent {
    private final int mCode;
    private final String mMessage;
    private final String mRawEvent;
    private String[] mParsed;

    private NativeDaemonEvent(int cmdNumber, int code, String message, String rawEvent) {
        mCmdNumber = cmdNumber;
        mCode = code;
        mMessage = message;
        mRawEvent = rawEvent;
        mParsed = null;
    }

    public int getCmdNumber() {
@@ -166,4 +169,86 @@ public class NativeDaemonEvent {
        }
        return result.toArray(new String[result.size()]);
    }

    /**
     * Find the Nth field of the event.
     *
     * This ignores and code or cmdNum, the first return value is given for N=0.
     * Also understands "\"quoted\" multiword responses" and tries them as a single field
     */
    public String getField(int n) {
        if (mParsed == null) {
            mParsed = unescapeArgs(mRawEvent);
        }
        n += 2; // skip code and command#
        if (n > mParsed.length) return null;
            return mParsed[n];
        }

    public static String[] unescapeArgs(String rawEvent) {
        final boolean DEBUG_ROUTINE = false;
        final String LOGTAG = "unescapeArgs";
        final ArrayList<String> parsed = new ArrayList<String>();
        final int length = rawEvent.length();
        int current = 0;
        int wordEnd = -1;
        boolean quoted = false;

        if (DEBUG_ROUTINE) Slog.e(LOGTAG, "parsing '" + rawEvent + "'");
        if (rawEvent.charAt(current) == '\"') {
            quoted = true;
            current++;
        }
        while (current < length) {
            // find the end of the word
            if (quoted) {
                wordEnd = current;
                while ((wordEnd = rawEvent.indexOf('\"', wordEnd)) != -1) {
                    if (rawEvent.charAt(wordEnd - 1) != '\\') {
                        break;
                    } else {
                        wordEnd++; // skip this escaped quote and keep looking
                    }
                }
            } else {
                wordEnd = rawEvent.indexOf(' ', current);
            }
            // if we didn't find the end-o-word token, take the rest of the string
            if (wordEnd == -1) wordEnd = length;
            String word = rawEvent.substring(current, wordEnd);
            current += word.length();
            if (!quoted) {
                word = word.trim();
            } else {
                current++;  // skip the trailing quote
            }
            // unescape stuff within the word
            word.replace("\\\\", "\\");
            word.replace("\\\"", "\"");

            if (DEBUG_ROUTINE) Slog.e(LOGTAG, "found '" + word + "'");
            parsed.add(word);

            // find the beginning of the next word - either of these options
            int nextSpace = rawEvent.indexOf(' ', current);
            int nextQuote = rawEvent.indexOf(" \"", current);
            if (DEBUG_ROUTINE) {
                Slog.e(LOGTAG, "nextSpace=" + nextSpace + ", nextQuote=" + nextQuote);
            }
            if (nextQuote > -1 && nextQuote <= nextSpace) {
                quoted = true;
                current = nextQuote + 2;
            } else {
                quoted = false;
                if (nextSpace > -1) {
                    current = nextSpace + 1;
                }
            } // else we just start the next word after the current and read til the end
            if (DEBUG_ROUTINE) {
                Slog.e(LOGTAG, "next loop - current=" + current +
                        ", length=" + length + ", quoted=" + quoted);
            }
        }
        return parsed.toArray(new String[parsed.size()]);
    }
}