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
This commit is contained in:
Robert Greenwalt
2012-04-20 13:08:02 -07:00
parent 81394337bc
commit 2a9efc2c6e
2 changed files with 86 additions and 1 deletions

View File

@@ -94,7 +94,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
public boolean handleMessage(Message msg) { public boolean handleMessage(Message msg) {
String event = (String) msg.obj; String event = (String) msg.obj;
try { 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)); log(String.format("Unhandled event '%s'", event));
} }
} catch (Exception e) { } catch (Exception e) {

View File

@@ -16,6 +16,7 @@
package com.android.server; package com.android.server;
import android.util.Slog;
import com.google.android.collect.Lists; import com.google.android.collect.Lists;
import java.util.ArrayList; import java.util.ArrayList;
@@ -32,12 +33,14 @@ public class NativeDaemonEvent {
private final int mCode; private final int mCode;
private final String mMessage; private final String mMessage;
private final String mRawEvent; private final String mRawEvent;
private String[] mParsed;
private NativeDaemonEvent(int cmdNumber, int code, String message, String rawEvent) { private NativeDaemonEvent(int cmdNumber, int code, String message, String rawEvent) {
mCmdNumber = cmdNumber; mCmdNumber = cmdNumber;
mCode = code; mCode = code;
mMessage = message; mMessage = message;
mRawEvent = rawEvent; mRawEvent = rawEvent;
mParsed = null;
} }
public int getCmdNumber() { public int getCmdNumber() {
@@ -166,4 +169,86 @@ public class NativeDaemonEvent {
} }
return result.toArray(new String[result.size()]); 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()]);
}
} }